diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13567559..b9f89ca4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,6 +89,7 @@ jobs: src/numpy-stubs/testing src/numpy-stubs/typing src/numpy-stubs/__config__.pyi + src/numpy-stubs/_array_api_info.pyi src/numpy-stubs/_configtool.pyi src/numpy-stubs/_distributor_init.pyi src/numpy-stubs/_expired_attrs_2_0.pyi @@ -149,6 +150,7 @@ jobs: src/numpy-stubs/testing src/numpy-stubs/typing src/numpy-stubs/__config__.pyi + src/numpy-stubs/_array_api_info.pyi src/numpy-stubs/_configtool.pyi src/numpy-stubs/_distributor_init.pyi src/numpy-stubs/_expired_attrs_2_0.pyi diff --git a/src/numpy-stubs/_array_api_info.pyi b/src/numpy-stubs/_array_api_info.pyi index e989153b..921baf44 100644 --- a/src/numpy-stubs/_array_api_info.pyi +++ b/src/numpy-stubs/_array_api_info.pyi @@ -1,42 +1,16 @@ -from typing import ClassVar, Literal, TypeAlias, TypedDict, final, overload, type_check_only -from typing_extensions import Never, TypeVar +from typing import Literal as L, TypeAlias, TypedDict, overload, type_check_only +from typing_extensions import TypeVar import numpy as np -_Device: TypeAlias = Literal["cpu"] -_DeviceLike: TypeAlias = _Device | None - -_Capabilities = TypedDict( - "_Capabilities", - { - "boolean indexing": Literal[True], - "data-dependent shapes": Literal[True], - }, -) - -_DefaultDTypes = TypedDict( - "_DefaultDTypes", - { - "real floating": np.dtype[np.float64], - "complex floating": np.dtype[np.complex128], - "integral": np.dtype[np.intp], - "indexing": np.dtype[np.intp], - }, -) - -_KindBool: TypeAlias = Literal["bool"] -_KindInt: TypeAlias = Literal["signed integer"] -_KindUInt: TypeAlias = Literal["unsigned integer"] -_KindInteger: TypeAlias = Literal["integral"] -_KindFloat: TypeAlias = Literal["real floating"] -_KindComplex: TypeAlias = Literal["complex floating"] -_KindNumber: TypeAlias = Literal["numeric"] -_Kind: TypeAlias = _KindBool | _KindInt | _KindUInt | _KindInteger | _KindFloat | _KindComplex | _KindNumber +### +_T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") _T3 = TypeVar("_T3") -_Permute1: TypeAlias = _T1 | tuple[_T1] + +_Permute1: TypeAlias = _T | tuple[_T] _Permute2: TypeAlias = tuple[_T1, _T2] | tuple[_T2, _T1] _Permute3: TypeAlias = ( tuple[_T1, _T2, _T3] @@ -46,37 +20,73 @@ _Permute3: TypeAlias = ( | tuple[_T3, _T1, _T2] | tuple[_T3, _T2, _T1] ) +_Permute12: TypeAlias = _Permute1[_T] | _Permute2[_T1, _T2] +_Permute13: TypeAlias = _Permute1[_T] | _Permute3[_T1, _T2, _T3] + +_Device: TypeAlias = L["cpu"] +_KindBool: TypeAlias = L["bool"] +_KindInt: TypeAlias = L["signed integer"] +_KindUInt: TypeAlias = L["unsigned integer"] +_KindInteger: TypeAlias = L["integral"] +_KindFloat: TypeAlias = L["real floating"] +_KindComplex: TypeAlias = L["complex floating"] +_KindNumber: TypeAlias = L["numeric"] +_Kind: TypeAlias = L[_KindBool, _KindInt, _KindUInt, _KindInteger, _KindFloat, _KindComplex, _KindNumber] + +### + +_Capabilities = TypedDict( + "_Capabilities", + { + "boolean indexing": L[True], + "data-dependent shapes": L[True], + # 'max rank' will be part of the 2024.12 standard + # "max rank": 64, + }, +) +_DefaultDTypes = TypedDict( + "_DefaultDTypes", + { + "real floating": np.dtypes.Float64DType, + "complex floating": np.dtypes.Complex128DType, + "integral": np.dtype[np.int_], + "indexing": np.dtype[np.intp], + }, +) @type_check_only class _DTypesBool(TypedDict): - bool: np.dtype[np.bool] + bool: np.dtypes.BoolDType @type_check_only class _DTypesInt(TypedDict): - int8: np.dtype[np.int8] - int16: np.dtype[np.int16] - int32: np.dtype[np.int32] - int64: np.dtype[np.int64] + int8: np.dtypes.Int8DType + int16: np.dtypes.Int16DType + int32: np.dtypes.Int32DType + int64: np.dtypes.Int64DType @type_check_only class _DTypesUInt(TypedDict): - uint8: np.dtype[np.uint8] - uint16: np.dtype[np.uint16] - uint32: np.dtype[np.uint32] - uint64: np.dtype[np.uint64] - -@type_check_only -class _DTypesInteger(_DTypesInt, _DTypesUInt): ... + uint8: np.dtypes.UInt8DType + uint16: np.dtypes.UInt16DType + uint32: np.dtypes.UInt32DType + uint64: np.dtypes.UInt64DType @type_check_only class _DTypesFloat(TypedDict): - float32: np.dtype[np.float32] - float64: np.dtype[np.float64] + float32: np.dtypes.Float32DType + float64: np.dtypes.Float64DType @type_check_only class _DTypesComplex(TypedDict): - complex64: np.dtype[np.complex64] - complex128: np.dtype[np.complex128] + complex64: np.dtypes.Complex64DType + complex128: np.dtypes.Complex128DType + +@type_check_only +class _DTypesEmpty(TypedDict): ... + +@type_check_only +class _DTypesInteger(_DTypesInt, _DTypesUInt): ... @type_check_only class _DTypesNumber(_DTypesInteger, _DTypesFloat, _DTypesComplex): ... @@ -86,101 +96,60 @@ class _DTypes(_DTypesBool, _DTypesNumber): ... @type_check_only class _DTypesUnion(TypedDict, total=False): - bool: np.dtype[np.bool] - int8: np.dtype[np.int8] - int16: np.dtype[np.int16] - int32: np.dtype[np.int32] - int64: np.dtype[np.int64] - uint8: np.dtype[np.uint8] - uint16: np.dtype[np.uint16] - uint32: np.dtype[np.uint32] - uint64: np.dtype[np.uint64] - float32: np.dtype[np.float32] - float64: np.dtype[np.float64] - complex64: np.dtype[np.complex64] - complex128: np.dtype[np.complex128] - -_EmptyDict: TypeAlias = dict[Never, Never] - -@final + bool: np.dtypes.BoolDType + int8: np.dtypes.Int8DType + int16: np.dtypes.Int16DType + int32: np.dtypes.Int32DType + int64: np.dtypes.Int64DType + uint8: np.dtypes.UInt8DType + uint16: np.dtypes.UInt16DType + uint32: np.dtypes.UInt32DType + uint64: np.dtypes.UInt64DType + float32: np.dtypes.Float32DType + float64: np.dtypes.Float64DType + complex64: np.dtypes.Complex64DType + complex128: np.dtypes.Complex128DType + +### + class __array_namespace_info__: - __module__: ClassVar[Literal["numpy"]] + __module__: L["numpy"] = "numpy" - def capabilities(self) -> _Capabilities: ... - def default_device(self) -> _Device: ... - def default_dtypes( - self, - *, - device: _DeviceLike = ..., - ) -> _DefaultDTypes: ... - def devices(self) -> list[_Device]: ... + def capabilities(self, /) -> _Capabilities: ... + def devices(self, /) -> list[_Device]: ... + def default_device(self, /) -> _Device: ... + def default_dtypes(self, /, *, device: _Device | None = None) -> _DefaultDTypes: ... + + # the mypy errors are false positives @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: None = ..., - ) -> _DTypes: ... + def dtypes(self, /, *, device: _Device | None = None, kind: None = ...) -> _DTypes: ... @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: _Permute1[_KindBool], - ) -> _DTypesBool: ... + def dtypes(self, /, *, device: _Device | None = None, kind: tuple[()]) -> _DTypesEmpty: ... # type: ignore[overload-overlap] @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: _Permute1[_KindInt], - ) -> _DTypesInt: ... + def dtypes(self, /, *, device: _Device | None = None, kind: _Permute1[_KindBool]) -> _DTypesBool: ... # type: ignore[overload-overlap] @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: _Permute1[_KindUInt], - ) -> _DTypesUInt: ... + def dtypes(self, /, *, device: _Device | None = None, kind: _Permute1[_KindInt]) -> _DTypesInt: ... # type: ignore[overload-overlap] @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: _Permute1[_KindFloat], - ) -> _DTypesFloat: ... + def dtypes(self, /, *, device: _Device | None = None, kind: _Permute1[_KindUInt]) -> _DTypesUInt: ... # type: ignore[overload-overlap] @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: _Permute1[_KindComplex], - ) -> _DTypesComplex: ... + def dtypes(self, /, *, device: _Device | None = None, kind: _Permute1[_KindFloat]) -> _DTypesFloat: ... # type: ignore[overload-overlap] + @overload + def dtypes(self, /, *, device: _Device | None = None, kind: _Permute1[_KindComplex]) -> _DTypesComplex: ... # type: ignore[overload-overlap] @overload - def dtypes( + def dtypes( # type: ignore[overload-overlap] self, + /, *, - device: _DeviceLike = ..., - kind: (_Permute1[_KindInteger] | _Permute2[_KindInt, _KindUInt]), + device: _Device | None = None, + kind: _Permute12[_KindInteger, _KindInt, _KindUInt], ) -> _DTypesInteger: ... @overload - def dtypes( + def dtypes( # type: ignore[overload-overlap] self, + /, *, - device: _DeviceLike = ..., - kind: (_Permute1[_KindNumber] | _Permute3[_KindInteger, _KindFloat, _KindComplex]), + device: _Device | None = None, + kind: _Permute13[_KindNumber, _KindInteger, _KindFloat, _KindComplex], ) -> _DTypesNumber: ... @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: tuple[()], - ) -> _EmptyDict: ... - @overload - def dtypes( - self, - *, - device: _DeviceLike = ..., - kind: tuple[_Kind, ...], - ) -> _DTypesUnion: ... + def dtypes(self, /, *, device: _Device | None = None, kind: tuple[_Kind, ...]) -> _DTypesUnion: ... diff --git a/test/static/accept/array_api_info.pyi b/test/static/accept/array_api_info.pyi index 898d8a6e..aa4e58cd 100644 --- a/test/static/accept/array_api_info.pyi +++ b/test/static/accept/array_api_info.pyi @@ -1,5 +1,5 @@ from typing import Literal -from typing_extensions import Never, assert_type +from typing_extensions import assert_type import numpy as np @@ -14,58 +14,56 @@ assert_type(info.devices()[-1], Literal["cpu"]) assert_type(info.capabilities()["boolean indexing"], Literal[True]) assert_type(info.capabilities()["data-dependent shapes"], Literal[True]) -assert_type(info.default_dtypes()["real floating"], np.dtype[np.float64]) -assert_type(info.default_dtypes()["complex floating"], np.dtype[np.complex128]) +assert_type(info.default_dtypes()["real floating"], np.dtypes.Float64DType) +assert_type(info.default_dtypes()["complex floating"], np.dtypes.Complex128DType) assert_type(info.default_dtypes()["integral"], np.dtype[np.int_]) assert_type(info.default_dtypes()["indexing"], np.dtype[np.intp]) -assert_type(info.dtypes()["bool"], np.dtype[np.bool]) -assert_type(info.dtypes()["int8"], np.dtype[np.int8]) -assert_type(info.dtypes()["uint8"], np.dtype[np.uint8]) -assert_type(info.dtypes()["float32"], np.dtype[np.float32]) -assert_type(info.dtypes()["complex64"], np.dtype[np.complex64]) +assert_type(info.dtypes()["bool"], np.dtypes.BoolDType) +assert_type(info.dtypes()["int8"], np.dtypes.Int8DType) +assert_type(info.dtypes()["uint8"], np.dtypes.UInt8DType) +assert_type(info.dtypes()["float32"], np.dtypes.Float32DType) +assert_type(info.dtypes()["complex64"], np.dtypes.Complex64DType) -assert_type(info.dtypes(kind="bool")["bool"], np.dtype[np.bool]) -assert_type(info.dtypes(kind="signed integer")["int64"], np.dtype[np.int64]) -assert_type(info.dtypes(kind="unsigned integer")["uint64"], np.dtype[np.uint64]) -assert_type(info.dtypes(kind="integral")["int32"], np.dtype[np.int32]) -assert_type(info.dtypes(kind="integral")["uint32"], np.dtype[np.uint32]) -assert_type(info.dtypes(kind="real floating")["float64"], np.dtype[np.float64]) -assert_type(info.dtypes(kind="complex floating")["complex128"], np.dtype[np.complex128]) -assert_type(info.dtypes(kind="numeric")["int16"], np.dtype[np.int16]) -assert_type(info.dtypes(kind="numeric")["uint16"], np.dtype[np.uint16]) -assert_type(info.dtypes(kind="numeric")["float64"], np.dtype[np.float64]) -assert_type(info.dtypes(kind="numeric")["complex128"], np.dtype[np.complex128]) +assert_type(info.dtypes(kind="bool")["bool"], np.dtypes.BoolDType) +assert_type(info.dtypes(kind="signed integer")["int64"], np.dtypes.Int64DType) +assert_type(info.dtypes(kind="unsigned integer")["uint64"], np.dtypes.UInt64DType) +assert_type(info.dtypes(kind="integral")["int32"], np.dtypes.Int32DType) +assert_type(info.dtypes(kind="integral")["uint32"], np.dtypes.UInt32DType) +assert_type(info.dtypes(kind="real floating")["float64"], np.dtypes.Float64DType) +assert_type(info.dtypes(kind="complex floating")["complex128"], np.dtypes.Complex128DType) +assert_type(info.dtypes(kind="numeric")["int16"], np.dtypes.Int16DType) +assert_type(info.dtypes(kind="numeric")["uint16"], np.dtypes.UInt16DType) +assert_type(info.dtypes(kind="numeric")["float64"], np.dtypes.Float64DType) +assert_type(info.dtypes(kind="numeric")["complex128"], np.dtypes.Complex128DType) -assert_type(info.dtypes(kind=()), dict[Never, Never]) - -assert_type(info.dtypes(kind=("bool",))["bool"], np.dtype[np.bool]) -assert_type(info.dtypes(kind=("signed integer",))["int64"], np.dtype[np.int64]) -assert_type(info.dtypes(kind=("integral",))["uint32"], np.dtype[np.uint32]) -assert_type(info.dtypes(kind=("complex floating",))["complex128"], np.dtype[np.complex128]) -assert_type(info.dtypes(kind=("numeric",))["float64"], np.dtype[np.float64]) +assert_type(info.dtypes(kind=("bool",))["bool"], np.dtypes.BoolDType) +assert_type(info.dtypes(kind=("signed integer",))["int64"], np.dtypes.Int64DType) +assert_type(info.dtypes(kind=("integral",))["uint32"], np.dtypes.UInt32DType) +assert_type(info.dtypes(kind=("complex floating",))["complex128"], np.dtypes.Complex128DType) +assert_type(info.dtypes(kind=("numeric",))["float64"], np.dtypes.Float64DType) assert_type( info.dtypes(kind=("signed integer", "unsigned integer"))["int8"], - np.dtype[np.int8], + np.dtypes.Int8DType, ) assert_type( info.dtypes(kind=("signed integer", "unsigned integer"))["uint8"], - np.dtype[np.uint8], + np.dtypes.UInt8DType, ) assert_type( info.dtypes(kind=("integral", "real floating", "complex floating"))["int16"], - np.dtype[np.int16], + np.dtypes.Int16DType, ) assert_type( info.dtypes(kind=("integral", "real floating", "complex floating"))["uint16"], - np.dtype[np.uint16], + np.dtypes.UInt16DType, ) assert_type( info.dtypes(kind=("integral", "real floating", "complex floating"))["float32"], - np.dtype[np.float32], + np.dtypes.Float32DType, ) assert_type( info.dtypes(kind=("integral", "real floating", "complex floating"))["complex64"], - np.dtype[np.complex64], + np.dtypes.Complex64DType, )