From f109cc708d5fb7ab5689028280b8fc2ffa15780c Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 20 Feb 2025 00:30:30 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20simplified=20`numpy.?= =?UTF-8?q?=5Ftyping`=20dtype-=20and=20array-like=20aliases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/numpy-stubs/_typing/_array_like.pyi | 41 +++--- src/numpy-stubs/_typing/_dtype_like.pyi | 184 ++++++------------------ src/numpy-stubs/_typing/_scalars.pyi | 16 +-- 3 files changed, 64 insertions(+), 177 deletions(-) diff --git a/src/numpy-stubs/_typing/_array_like.pyi b/src/numpy-stubs/_typing/_array_like.pyi index f6696b5e..40084d17 100644 --- a/src/numpy-stubs/_typing/_array_like.pyi +++ b/src/numpy-stubs/_typing/_array_like.pyi @@ -6,7 +6,7 @@ from typing_extensions import Never, TypeVar import numpy as np from numpy.dtypes import StringDType -from ._nbit_base import _32Bit, _64Bit +from ._nbit_base import _64Bit from ._nested_sequence import _NestedSequence from ._shape import _Shape @@ -32,7 +32,7 @@ _UnknownType: TypeAlias = Never # any and all remaining overloads @runtime_checkable class _SupportsArray(Protocol[_DType_co]): - def __array__(self) -> np.ndarray[Any, _DType_co]: ... + def __array__(self, /) -> np.ndarray[Any, _DType_co]: ... @runtime_checkable class _SupportsArrayFunc(Protocol): @@ -54,38 +54,31 @@ _ArrayLike: TypeAlias = _SupportsArray[np.dtype[_ScalarType]] | _NestedSequence[ # A union representing array-like objects; consists of two typevars: # One representing types that can be parametrized w.r.t. `np.dtype` # and another one for the rest -_DualArrayLike: TypeAlias = _SupportsArray[_DType] | _NestedSequence[_SupportsArray[_DType]] | _T | _NestedSequence[_T] +_DualArrayLike: TypeAlias = _SupportsArray[_DType] | _T | _NestedSequence[_T] | _NestedSequence[_SupportsArray[_DType]] -ArrayLike: TypeAlias = _Buffer | _DualArrayLike[np.dtype[Any], bool | int | float | complex | str | bytes] +ArrayLike: TypeAlias = _Buffer | _DualArrayLike[np.dtype[Any], complex | str | bytes] # `ArrayLike_co`: array-like objects that can be coerced into `X` # given the casting rules `same_kind` _ArrayLikeBool_co: TypeAlias = _DualArrayLike[np.dtype[np.bool], bool] -_ArrayLikeUInt_co: TypeAlias = _DualArrayLike[np.dtype[np.bool] | np.dtype[np.unsignedinteger], bool] -_ArrayLikeInt_co: TypeAlias = _DualArrayLike[np.dtype[np.bool] | np.dtype[np.integer], bool | int] -_ArrayLikeFloat_co: TypeAlias = _DualArrayLike[ - np.dtype[np.bool] | np.dtype[np.integer] | np.dtype[np.floating], - bool | int | float, -] -_ArrayLikeComplex_co: TypeAlias = _DualArrayLike[ - (np.dtype[np.bool] | np.dtype[np.integer] | np.dtype[np.floating] | np.dtype[np.complexfloating]), - bool | int | float | complex, -] -_ArrayLikeNumber_co: TypeAlias = _DualArrayLike[np.dtype[np.bool] | np.dtype[np.number], bool | int | float | complex] -_ArrayLikeTD64_co: TypeAlias = _DualArrayLike[np.dtype[np.bool] | np.dtype[np.integer] | np.dtype[np.timedelta64], bool | int] -_ArrayLikeDT64_co: TypeAlias = _SupportsArray[np.dtype[np.datetime64]] | _NestedSequence[_SupportsArray[np.dtype[np.datetime64]]] -_ArrayLikeObject_co: TypeAlias = _SupportsArray[np.dtype[np.object_]] | _NestedSequence[_SupportsArray[np.dtype[np.object_]]] - -_ArrayLikeVoid_co: TypeAlias = _SupportsArray[np.dtype[np.void]] | _NestedSequence[_SupportsArray[np.dtype[np.void]]] +_ArrayLikeUInt_co: TypeAlias = _DualArrayLike[np.dtype[np.unsignedinteger | np.bool], bool] +_ArrayLikeInt_co: TypeAlias = _DualArrayLike[np.dtype[np.integer | np.bool], int] +_ArrayLikeFloat_co: TypeAlias = _DualArrayLike[np.dtype[np.floating | np.integer | np.bool], float] +_ArrayLikeComplex_co: TypeAlias = _DualArrayLike[np.dtype[np.bool | np.number], complex] +_ArrayLikeNumber_co: TypeAlias = _ArrayLikeComplex_co +_ArrayLikeTD64_co: TypeAlias = _DualArrayLike[np.dtype[np.timedelta64 | np.integer | np.bool], int] +_ArrayLikeDT64_co: TypeAlias = _ArrayLike[np.datetime64] +_ArrayLikeObject_co: TypeAlias = _ArrayLike[np.object_] +_ArrayLikeVoid_co: TypeAlias = _ArrayLike[np.void] _ArrayLikeStr_co: TypeAlias = _DualArrayLike[np.dtype[np.str_], str] _ArrayLikeBytes_co: TypeAlias = _DualArrayLike[np.dtype[np.bytes_], bytes] _ArrayLikeString_co: TypeAlias = _DualArrayLike[StringDType, str] -_ArrayLikeAnyString_co: TypeAlias = _ArrayLikeStr_co | _ArrayLikeBytes_co | _ArrayLikeString_co +_ArrayLikeAnyString_co: TypeAlias = _DualArrayLike[StringDType | np.dtype[np.character], bytes | str] __Float64_co: TypeAlias = np.floating[_64Bit] | np.float32 | np.float16 | np.integer | np.bool -__Complex128_co: TypeAlias = np.number[_64Bit] | np.number[_32Bit] | np.float16 | np.integer | np.bool -_ArrayLikeFloat64_co: TypeAlias = _DualArrayLike[np.dtype[__Float64_co], float | int] -_ArrayLikeComplex128_co: TypeAlias = _DualArrayLike[np.dtype[__Complex128_co], complex | float | int] +__Complex128_co: TypeAlias = np.complexfloating[_64Bit] | np.complex64 | __Float64_co +_ArrayLikeFloat64_co: TypeAlias = _DualArrayLike[np.dtype[__Float64_co], float] +_ArrayLikeComplex128_co: TypeAlias = _DualArrayLike[np.dtype[__Complex128_co], complex] # NOTE: This includes `builtins.bool`, but not `numpy.bool`. _ArrayLikeInt: TypeAlias = _DualArrayLike[np.dtype[np.integer], int] diff --git a/src/numpy-stubs/_typing/_dtype_like.pyi b/src/numpy-stubs/_typing/_dtype_like.pyi index 57e25544..c4c9f3a5 100644 --- a/src/numpy-stubs/_typing/_dtype_like.pyi +++ b/src/numpy-stubs/_typing/_dtype_like.pyi @@ -1,104 +1,69 @@ +from _typeshed import Incomplete from collections.abc import Sequence from typing import Any, Protocol, TypeAlias, TypedDict, runtime_checkable -from typing_extensions import TypeVar +from typing_extensions import Required, TypeVar import numpy as np from ._char_codes import ( _BoolCodes, - _ByteCodes, _BytesCodes, - _CDoubleCodes, - _CLongDoubleCodes, - _CSingleCodes, - _Complex64Codes, - _Complex128Codes, + _ComplexFloatingCodes, _DT64Codes, - _DoubleCodes, - _Float16Codes, - _Float32Codes, - _Float64Codes, - _HalfCodes, - _Int8Codes, - _Int16Codes, - _Int32Codes, - _Int64Codes, - _IntCCodes, - _IntCodes, - _IntPCodes, - _LongCodes, - _LongDoubleCodes, - _LongLongCodes, + _FloatingCodes, + _NumberCodes, _ObjectCodes, - _ShortCodes, - _SingleCodes, + _SignedIntegerCodes, _StrCodes, _TD64Codes, - _UByteCodes, - _UInt8Codes, - _UInt16Codes, - _UInt32Codes, - _UInt64Codes, - _UIntCCodes, - _UIntCodes, - _UIntPCodes, - _ULongLongCodes, - _UShortCodes, + _UnsignedIntegerCodes, _VoidCodes, ) from ._shape import _ShapeLike -_SCT = TypeVar("_SCT", bound=np.generic) -_DType_co = TypeVar("_DType_co", covariant=True, bound=np.dtype[Any]) +_ScalarT = TypeVar("_ScalarT", bound=np.generic) +_DTypeT_co = TypeVar("_DTypeT_co", covariant=True, bound=np.dtype[Any]) -_DTypeLikeNested: TypeAlias = Any +# TODO(jorenham): Actually annotate this +_DTypeLikeNested: TypeAlias = Incomplete -# Mandatory keys -class _DTypeDictBase(TypedDict): - names: Sequence[str] - formats: Sequence[_DTypeLikeNested] - -# Mandatory + optional keys -class _DTypeDict(_DTypeDictBase, total=False): - # Only `str` elements are usable as indexing aliases, - # but `titles` can in principle accept any object - offsets: Sequence[int] - titles: Sequence[Any] +class _DTypeDict(TypedDict, total=False): + names: Required[Sequence[str]] + formats: Required[Sequence[_DTypeLikeNested]] itemsize: int aligned: bool + offsets: Sequence[int] + # Only `str` elements are usable as indexing aliases, + # but `titles` can in principle accept any object + titles: Sequence[str | Any] # A protocol for anything with the dtype attribute @runtime_checkable -class _SupportsDType(Protocol[_DType_co]): +class _SupportsDType(Protocol[_DTypeT_co]): @property - def dtype(self) -> _DType_co: ... + def dtype(self) -> _DTypeT_co: ... # A subset of `npt.DTypeLike` that can be parametrized w.r.t. `np.generic` -_DTypeLike: TypeAlias = np.dtype[_SCT] | type[_SCT] | _SupportsDType[np.dtype[_SCT]] +_DTypeLike: TypeAlias = type[_ScalarT] | np.dtype[_ScalarT] | _SupportsDType[np.dtype[_ScalarT]] # Would create a dtype[np.void] -_VoidDTypeLike: TypeAlias = ( - tuple[_DTypeLikeNested, int] - | tuple[_DTypeLikeNested, _ShapeLike] - | list[Any] - | _DTypeDict - | tuple[_DTypeLikeNested, _DTypeLikeNested] -) +_VoidDTypeLike: TypeAlias = tuple[_DTypeLikeNested, int | _ShapeLike | _DTypeLikeNested] | list[Any] | _DTypeDict -# Anything that can be coerced into numpy.dtype. -# Reference: https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html -DTypeLike: TypeAlias = ( - np.dtype[Any] - # array-scalar types and generic types - | type[Any] # NOTE: We're stuck with `type[Any]` due to object dtypes - # anything with a dtype attribute - | _SupportsDType[np.dtype[Any]] - # character codes, type strings or comma-separated fields, e.g., 'float64' - | str - | _VoidDTypeLike - # default data type (float64) - | None -) +# Aliases for commonly used dtype-like objects. +# Note that the precision of `np.number` subclasses is ignored herein. +_DTypeLikeBool: TypeAlias = type[bool] | _DTypeLike[np.bool] | _BoolCodes +_DTypeLikeUInt: TypeAlias = _DTypeLike[np.unsignedinteger] | _UnsignedIntegerCodes +_DTypeLikeInt: TypeAlias = type[int] | _DTypeLike[np.signedinteger] | _SignedIntegerCodes +_DTypeLikeFloat: TypeAlias = type[float] | _DTypeLike[np.floating] | _FloatingCodes +_DTypeLikeComplex: TypeAlias = type[complex] | _DTypeLike[np.complexfloating] | _ComplexFloatingCodes +_DTypeLikeDT64: TypeAlias = _DTypeLike[np.timedelta64] | _TD64Codes +_DTypeLikeTD64: TypeAlias = _DTypeLike[np.datetime64] | _DT64Codes +_DTypeLikeStr: TypeAlias = type[str] | _DTypeLike[np.str_] | _StrCodes +_DTypeLikeBytes: TypeAlias = type[bytes] | _DTypeLike[np.bytes_] | _BytesCodes +_DTypeLikeVoid: TypeAlias = _DTypeLike[np.void] | _VoidCodes | _VoidDTypeLike +_DTypeLikeObject: TypeAlias = type | _DTypeLike[np.object_] | _ObjectCodes + +_DTypeLikeComplex_co: TypeAlias = type[complex] | _DTypeLike[np.number] | _NumberCodes | _BoolCodes # NOTE: while it is possible to provide the dtype as a dict of # dtype-like objects (e.g. `{'field1': ..., 'field2': ..., ...}`), @@ -107,75 +72,6 @@ DTypeLike: TypeAlias = ( # # See https://github.com/numpy/numpy/issues/16891 for more details. -# Aliases for commonly used dtype-like objects. -# Note that the precision of `np.number` subclasses is ignored herein. -_DTypeLikeBool: TypeAlias = type[bool] | type[np.bool] | np.dtype[np.bool] | _SupportsDType[np.dtype[np.bool]] | _BoolCodes -_DTypeLikeUInt: TypeAlias = ( - type[np.unsignedinteger[Any]] - | np.dtype[np.unsignedinteger[Any]] - | _SupportsDType[np.dtype[np.unsignedinteger[Any]]] - | _UInt8Codes - | _UInt16Codes - | _UInt32Codes - | _UInt64Codes - | _UByteCodes - | _UShortCodes - | _UIntCCodes - | _LongCodes - | _ULongLongCodes - | _UIntPCodes - | _UIntCodes -) -_DTypeLikeInt: TypeAlias = ( - type[int] - | type[np.signedinteger[Any]] - | np.dtype[np.signedinteger[Any]] - | _SupportsDType[np.dtype[np.signedinteger[Any]]] - | _Int8Codes - | _Int16Codes - | _Int32Codes - | _Int64Codes - | _ByteCodes - | _ShortCodes - | _IntCCodes - | _LongCodes - | _LongLongCodes - | _IntPCodes - | _IntCodes -) -_DTypeLikeFloat: TypeAlias = ( - type[float] - | type[np.floating[Any]] - | np.dtype[np.floating[Any]] - | _SupportsDType[np.dtype[np.floating[Any]]] - | _Float16Codes - | _Float32Codes - | _Float64Codes - | _HalfCodes - | _SingleCodes - | _DoubleCodes - | _LongDoubleCodes -) -_DTypeLikeComplex: TypeAlias = ( - type[complex] - | type[np.complexfloating[Any]] - | np.dtype[np.complexfloating[Any]] - | _SupportsDType[np.dtype[np.complexfloating[Any]]] - | _Complex64Codes - | _Complex128Codes - | _CSingleCodes - | _CDoubleCodes - | _CLongDoubleCodes -) -_DTypeLikeDT64: TypeAlias = ( - type[np.timedelta64] | np.dtype[np.timedelta64] | _SupportsDType[np.dtype[np.timedelta64]] | _TD64Codes -) -_DTypeLikeTD64: TypeAlias = type[np.datetime64] | np.dtype[np.datetime64] | _SupportsDType[np.dtype[np.datetime64]] | _DT64Codes -_DTypeLikeStr: TypeAlias = type[str] | type[np.str_] | np.dtype[np.str_] | _SupportsDType[np.dtype[np.str_]] | _StrCodes -_DTypeLikeBytes: TypeAlias = ( - type[bytes] | type[np.bytes_] | np.dtype[np.bytes_] | _SupportsDType[np.dtype[np.bytes_]] | _BytesCodes -) -_DTypeLikeVoid: TypeAlias = type[np.void] | np.dtype[np.void] | _SupportsDType[np.dtype[np.void]] | _VoidCodes | _VoidDTypeLike -_DTypeLikeObject: TypeAlias = type | np.dtype[np.object_] | _SupportsDType[np.dtype[np.object_]] | _ObjectCodes - -_DTypeLikeComplex_co: TypeAlias = _DTypeLikeBool | _DTypeLikeUInt | _DTypeLikeInt | _DTypeLikeFloat | _DTypeLikeComplex +# Anything that can be coerced into numpy.dtype. +# Reference: https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html +DTypeLike: TypeAlias = str | _DTypeLike[Any] | _VoidDTypeLike | None diff --git a/src/numpy-stubs/_typing/_scalars.pyi b/src/numpy-stubs/_typing/_scalars.pyi index bb6c3bcf..ca629888 100644 --- a/src/numpy-stubs/_typing/_scalars.pyi +++ b/src/numpy-stubs/_typing/_scalars.pyi @@ -4,20 +4,18 @@ import numpy as np # NOTE: `_StrLike_co` and `_BytesLike_co` are pointless, as `np.str_` and # `np.bytes_` are already subclasses of their builtin counterpart - _CharLike_co: TypeAlias = str | bytes # The 6 `Like_co` type-aliases below represent all scalars that can be # coerced into `` (with the casting rule `same_kind`) _BoolLike_co: TypeAlias = bool | np.bool -_UIntLike_co: TypeAlias = np.unsignedinteger[Any] | _BoolLike_co -_IntLike_co: TypeAlias = int | np.integer | _BoolLike_co -_FloatLike_co: TypeAlias = float | np.floating | _IntLike_co -_ComplexLike_co: TypeAlias = complex | np.complexfloating | _FloatLike_co -_TD64Like_co: TypeAlias = np.timedelta64 | _IntLike_co - -_NumberLike_co: TypeAlias = int | float | complex | np.number | np.bool -_ScalarLike_co: TypeAlias = int | float | complex | str | bytes | np.generic +_UIntLike_co: TypeAlias = bool | np.unsignedinteger | np.bool +_IntLike_co: TypeAlias = int | np.integer | np.bool +_FloatLike_co: TypeAlias = float | np.floating | np.integer | np.bool +_ComplexLike_co: TypeAlias = complex | np.number | np.bool +_NumberLike_co = _ComplexLike_co +_TD64Like_co: TypeAlias = int | np.timedelta64 | np.integer | np.bool +_ScalarLike_co: TypeAlias = complex | bytes | str | np.generic # `_VoidLike_co` is technically not a scalar, but it's close enough _VoidLike_co: TypeAlias = tuple[Any, ...] | np.void From 2853e03033328f9003000432b9e42160bfeeadaa Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 20 Feb 2025 00:44:54 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=9A=A8=20temporarily=20ignore=20a=20p?= =?UTF-8?q?yright=20error=20(will=20fix=20in=20#158)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/numpy-stubs/_core/_multiarray_umath.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numpy-stubs/_core/_multiarray_umath.pyi b/src/numpy-stubs/_core/_multiarray_umath.pyi index fb7cad7c..45903648 100644 --- a/src/numpy-stubs/_core/_multiarray_umath.pyi +++ b/src/numpy-stubs/_core/_multiarray_umath.pyi @@ -1412,7 +1412,7 @@ def dot(a: npt.ArrayLike, b: npt.ArrayLike, out: _ArrayT) -> _ArrayT: ... # @overload -def vdot(a: _ArrayLike[_NumericT], b: _ArrayLike[_NumericT], /) -> _NumericT: ... # type: ignore[overload-overlap] # false positive +def vdot(a: _ArrayLike[_NumericT], b: _ArrayLike[_NumericT], /) -> _NumericT: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload def vdot(a: _ArrayLikeInt_co, b: _ArrayLikeInt_co, /) -> np.signedinteger: ... @overload