Skip to content

Module arti.types.numpy

None

None

View Source
from __future__ import annotations

from functools import partial

from typing import Any, cast

import numpy as np

import arti.types

from arti.types import (

    Binary,

    Boolean,

    List,

    String,

    Type,

    TypeAdapter,

    TypeSystem,

    _ScalarClassTypeAdapter,

)

# NOTE: TypeAdapters for some types may still be missing. Please open an issue or PR if you find

# anything missing.

#

# TODO: Handle compound/structured dtypes and recarray

# - This page will likely be helpful: https://numpy.org/doc/stable/reference/arrays.dtypes.html#arrays-dtypes

numpy_type_system = TypeSystem(key="numpy")

class _NumpyScalarTypeAdapter(_ScalarClassTypeAdapter):

    @classmethod

    def matches_system(cls, type_: Any, *, hints: dict[str, Any]) -> bool:

        if isinstance(type_, np.ndarray):

            return False

        # NOTE: this works for both direct type and np.dtype comparison, eg:

        # - np.bool_ == np.bool_

        # - np.dtype("bool") == np.bool_

        return cast(bool, type_ == cls.system)

_generate = partial(_NumpyScalarTypeAdapter.generate, type_system=numpy_type_system)

_generate(artigraph=Binary, system=np.bytes_)

_generate(artigraph=Boolean, system=np.bool_)

_generate(artigraph=String, system=np.str_)

for _precision in (16, 32, 64):

    _generate(

        artigraph=getattr(arti.types, f"Float{_precision}"),

        system=getattr(np, f"float{_precision}"),

        priority=_precision,

    )

for _precision in (8, 16, 32, 64):

    _generate(

        artigraph=getattr(arti.types, f"Int{_precision}"),

        system=getattr(np, f"int{_precision}"),

        priority=_precision,

    )

    _generate(

        artigraph=getattr(arti.types, f"UInt{_precision}"),

        system=getattr(np, f"uint{_precision}"),

        priority=_precision,

    )

@numpy_type_system.register_adapter

class ArrayAdapter(TypeAdapter):

    artigraph = List

    system = np.ndarray

    # NOTE: np.ndarray now supports TypeVars, eg: `np.ndarray[Any, np.dtype[np.float64]]`

    #

    # We may consider supporting that form in addition to an empty value, but it doesn't yet support

    # specifying the shape/ndim.

    @classmethod

    def to_artigraph(

        cls, type_: np.ndarray[Any, Any], *, hints: dict[str, Any], type_system: TypeSystem

    ) -> Type:

        value = type_[0] if isinstance(type_[0], np.ndarray) else type(type_[0])

        return cls.artigraph(element=type_system.to_artigraph(value, hints=hints))

    @classmethod

    def matches_system(cls, type_: Any, *, hints: dict[str, Any]) -> bool:

        return isinstance(type_, np.ndarray)

    @classmethod

    def to_system(

        cls, type_: Type, *, hints: dict[str, Any], type_system: TypeSystem

    ) -> np.ndarray[Any, Any]:

        assert isinstance(type_, List)

        element_type = type_system.to_system(type_.element, hints=hints)

        # scalar numpy dtypes can be instantiated to return a zero value, like the python types

        value = element_type if isinstance(element_type, np.ndarray) else element_type()

        return np.array([value])

Variables

numpy_type_system

Classes

ArrayAdapter

class ArrayAdapter(
    /,
    *args,
    **kwargs
)
View Source
@numpy_type_system.register_adapter

class ArrayAdapter(TypeAdapter):

    artigraph = List

    system = np.ndarray

    # NOTE: np.ndarray now supports TypeVars, eg: `np.ndarray[Any, np.dtype[np.float64]]`

    #

    # We may consider supporting that form in addition to an empty value, but it doesn't yet support

    # specifying the shape/ndim.

    @classmethod

    def to_artigraph(

        cls, type_: np.ndarray[Any, Any], *, hints: dict[str, Any], type_system: TypeSystem

    ) -> Type:

        value = type_[0] if isinstance(type_[0], np.ndarray) else type(type_[0])

        return cls.artigraph(element=type_system.to_artigraph(value, hints=hints))

    @classmethod

    def matches_system(cls, type_: Any, *, hints: dict[str, Any]) -> bool:

        return isinstance(type_, np.ndarray)

    @classmethod

    def to_system(

        cls, type_: Type, *, hints: dict[str, Any], type_system: TypeSystem

    ) -> np.ndarray[Any, Any]:

        assert isinstance(type_, List)

        element_type = type_system.to_system(type_.element, hints=hints)

        # scalar numpy dtypes can be instantiated to return a zero value, like the python types

        value = element_type if isinstance(element_type, np.ndarray) else element_type()

        return np.array([value])

Ancestors (in MRO)

  • arti.types.TypeAdapter

Class variables

artigraph
key
priority
system

Static methods

matches_artigraph

def matches_artigraph(
    type_: 'Type',
    *,
    hints: 'dict[str, Any]'
) -> 'bool'
View Source
    @classmethod

    def matches_artigraph(cls, type_: Type, *, hints: dict[str, Any]) -> bool:

        return isinstance(type_, cls.artigraph)

matches_system

def matches_system(
    type_: 'Any',
    *,
    hints: 'dict[str, Any]'
) -> 'bool'
View Source
    @classmethod

    def matches_system(cls, type_: Any, *, hints: dict[str, Any]) -> bool:

        return isinstance(type_, np.ndarray)

to_artigraph

def to_artigraph(
    type_: 'np.ndarray[Any, Any]',
    *,
    hints: 'dict[str, Any]',
    type_system: 'TypeSystem'
) -> 'Type'
View Source
    @classmethod

    def to_artigraph(

        cls, type_: np.ndarray[Any, Any], *, hints: dict[str, Any], type_system: TypeSystem

    ) -> Type:

        value = type_[0] if isinstance(type_[0], np.ndarray) else type(type_[0])

        return cls.artigraph(element=type_system.to_artigraph(value, hints=hints))

to_system

def to_system(
    type_: 'Type',
    *,
    hints: 'dict[str, Any]',
    type_system: 'TypeSystem'
) -> 'np.ndarray[Any, Any]'
View Source
    @classmethod

    def to_system(

        cls, type_: Type, *, hints: dict[str, Any], type_system: TypeSystem

    ) -> np.ndarray[Any, Any]:

        assert isinstance(type_, List)

        element_type = type_system.to_system(type_.element, hints=hints)

        # scalar numpy dtypes can be instantiated to return a zero value, like the python types

        value = element_type if isinstance(element_type, np.ndarray) else element_type()

        return np.array([value])