diff options
| author | Touqir Sajed <touqir@ualberta.ca> | 2021-02-05 16:49:16 +0600 |
|---|---|---|
| committer | Touqir Sajed <touqir@ualberta.ca> | 2021-02-05 16:49:16 +0600 |
| commit | ed3d080f637e263fdcd702fb7d588433461ff243 (patch) | |
| tree | 1e96b98c6ce36a4f6055f80edab22a44875a997a /numpy | |
| parent | 2b41cbf3e46e6d16e84f0fa800500346789dba6d (diff) | |
| parent | 0a1bd4ead41b1fdfb53142097b5e08555f280545 (diff) | |
| download | numpy-ed3d080f637e263fdcd702fb7d588433461ff243.tar.gz | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'numpy')
112 files changed, 2757 insertions, 1266 deletions
diff --git a/numpy/__init__.py b/numpy/__init__.py index a242bb7df..6e0b60913 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -109,8 +109,9 @@ Exceptions to this rule are documented. import sys import warnings -from ._globals import ModuleDeprecationWarning, VisibleDeprecationWarning -from ._globals import _NoValue +from ._globals import ( + ModuleDeprecationWarning, VisibleDeprecationWarning, _NoValue +) # We first need to detect if we're being called as part of the numpy setup # procedure itself in a reliable manner. @@ -165,34 +166,58 @@ else: # Deprecations introduced in NumPy 1.20.0, 2020-06-06 import builtins as _builtins + + _msg = ( + "`np.{n}` is a deprecated alias for the builtin `{n}`. " + "To silence this warning, use `{n}` by itself. Doing this will not " + "modify any behavior and is safe. {extended_msg}\n" + "Deprecated in NumPy 1.20; for more details and guidance: " + "https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations") + + _specific_msg = ( + "If you specifically wanted the numpy scalar type, use `np.{}` here.") + + _int_extended_msg = ( + "When replacing `np.{}`, you may wish to use e.g. `np.int64` " + "or `np.int32` to specify the precision. If you wish to review " + "your current use, check the release note link for " + "additional information.") + + _type_info = [ + ("object", ""), # The NumPy scalar only exists by name. + ("bool", _specific_msg.format("bool_")), + ("float", _specific_msg.format("float64")), + ("complex", _specific_msg.format("complex128")), + ("str", _specific_msg.format("str_")), + ("int", _int_extended_msg.format("int"))] + __deprecated_attrs__.update({ - n: ( - getattr(_builtins, n), - "`np.{n}` is a deprecated alias for the builtin `{n}`. " - "Use `{n}` by itself, which is identical in behavior, to silence " - "this warning. " - "If you specifically wanted the numpy scalar type, use `np.{n}_` " - "here." - .format(n=n) - ) - for n in ["bool", "int", "float", "complex", "object", "str"] - }) - __deprecated_attrs__.update({ - n: ( - getattr(compat, n), - "`np.{n}` is a deprecated alias for `np.compat.{n}`. " - "Use `np.compat.{n}` by itself, which is identical in behavior, " - "to silence this warning. " - "In the likely event your code does not need to work on Python 2 " - "you can use the builtin ``{n2}`` for which ``np.compat.{n}`` is " - "itself an alias. " - "If you specifically wanted the numpy scalar type, use `np.{n2}_` " - "here." - .format(n=n, n2=n2) - ) - for n, n2 in [("long", "int"), ("unicode", "str")] + n: (getattr(_builtins, n), _msg.format(n=n, extended_msg=extended_msg)) + for n, extended_msg in _type_info }) + _msg = ( + "`np.{n}` is a deprecated alias for `np.compat.{n}`. " + "To silence this warning, use `np.compat.{n}` by itself. " + "In the likely event your code does not need to work on Python 2 " + "you can use the builtin `{n2}` for which `np.compat.{n}` is itself " + "an alias. Doing this will not modify any behaviour and is safe. " + "{extended_msg}\n" + "Deprecated in NumPy 1.20; for more details and guidance: " + "https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations") + + __deprecated_attrs__["long"] = ( + getattr(compat, "long"), + _msg.format(n="long", n2="int", + extended_msg=_int_extended_msg.format("long"))) + + __deprecated_attrs__["unicode"] = ( + getattr(compat, "unicode"), + _msg.format(n="unicode", n2="str", + extended_msg=_specific_msg.format("str_"))) + + del _msg, _specific_msg, _int_extended_msg, _type_info, _builtins + from .core import round, abs, max, min # now that numpy modules are imported, can initialize limits core.getlimits._register_known_types() @@ -397,4 +422,3 @@ else: from ._version import get_versions __version__ = get_versions()['version'] del get_versions - diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 656048173..b29ba38da 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -7,19 +7,41 @@ from contextlib import ContextDecorator from numpy.core._internal import _ctypes from numpy.typing import ( + # Arrays ArrayLike, + _ArrayND, + _ArrayOrScalar, + _NestedSequence, + _RecursiveSequence, + _ArrayLikeBool_co, + _ArrayLikeUInt_co, + _ArrayLikeInt_co, + _ArrayLikeFloat_co, + _ArrayLikeComplex_co, + _ArrayLikeNumber_co, + _ArrayLikeTD64_co, + _ArrayLikeDT64_co, + _ArrayLikeObject_co, + + # DTypes DTypeLike, - _Shape, - _ShapeLike, - _CharLike, - _BoolLike, - _IntLike, - _FloatLike, - _ComplexLike, - _TD64Like, - _NumberLike, _SupportsDType, _VoidDTypeLike, + + # Shapes + _Shape, + _ShapeLike, + + # Scalars + _CharLike_co, + _BoolLike_co, + _IntLike_co, + _FloatLike_co, + _ComplexLike_co, + _TD64Like_co, + _NumberLike_co, + + # `number` precision NBitBase, _256Bit, _128Bit, @@ -39,8 +61,8 @@ from numpy.typing import ( _NBitSingle, _NBitDouble, _NBitLongDouble, -) -from numpy.typing import ( + + # Character codes _BoolCodes, _UInt8Codes, _UInt16Codes, @@ -118,6 +140,7 @@ from typing import ( Iterable, List, Mapping, + NoReturn, Optional, overload, Sequence, @@ -135,72 +158,70 @@ from typing import ( if sys.version_info >= (3, 8): from typing import Literal, Protocol, SupportsIndex, Final else: - from typing_extensions import Literal, Protocol, Final - class SupportsIndex(Protocol): - def __index__(self) -> int: ... + from typing_extensions import Literal, Protocol, SupportsIndex, Final # Ensures that the stubs are picked up from numpy import ( - char, - ctypeslib, - emath, - fft, - lib, - linalg, - ma, - matrixlib, - polynomial, - random, - rec, - testing, - version, + char as char, + ctypeslib as ctypeslib, + emath as emath, + fft as fft, + lib as lib, + linalg as linalg, + ma as ma, + matrixlib as matrixlib, + polynomial as polynomial, + random as random, + rec as rec, + testing as testing, + version as version, ) from numpy.core.function_base import ( - linspace, - logspace, - geomspace, + linspace as linspace, + logspace as logspace, + geomspace as geomspace, ) from numpy.core.fromnumeric import ( - take, - reshape, - choose, - repeat, - put, - swapaxes, - transpose, - partition, - argpartition, - sort, - argsort, - argmax, - argmin, - searchsorted, - resize, - squeeze, - diagonal, - trace, - ravel, - nonzero, - shape, - compress, - clip, - sum, - all, - any, - cumsum, - ptp, - amax, - amin, - prod, - cumprod, - ndim, - size, - around, - mean, - std, - var, + take as take, + reshape as reshape, + choose as choose, + repeat as repeat, + put as put, + swapaxes as swapaxes, + transpose as transpose, + partition as partition, + argpartition as argpartition, + sort as sort, + argsort as argsort, + argmax as argmax, + argmin as argmin, + searchsorted as searchsorted, + resize as resize, + squeeze as squeeze, + diagonal as diagonal, + trace as trace, + ravel as ravel, + nonzero as nonzero, + shape as shape, + compress as compress, + clip as clip, + sum as sum, + all as all, + any as any, + cumsum as cumsum, + ptp as ptp, + amax as amax, + amin as amin, + prod as prod, + cumprod as cumprod, + ndim as ndim, + size as size, + around as around, + mean as mean, + std as std, + var as var, ) from numpy.core._asarray import ( @@ -293,52 +314,10 @@ from numpy.core.shape_base import ( vstack as vstack, ) -# Add an object to `__all__` if their stubs are defined in an external file; -# their stubs will not be recognized otherwise. -# NOTE: This is redundant for objects defined within this file. -__all__ = [ - "linspace", - "logspace", - "geomspace", - "take", - "reshape", - "choose", - "repeat", - "put", - "swapaxes", - "transpose", - "partition", - "argpartition", - "sort", - "argsort", - "argmax", - "argmin", - "searchsorted", - "resize", - "squeeze", - "diagonal", - "trace", - "ravel", - "nonzero", - "shape", - "compress", - "clip", - "sum", - "all", - "any", - "cumsum", - "ptp", - "amax", - "amin", - "prod", - "cumprod", - "ndim", - "size", - "around", - "mean", - "std", - "var", -] +__all__: List[str] +__path__: List[str] +__version__: str +__git_version__: str DataSource: Any MachAr: Any @@ -359,7 +338,6 @@ bincount: Any bitwise_not: Any blackman: Any bmat: Any -bool8: Any broadcast: Any broadcast_arrays: Any broadcast_to: Any @@ -367,7 +345,6 @@ busday_count: Any busday_offset: Any busdaycalendar: Any byte_bounds: Any -bytes0: Any c_: Any can_cast: Any cast: Any @@ -375,7 +352,6 @@ chararray: Any column_stack: Any common_type: Any compare_chararrays: Any -complex256: Any concatenate: Any conj: Any copy: Any @@ -411,7 +387,6 @@ fix: Any flip: Any fliplr: Any flipud: Any -float128: Any format_parser: Any frombuffer: Any fromfile: Any @@ -495,7 +470,6 @@ nditer: Any nested_iters: Any newaxis: Any numarray: Any -object0: Any ogrid: Any packbits: Any pad: Any @@ -546,7 +520,6 @@ sinc: Any sort_complex: Any source: Any split: Any -string_: Any take_along_axis: Any tile: Any trapz: Any @@ -569,25 +542,24 @@ unwrap: Any vander: Any vdot: Any vectorize: Any -void0: Any vsplit: Any where: Any who: Any _NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray) -_DTypeScalar = TypeVar("_DTypeScalar", bound=generic) +_DTypeScalar_co = TypeVar("_DTypeScalar_co", covariant=True, bound=generic) _ByteOrder = Literal["S", "<", ">", "=", "|", "L", "B", "N", "I"] -class dtype(Generic[_DTypeScalar]): +class dtype(Generic[_DTypeScalar_co]): names: Optional[Tuple[str, ...]] # Overload for subclass of generic @overload def __new__( cls, - dtype: Type[_DTypeScalar], + dtype: Type[_DTypeScalar_co], align: bool = ..., copy: bool = ..., - ) -> dtype[_DTypeScalar]: ... + ) -> dtype[_DTypeScalar_co]: ... # Overloads for string aliases, Python types, and some assorted # other special cases. Order is sometimes important because of the # subtype relationships @@ -702,18 +674,17 @@ class dtype(Generic[_DTypeScalar]): @overload def __new__( cls, - dtype: dtype[_DTypeScalar], + dtype: dtype[_DTypeScalar_co], align: bool = ..., copy: bool = ..., - ) -> dtype[_DTypeScalar]: ... - # TODO: handle _SupportsDType better + ) -> dtype[_DTypeScalar_co]: ... @overload def __new__( cls, - dtype: _SupportsDType, + dtype: _SupportsDType[dtype[_DTypeScalar_co]], align: bool = ..., copy: bool = ..., - ) -> dtype[Any]: ... + ) -> dtype[_DTypeScalar_co]: ... # Handle strings that can't be expressed as literals; i.e. s1, s2, ... @overload def __new__( @@ -782,7 +753,7 @@ class dtype(Generic[_DTypeScalar]): @property def str(self) -> builtins.str: ... @property - def type(self) -> Type[_DTypeScalar]: ... + def type(self) -> Type[_DTypeScalar_co]: ... class _flagsobj: aligned: bool @@ -858,11 +829,11 @@ _PartitionKind = Literal["introselect"] _SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"] _SortSide = Literal["left", "right"] -_ArrayLikeBool = Union[_BoolLike, Sequence[_BoolLike], ndarray] +_ArrayLikeBool = Union[_BoolLike_co, Sequence[_BoolLike_co], ndarray] _ArrayLikeIntOrBool = Union[ - _IntLike, + _IntLike_co, ndarray, - Sequence[_IntLike], + Sequence[_IntLike_co], Sequence[Sequence[Any]], # TODO: wait for support for recursive types ] @@ -1073,7 +1044,7 @@ class _ArrayOrScalarCommon: axis: None = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1082,7 +1053,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1091,7 +1062,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... @overload @@ -1124,7 +1095,7 @@ class _ArrayOrScalarCommon: axis: None = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1133,7 +1104,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1142,7 +1113,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... def newbyteorder(self: _ArraySelf, __new_order: _ByteOrder = ...) -> _ArraySelf: ... @@ -1153,7 +1124,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1163,7 +1134,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1173,7 +1144,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... @overload @@ -1234,7 +1205,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1244,7 +1215,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1254,13 +1225,13 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... @overload def take( self, - indices: _IntLike, + indices: _IntLike_co, axis: Optional[int] = ..., out: None = ..., mode: _ModeKind = ..., @@ -1310,15 +1281,26 @@ class _ArrayOrScalarCommon: ) -> _NdArraySubClass: ... _DType = TypeVar("_DType", bound=dtype[Any]) +_DType_co = TypeVar("_DType_co", covariant=True, bound=dtype[Any]) # TODO: Set the `bound` to something more suitable once we # have proper shape support _ShapeType = TypeVar("_ShapeType", bound=Any) - +_NumberType = TypeVar("_NumberType", bound=number[Any]) _BufferType = Union[ndarray, bytes, bytearray, memoryview] + +_T = TypeVar("_T") +_2Tuple = Tuple[_T, _T] _Casting = Literal["no", "equiv", "safe", "same_kind", "unsafe"] -class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): +_ArrayUInt_co = _ArrayND[Union[bool_, unsignedinteger[Any]]] +_ArrayInt_co = _ArrayND[Union[bool_, integer[Any]]] +_ArrayFloat_co = _ArrayND[Union[bool_, integer[Any], floating[Any]]] +_ArrayComplex_co = _ArrayND[Union[bool_, integer[Any], floating[Any], complexfloating[Any, Any]]] +_ArrayNumber_co = _ArrayND[Union[bool_, number[Any]]] +_ArrayTD64_co = _ArrayND[Union[bool_, integer[Any], timedelta64]] + +class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): @property def base(self) -> Optional[ndarray]: ... @property @@ -1343,7 +1325,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): order: _OrderKACF = ..., ) -> _ArraySelf: ... @overload - def __array__(self, __dtype: None = ...) -> ndarray[Any, _DType]: ... + def __array__(self, __dtype: None = ...) -> ndarray[Any, _DType_co]: ... @overload def __array__(self, __dtype: DTypeLike) -> ndarray[Any, dtype[Any]]: ... @property @@ -1455,33 +1437,414 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): def __iter__(self) -> Any: ... def __contains__(self, key) -> bool: ... def __index__(self) -> int: ... - def __lt__(self, other: ArrayLike) -> Union[ndarray, bool_]: ... - def __le__(self, other: ArrayLike) -> Union[ndarray, bool_]: ... - def __gt__(self, other: ArrayLike) -> Union[ndarray, bool_]: ... - def __ge__(self, other: ArrayLike) -> Union[ndarray, bool_]: ... - def __matmul__(self, other: ArrayLike) -> Any: ... + + # The last overload is for catching recursive objects whose + # nesting is too deep. + # The first overload is for catching `bytes` (as they are a subtype of + # `Sequence[int]`) and `str`. As `str` is a recusive sequence of + # strings, it will pass through the final overload otherwise + + @overload + def __lt__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __lt__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __lt__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __lt__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __lt__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ... + @overload + def __lt__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __lt__( + self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]], + other: _RecursiveSequence, + ) -> _ArrayOrScalar[bool_]: ... + + @overload + def __le__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __le__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __le__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __le__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __le__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ... + @overload + def __le__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __le__( + self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]], + other: _RecursiveSequence, + ) -> _ArrayOrScalar[bool_]: ... + + @overload + def __gt__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __gt__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __gt__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __gt__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __gt__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ... + @overload + def __gt__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __gt__( + self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]], + other: _RecursiveSequence, + ) -> _ArrayOrScalar[bool_]: ... + + @overload + def __ge__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __ge__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __ge__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __ge__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __ge__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ... + @overload + def __ge__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> _ArrayOrScalar[bool_]: ... + @overload + def __ge__( + self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]], + other: _RecursiveSequence, + ) -> _ArrayOrScalar[bool_]: ... + + # Unary ops + @overload + def __abs__(self: _ArrayND[bool_]) -> _ArrayOrScalar[bool_]: ... + @overload + def __abs__(self: _ArrayND[complexfloating[_NBit1, _NBit1]]) -> _ArrayOrScalar[floating[_NBit1]]: ... + @overload + def __abs__(self: _ArrayND[_NumberType]) -> _ArrayOrScalar[_NumberType]: ... + @overload + def __abs__(self: _ArrayND[timedelta64]) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __abs__(self: _ArrayND[object_]) -> Any: ... + + @overload + def __invert__(self: _ArrayND[bool_]) -> _ArrayOrScalar[bool_]: ... + @overload + def __invert__(self: _ArrayND[_IntType]) -> _ArrayOrScalar[_IntType]: ... + @overload + def __invert__(self: _ArrayND[object_]) -> Any: ... + + @overload + def __pos__(self: _ArrayND[_NumberType]) -> _ArrayOrScalar[_NumberType]: ... + @overload + def __pos__(self: _ArrayND[timedelta64]) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __pos__(self: _ArrayND[object_]) -> Any: ... + + @overload + def __neg__(self: _ArrayND[_NumberType]) -> _ArrayOrScalar[_NumberType]: ... + @overload + def __neg__(self: _ArrayND[timedelta64]) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __neg__(self: _ArrayND[object_]) -> Any: ... + + # Binary ops # NOTE: `ndarray` does not implement `__imatmul__` - def __rmatmul__(self, other: ArrayLike) -> Any: ... - def __neg__(self: _ArraySelf) -> Any: ... - def __pos__(self: _ArraySelf) -> Any: ... - def __abs__(self: _ArraySelf) -> Any: ... - def __mod__(self, other: ArrayLike) -> Any: ... - def __rmod__(self, other: ArrayLike) -> Any: ... - def __divmod__(self, other: ArrayLike) -> Tuple[Any, Any]: ... - def __rdivmod__(self, other: ArrayLike) -> Tuple[Any, Any]: ... - def __add__(self, other: ArrayLike) -> Any: ... - def __radd__(self, other: ArrayLike) -> Any: ... - def __sub__(self, other: ArrayLike) -> Any: ... - def __rsub__(self, other: ArrayLike) -> Any: ... - def __mul__(self, other: ArrayLike) -> Any: ... - def __rmul__(self, other: ArrayLike) -> Any: ... + @overload + def __matmul__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __matmul__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[bool_]: ... # type: ignore[misc] + @overload + def __matmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __matmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __matmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __matmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... + @overload + def __matmul__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __matmul__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __matmul__( + self: _ArrayNumber_co, + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __rmatmul__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __rmatmul__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[bool_]: ... # type: ignore[misc] + @overload + def __rmatmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rmatmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rmatmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __rmatmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... + @overload + def __rmatmul__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __rmatmul__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __rmatmul__( + self: _ArrayNumber_co, + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __mod__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __mod__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[int8]: ... # type: ignore[misc] + @overload + def __mod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __mod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __mod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __mod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __mod__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __mod__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __mod__( + self: _ArrayND[Union[bool_, integer[Any], floating[Any], timedelta64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __rmod__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __rmod__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[int8]: ... # type: ignore[misc] + @overload + def __rmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __rmod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __rmod__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __rmod__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __rmod__( + self: _ArrayND[Union[bool_, integer[Any], floating[Any], timedelta64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __divmod__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __divmod__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _2Tuple[_ArrayOrScalar[int8]]: ... # type: ignore[misc] + @overload + def __divmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _2Tuple[_ArrayOrScalar[unsignedinteger[Any]]]: ... # type: ignore[misc] + @overload + def __divmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _2Tuple[_ArrayOrScalar[signedinteger[Any]]]: ... # type: ignore[misc] + @overload + def __divmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _2Tuple[_ArrayOrScalar[floating[Any]]]: ... # type: ignore[misc] + @overload + def __divmod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> Union[Tuple[int64, timedelta64], Tuple[_ArrayND[int64], _ArrayND[timedelta64]]]: ... + @overload + def __divmod__( + self: _ArrayND[Union[bool_, integer[Any], floating[Any], timedelta64]], + other: _RecursiveSequence, + ) -> _2Tuple[Any]: ... + + @overload + def __rdivmod__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __rdivmod__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _2Tuple[_ArrayOrScalar[int8]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _2Tuple[_ArrayOrScalar[unsignedinteger[Any]]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _2Tuple[_ArrayOrScalar[signedinteger[Any]]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _2Tuple[_ArrayOrScalar[floating[Any]]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> Union[Tuple[int64, timedelta64], Tuple[_ArrayND[int64], _ArrayND[timedelta64]]]: ... + @overload + def __rdivmod__( + self: _ArrayND[Union[bool_, integer[Any], floating[Any], timedelta64]], + other: _RecursiveSequence, + ) -> _2Tuple[Any]: ... + + @overload + def __add__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __add__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[bool_]: ... # type: ignore[misc] + @overload + def __add__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __add__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __add__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __add__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... # type: ignore[misc] + @overload + def __add__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... # type: ignore[misc] + @overload + def __add__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co) -> _ArrayOrScalar[datetime64]: ... + @overload + def __add__(self: _ArrayND[datetime64], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[datetime64]: ... + @overload + def __add__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __add__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __add__( + self: _ArrayND[Union[bool_, number[Any], timedelta64, datetime64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __radd__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __radd__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[bool_]: ... # type: ignore[misc] + @overload + def __radd__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __radd__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __radd__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __radd__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... # type: ignore[misc] + @overload + def __radd__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... # type: ignore[misc] + @overload + def __radd__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co) -> _ArrayOrScalar[datetime64]: ... + @overload + def __radd__(self: _ArrayND[datetime64], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[datetime64]: ... + @overload + def __radd__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __radd__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __radd__( + self: _ArrayND[Union[bool_, number[Any], timedelta64, datetime64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __sub__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __sub__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> NoReturn: ... + @overload + def __sub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __sub__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __sub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __sub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... # type: ignore[misc] + @overload + def __sub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... # type: ignore[misc] + @overload + def __sub__(self: _ArrayND[datetime64], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[datetime64]: ... + @overload + def __sub__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __sub__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __sub__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __sub__( + self: _ArrayND[Union[bool_, number[Any], timedelta64, datetime64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __rsub__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __rsub__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> NoReturn: ... + @overload + def __rsub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rsub__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rsub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __rsub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... # type: ignore[misc] + @overload + def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... # type: ignore[misc] + @overload + def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co) -> _ArrayOrScalar[datetime64]: ... # type: ignore[misc] + @overload + def __rsub__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __rsub__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __rsub__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __rsub__( + self: _ArrayND[Union[bool_, number[Any], timedelta64, datetime64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __mul__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __mul__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[bool_]: ... # type: ignore[misc] + @overload + def __mul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __mul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __mul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __mul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... # type: ignore[misc] + @overload + def __mul__(self: _ArrayTD64_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __mul__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __mul__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __mul__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __mul__( + self: _ArrayND[Union[bool_, number[Any], timedelta64]], + other: _RecursiveSequence, + ) -> Any: ... + + @overload + def __rmul__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ... + @overload + def __rmul__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayOrScalar[bool_]: ... # type: ignore[misc] + @overload + def __rmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _ArrayOrScalar[unsignedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _ArrayOrScalar[signedinteger[Any]]: ... # type: ignore[misc] + @overload + def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] + @overload + def __rmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> _ArrayOrScalar[complexfloating[Any, Any]]: ... # type: ignore[misc] + @overload + def __rmul__(self: _ArrayTD64_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... + @overload + def __rmul__(self: _ArrayND[object_], other: Any) -> Any: ... + @overload + def __rmul__(self: _ArrayND[Any], other: _ArrayLikeObject_co) -> Any: ... + @overload + def __rmul__( + self: _ArrayND[Union[bool_, number[Any], timedelta64]], + other: _RecursiveSequence, + ) -> Any: ... + def __floordiv__(self, other: ArrayLike) -> Any: ... def __rfloordiv__(self, other: ArrayLike) -> Any: ... def __pow__(self, other: ArrayLike) -> Any: ... def __rpow__(self, other: ArrayLike) -> Any: ... def __truediv__(self, other: ArrayLike) -> Any: ... def __rtruediv__(self, other: ArrayLike) -> Any: ... - def __invert__(self: _ArraySelf) -> Any: ... def __lshift__(self, other: ArrayLike) -> Any: ... def __rlshift__(self, other: ArrayLike) -> Any: ... def __rshift__(self, other: ArrayLike) -> Any: ... @@ -1492,6 +1855,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): def __rxor__(self, other: ArrayLike) -> Any: ... def __or__(self, other: ArrayLike) -> Any: ... def __ror__(self, other: ArrayLike) -> Any: ... + # `np.generic` does not support inplace operations def __iadd__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... def __isub__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... @@ -1505,9 +1869,10 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): def __iand__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... def __ixor__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... def __ior__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... + # Keep `dtype` at the bottom to avoid name conflicts with `np.dtype` @property - def dtype(self) -> _DType: ... + def dtype(self) -> _DType_co: ... # NOTE: while `np.generic` is not technically an instance of `ABCMeta`, # the `@abstractmethod` decorator is herein used to (forcefully) deny @@ -1518,8 +1883,8 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): # See https://github.com/numpy/numpy-stubs/pull/80 for more details. _ScalarType = TypeVar("_ScalarType", bound=generic) -_NBit_co = TypeVar("_NBit_co", covariant=True, bound=NBitBase) -_NBit_co2 = TypeVar("_NBit_co2", covariant=True, bound=NBitBase) +_NBit1 = TypeVar("_NBit1", bound=NBitBase) +_NBit2 = TypeVar("_NBit2", bound=NBitBase) class generic(_ArrayOrScalarCommon): @abstractmethod @@ -1553,7 +1918,7 @@ class generic(_ArrayOrScalarCommon): @property def dtype(self: _ScalarType) -> dtype[_ScalarType]: ... -class number(generic, Generic[_NBit_co]): # type: ignore +class number(generic, Generic[_NBit1]): # type: ignore @property def real(self: _ArraySelf) -> _ArraySelf: ... @property @@ -1577,10 +1942,10 @@ class number(generic, Generic[_NBit_co]): # type: ignore __rpow__: _NumberOp __truediv__: _NumberOp __rtruediv__: _NumberOp - __lt__: _ComparisonOp[_NumberLike] - __le__: _ComparisonOp[_NumberLike] - __gt__: _ComparisonOp[_NumberLike] - __ge__: _ComparisonOp[_NumberLike] + __lt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + __le__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + __gt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + __ge__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] class bool_(generic): def __init__(self, __value: object = ...) -> None: ... @@ -1619,10 +1984,12 @@ class bool_(generic): __rmod__: _BoolMod __divmod__: _BoolDivMod __rdivmod__: _BoolDivMod - __lt__: _ComparisonOp[_NumberLike] - __le__: _ComparisonOp[_NumberLike] - __gt__: _ComparisonOp[_NumberLike] - __ge__: _ComparisonOp[_NumberLike] + __lt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + __le__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + __gt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + __ge__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co] + +bool8 = bool_ class object_(generic): def __init__(self, __value: object = ...) -> None: ... @@ -1631,88 +1998,90 @@ class object_(generic): @property def imag(self: _ArraySelf) -> _ArraySelf: ... +object0 = object_ + class datetime64(generic): @overload def __init__( self, - __value: Union[None, datetime64, _CharLike, dt.datetime] = ..., - __format: Union[_CharLike, Tuple[_CharLike, _IntLike]] = ..., + __value: Union[None, datetime64, _CharLike_co, dt.datetime] = ..., + __format: Union[_CharLike_co, Tuple[_CharLike_co, _IntLike_co]] = ..., ) -> None: ... @overload def __init__( self, __value: int, - __format: Union[_CharLike, Tuple[_CharLike, _IntLike]] + __format: Union[_CharLike_co, Tuple[_CharLike_co, _IntLike_co]] ) -> None: ... - def __add__(self, other: _TD64Like) -> datetime64: ... - def __radd__(self, other: _TD64Like) -> datetime64: ... + def __add__(self, other: _TD64Like_co) -> datetime64: ... + def __radd__(self, other: _TD64Like_co) -> datetime64: ... @overload def __sub__(self, other: datetime64) -> timedelta64: ... @overload - def __sub__(self, other: _TD64Like) -> datetime64: ... + def __sub__(self, other: _TD64Like_co) -> datetime64: ... def __rsub__(self, other: datetime64) -> timedelta64: ... - __lt__: _ComparisonOp[datetime64] - __le__: _ComparisonOp[datetime64] - __gt__: _ComparisonOp[datetime64] - __ge__: _ComparisonOp[datetime64] + __lt__: _ComparisonOp[datetime64, _ArrayLikeDT64_co] + __le__: _ComparisonOp[datetime64, _ArrayLikeDT64_co] + __gt__: _ComparisonOp[datetime64, _ArrayLikeDT64_co] + __ge__: _ComparisonOp[datetime64, _ArrayLikeDT64_co] # Support for `__index__` was added in python 3.8 (bpo-20092) if sys.version_info >= (3, 8): - _IntValue = Union[SupportsInt, _CharLike, SupportsIndex] - _FloatValue = Union[None, _CharLike, SupportsFloat, SupportsIndex] - _ComplexValue = Union[None, _CharLike, SupportsFloat, SupportsComplex, SupportsIndex] + _IntValue = Union[SupportsInt, _CharLike_co, SupportsIndex] + _FloatValue = Union[None, _CharLike_co, SupportsFloat, SupportsIndex] + _ComplexValue = Union[None, _CharLike_co, SupportsFloat, SupportsComplex, SupportsIndex] else: - _IntValue = Union[SupportsInt, _CharLike] - _FloatValue = Union[None, _CharLike, SupportsFloat] - _ComplexValue = Union[None, _CharLike, SupportsFloat, SupportsComplex] + _IntValue = Union[SupportsInt, _CharLike_co] + _FloatValue = Union[None, _CharLike_co, SupportsFloat] + _ComplexValue = Union[None, _CharLike_co, SupportsFloat, SupportsComplex] -class integer(number[_NBit_co]): # type: ignore +class integer(number[_NBit1]): # type: ignore # NOTE: `__index__` is technically defined in the bottom-most # sub-classes (`int64`, `uint32`, etc) def __index__(self) -> int: ... - __truediv__: _IntTrueDiv[_NBit_co] - __rtruediv__: _IntTrueDiv[_NBit_co] - def __mod__(self, value: _IntLike) -> integer: ... - def __rmod__(self, value: _IntLike) -> integer: ... + __truediv__: _IntTrueDiv[_NBit1] + __rtruediv__: _IntTrueDiv[_NBit1] + def __mod__(self, value: _IntLike_co) -> integer: ... + def __rmod__(self, value: _IntLike_co) -> integer: ... def __invert__(self: _IntType) -> _IntType: ... # Ensure that objects annotated as `integer` support bit-wise operations - def __lshift__(self, other: _IntLike) -> integer: ... - def __rlshift__(self, other: _IntLike) -> integer: ... - def __rshift__(self, other: _IntLike) -> integer: ... - def __rrshift__(self, other: _IntLike) -> integer: ... - def __and__(self, other: _IntLike) -> integer: ... - def __rand__(self, other: _IntLike) -> integer: ... - def __or__(self, other: _IntLike) -> integer: ... - def __ror__(self, other: _IntLike) -> integer: ... - def __xor__(self, other: _IntLike) -> integer: ... - def __rxor__(self, other: _IntLike) -> integer: ... - -class signedinteger(integer[_NBit_co]): + def __lshift__(self, other: _IntLike_co) -> integer: ... + def __rlshift__(self, other: _IntLike_co) -> integer: ... + def __rshift__(self, other: _IntLike_co) -> integer: ... + def __rrshift__(self, other: _IntLike_co) -> integer: ... + def __and__(self, other: _IntLike_co) -> integer: ... + def __rand__(self, other: _IntLike_co) -> integer: ... + def __or__(self, other: _IntLike_co) -> integer: ... + def __ror__(self, other: _IntLike_co) -> integer: ... + def __xor__(self, other: _IntLike_co) -> integer: ... + def __rxor__(self, other: _IntLike_co) -> integer: ... + +class signedinteger(integer[_NBit1]): def __init__(self, __value: _IntValue = ...) -> None: ... - __add__: _SignedIntOp[_NBit_co] - __radd__: _SignedIntOp[_NBit_co] - __sub__: _SignedIntOp[_NBit_co] - __rsub__: _SignedIntOp[_NBit_co] - __mul__: _SignedIntOp[_NBit_co] - __rmul__: _SignedIntOp[_NBit_co] - __floordiv__: _SignedIntOp[_NBit_co] - __rfloordiv__: _SignedIntOp[_NBit_co] - __pow__: _SignedIntOp[_NBit_co] - __rpow__: _SignedIntOp[_NBit_co] - __lshift__: _SignedIntBitOp[_NBit_co] - __rlshift__: _SignedIntBitOp[_NBit_co] - __rshift__: _SignedIntBitOp[_NBit_co] - __rrshift__: _SignedIntBitOp[_NBit_co] - __and__: _SignedIntBitOp[_NBit_co] - __rand__: _SignedIntBitOp[_NBit_co] - __xor__: _SignedIntBitOp[_NBit_co] - __rxor__: _SignedIntBitOp[_NBit_co] - __or__: _SignedIntBitOp[_NBit_co] - __ror__: _SignedIntBitOp[_NBit_co] - __mod__: _SignedIntMod[_NBit_co] - __rmod__: _SignedIntMod[_NBit_co] - __divmod__: _SignedIntDivMod[_NBit_co] - __rdivmod__: _SignedIntDivMod[_NBit_co] + __add__: _SignedIntOp[_NBit1] + __radd__: _SignedIntOp[_NBit1] + __sub__: _SignedIntOp[_NBit1] + __rsub__: _SignedIntOp[_NBit1] + __mul__: _SignedIntOp[_NBit1] + __rmul__: _SignedIntOp[_NBit1] + __floordiv__: _SignedIntOp[_NBit1] + __rfloordiv__: _SignedIntOp[_NBit1] + __pow__: _SignedIntOp[_NBit1] + __rpow__: _SignedIntOp[_NBit1] + __lshift__: _SignedIntBitOp[_NBit1] + __rlshift__: _SignedIntBitOp[_NBit1] + __rshift__: _SignedIntBitOp[_NBit1] + __rrshift__: _SignedIntBitOp[_NBit1] + __and__: _SignedIntBitOp[_NBit1] + __rand__: _SignedIntBitOp[_NBit1] + __xor__: _SignedIntBitOp[_NBit1] + __rxor__: _SignedIntBitOp[_NBit1] + __or__: _SignedIntBitOp[_NBit1] + __ror__: _SignedIntBitOp[_NBit1] + __mod__: _SignedIntMod[_NBit1] + __rmod__: _SignedIntMod[_NBit1] + __divmod__: _SignedIntDivMod[_NBit1] + __rdivmod__: _SignedIntDivMod[_NBit1] int8 = signedinteger[_8Bit] int16 = signedinteger[_16Bit] @@ -1730,8 +2099,8 @@ longlong = signedinteger[_NBitLongLong] class timedelta64(generic): def __init__( self, - __value: Union[None, int, _CharLike, dt.timedelta, timedelta64] = ..., - __format: Union[_CharLike, Tuple[_CharLike, _IntLike]] = ..., + __value: Union[None, int, _CharLike_co, dt.timedelta, timedelta64] = ..., + __format: Union[_CharLike_co, Tuple[_CharLike_co, _IntLike_co]] = ..., ) -> None: ... def __int__(self) -> int: ... def __float__(self) -> float: ... @@ -1739,12 +2108,12 @@ class timedelta64(generic): def __neg__(self: _ArraySelf) -> _ArraySelf: ... def __pos__(self: _ArraySelf) -> _ArraySelf: ... def __abs__(self: _ArraySelf) -> _ArraySelf: ... - def __add__(self, other: _TD64Like) -> timedelta64: ... - def __radd__(self, other: _TD64Like) -> timedelta64: ... - def __sub__(self, other: _TD64Like) -> timedelta64: ... - def __rsub__(self, other: _TD64Like) -> timedelta64: ... - def __mul__(self, other: _FloatLike) -> timedelta64: ... - def __rmul__(self, other: _FloatLike) -> timedelta64: ... + def __add__(self, other: _TD64Like_co) -> timedelta64: ... + def __radd__(self, other: _TD64Like_co) -> timedelta64: ... + def __sub__(self, other: _TD64Like_co) -> timedelta64: ... + def __rsub__(self, other: _TD64Like_co) -> timedelta64: ... + def __mul__(self, other: _FloatLike_co) -> timedelta64: ... + def __rmul__(self, other: _FloatLike_co) -> timedelta64: ... __truediv__: _TD64Div[float64] __floordiv__: _TD64Div[int64] def __rtruediv__(self, other: timedelta64) -> float64: ... @@ -1753,38 +2122,38 @@ class timedelta64(generic): def __rmod__(self, other: timedelta64) -> timedelta64: ... def __divmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ... def __rdivmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ... - __lt__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] - __le__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] - __gt__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] - __ge__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] + __lt__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co] + __le__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co] + __gt__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co] + __ge__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co] -class unsignedinteger(integer[_NBit_co]): +class unsignedinteger(integer[_NBit1]): # NOTE: `uint64 + signedinteger -> float64` def __init__(self, __value: _IntValue = ...) -> None: ... - __add__: _UnsignedIntOp[_NBit_co] - __radd__: _UnsignedIntOp[_NBit_co] - __sub__: _UnsignedIntOp[_NBit_co] - __rsub__: _UnsignedIntOp[_NBit_co] - __mul__: _UnsignedIntOp[_NBit_co] - __rmul__: _UnsignedIntOp[_NBit_co] - __floordiv__: _UnsignedIntOp[_NBit_co] - __rfloordiv__: _UnsignedIntOp[_NBit_co] - __pow__: _UnsignedIntOp[_NBit_co] - __rpow__: _UnsignedIntOp[_NBit_co] - __lshift__: _UnsignedIntBitOp[_NBit_co] - __rlshift__: _UnsignedIntBitOp[_NBit_co] - __rshift__: _UnsignedIntBitOp[_NBit_co] - __rrshift__: _UnsignedIntBitOp[_NBit_co] - __and__: _UnsignedIntBitOp[_NBit_co] - __rand__: _UnsignedIntBitOp[_NBit_co] - __xor__: _UnsignedIntBitOp[_NBit_co] - __rxor__: _UnsignedIntBitOp[_NBit_co] - __or__: _UnsignedIntBitOp[_NBit_co] - __ror__: _UnsignedIntBitOp[_NBit_co] - __mod__: _UnsignedIntMod[_NBit_co] - __rmod__: _UnsignedIntMod[_NBit_co] - __divmod__: _UnsignedIntDivMod[_NBit_co] - __rdivmod__: _UnsignedIntDivMod[_NBit_co] + __add__: _UnsignedIntOp[_NBit1] + __radd__: _UnsignedIntOp[_NBit1] + __sub__: _UnsignedIntOp[_NBit1] + __rsub__: _UnsignedIntOp[_NBit1] + __mul__: _UnsignedIntOp[_NBit1] + __rmul__: _UnsignedIntOp[_NBit1] + __floordiv__: _UnsignedIntOp[_NBit1] + __rfloordiv__: _UnsignedIntOp[_NBit1] + __pow__: _UnsignedIntOp[_NBit1] + __rpow__: _UnsignedIntOp[_NBit1] + __lshift__: _UnsignedIntBitOp[_NBit1] + __rlshift__: _UnsignedIntBitOp[_NBit1] + __rshift__: _UnsignedIntBitOp[_NBit1] + __rrshift__: _UnsignedIntBitOp[_NBit1] + __and__: _UnsignedIntBitOp[_NBit1] + __rand__: _UnsignedIntBitOp[_NBit1] + __xor__: _UnsignedIntBitOp[_NBit1] + __rxor__: _UnsignedIntBitOp[_NBit1] + __or__: _UnsignedIntBitOp[_NBit1] + __ror__: _UnsignedIntBitOp[_NBit1] + __mod__: _UnsignedIntMod[_NBit1] + __rmod__: _UnsignedIntMod[_NBit1] + __divmod__: _UnsignedIntDivMod[_NBit1] + __rdivmod__: _UnsignedIntDivMod[_NBit1] uint8 = unsignedinteger[_8Bit] uint16 = unsignedinteger[_16Bit] @@ -1799,33 +2168,34 @@ uint0 = unsignedinteger[_NBitIntP] uint = unsignedinteger[_NBitInt] ulonglong = unsignedinteger[_NBitLongLong] -class inexact(number[_NBit_co]): ... # type: ignore +class inexact(number[_NBit1]): ... # type: ignore _IntType = TypeVar("_IntType", bound=integer) _FloatType = TypeVar('_FloatType', bound=floating) -class floating(inexact[_NBit_co]): +class floating(inexact[_NBit1]): def __init__(self, __value: _FloatValue = ...) -> None: ... - __add__: _FloatOp[_NBit_co] - __radd__: _FloatOp[_NBit_co] - __sub__: _FloatOp[_NBit_co] - __rsub__: _FloatOp[_NBit_co] - __mul__: _FloatOp[_NBit_co] - __rmul__: _FloatOp[_NBit_co] - __truediv__: _FloatOp[_NBit_co] - __rtruediv__: _FloatOp[_NBit_co] - __floordiv__: _FloatOp[_NBit_co] - __rfloordiv__: _FloatOp[_NBit_co] - __pow__: _FloatOp[_NBit_co] - __rpow__: _FloatOp[_NBit_co] - __mod__: _FloatMod[_NBit_co] - __rmod__: _FloatMod[_NBit_co] - __divmod__: _FloatDivMod[_NBit_co] - __rdivmod__: _FloatDivMod[_NBit_co] + __add__: _FloatOp[_NBit1] + __radd__: _FloatOp[_NBit1] + __sub__: _FloatOp[_NBit1] + __rsub__: _FloatOp[_NBit1] + __mul__: _FloatOp[_NBit1] + __rmul__: _FloatOp[_NBit1] + __truediv__: _FloatOp[_NBit1] + __rtruediv__: _FloatOp[_NBit1] + __floordiv__: _FloatOp[_NBit1] + __rfloordiv__: _FloatOp[_NBit1] + __pow__: _FloatOp[_NBit1] + __rpow__: _FloatOp[_NBit1] + __mod__: _FloatMod[_NBit1] + __rmod__: _FloatMod[_NBit1] + __divmod__: _FloatDivMod[_NBit1] + __rdivmod__: _FloatDivMod[_NBit1] float16 = floating[_16Bit] float32 = floating[_32Bit] float64 = floating[_64Bit] +float128 = floating[_128Bit] half = floating[_NBitHalf] single = floating[_NBitSingle] @@ -1838,28 +2208,29 @@ longfloat = floating[_NBitLongDouble] # It is used to clarify why `complex128`s precision is `_64Bit`, the latter # describing the two 64 bit floats representing its real and imaginary component -class complexfloating(inexact[_NBit_co], Generic[_NBit_co, _NBit_co2]): +class complexfloating(inexact[_NBit1], Generic[_NBit1, _NBit2]): def __init__(self, __value: _ComplexValue = ...) -> None: ... @property - def real(self) -> floating[_NBit_co]: ... # type: ignore[override] - @property - def imag(self) -> floating[_NBit_co2]: ... # type: ignore[override] - def __abs__(self) -> floating[_NBit_co]: ... # type: ignore[override] - __add__: _ComplexOp[_NBit_co] - __radd__: _ComplexOp[_NBit_co] - __sub__: _ComplexOp[_NBit_co] - __rsub__: _ComplexOp[_NBit_co] - __mul__: _ComplexOp[_NBit_co] - __rmul__: _ComplexOp[_NBit_co] - __truediv__: _ComplexOp[_NBit_co] - __rtruediv__: _ComplexOp[_NBit_co] - __floordiv__: _ComplexOp[_NBit_co] - __rfloordiv__: _ComplexOp[_NBit_co] - __pow__: _ComplexOp[_NBit_co] - __rpow__: _ComplexOp[_NBit_co] + def real(self) -> floating[_NBit1]: ... # type: ignore[override] + @property + def imag(self) -> floating[_NBit2]: ... # type: ignore[override] + def __abs__(self) -> floating[_NBit1]: ... # type: ignore[override] + __add__: _ComplexOp[_NBit1] + __radd__: _ComplexOp[_NBit1] + __sub__: _ComplexOp[_NBit1] + __rsub__: _ComplexOp[_NBit1] + __mul__: _ComplexOp[_NBit1] + __rmul__: _ComplexOp[_NBit1] + __truediv__: _ComplexOp[_NBit1] + __rtruediv__: _ComplexOp[_NBit1] + __floordiv__: _ComplexOp[_NBit1] + __rfloordiv__: _ComplexOp[_NBit1] + __pow__: _ComplexOp[_NBit1] + __rpow__: _ComplexOp[_NBit1] complex64 = complexfloating[_32Bit, _32Bit] complex128 = complexfloating[_64Bit, _64Bit] +complex256 = complexfloating[_128Bit, _128Bit] csingle = complexfloating[_NBitSingle, _NBitSingle] singlecomplex = complexfloating[_NBitSingle, _NBitSingle] @@ -1873,7 +2244,7 @@ longcomplex = complexfloating[_NBitLongDouble, _NBitLongDouble] class flexible(generic): ... # type: ignore class void(flexible): - def __init__(self, __value: Union[_IntLike, bytes]): ... + def __init__(self, __value: Union[_IntLike_co, bytes]): ... @property def real(self: _ArraySelf) -> _ArraySelf: ... @property @@ -1882,6 +2253,8 @@ class void(flexible): self, val: ArrayLike, dtype: DTypeLike, offset: int = ... ) -> None: ... +void0 = void + class character(flexible): # type: ignore def __int__(self) -> int: ... def __float__(self) -> float: ... @@ -1897,6 +2270,9 @@ class bytes_(character, bytes): self, __value: str, encoding: str = ..., errors: str = ... ) -> None: ... +string_ = bytes_ +bytes0 = bytes_ + class str_(character, str): @overload def __init__(self, __value: object = ...) -> None: ... diff --git a/numpy/_globals.py b/numpy/_globals.py index 9f44c7729..4a8c266d3 100644 --- a/numpy/_globals.py +++ b/numpy/_globals.py @@ -58,8 +58,20 @@ class _NoValueType: """Special keyword value. The instance of this class may be used as the default value assigned to a - deprecated keyword in order to check if it has been given a user defined - value. + keyword if no other obvious default (e.g., `None`) is suitable, + + Common reasons for using this keyword are: + + - A new keyword is added to a function, and that function forwards its + inputs to another function or method which can be defined outside of + NumPy. For example, ``np.std(x)`` calls ``x.std``, so when a ``keepdims`` + keyword was added that could only be forwarded if the user explicitly + specified ``keepdims``; downstream array libraries may not have added + the same keyword, so adding ``x.std(..., keepdims=keepdims)`` + unconditionally could have broken previously working code. + - A keyword is being deprecated, and a deprecation warning must only be + emitted when the keyword is used. + """ __instance = None def __new__(cls): diff --git a/numpy/char.pyi b/numpy/char.pyi index 0e7342c0b..0e3596bb2 100644 --- a/numpy/char.pyi +++ b/numpy/char.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] equal: Any not_equal: Any @@ -51,3 +53,4 @@ isnumeric: Any isdecimal: Any array: Any asarray: Any +chararray: Any diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index e8d3a381b..f22c86f59 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -75,7 +75,7 @@ from . import fromnumeric from .fromnumeric import * from . import defchararray as char from . import records as rec -from .records import * +from .records import record, recarray, format_parser from .memmap import * from .defchararray import chararray from . import function_base @@ -106,7 +106,7 @@ from . import _methods __all__ = ['char', 'rec', 'memmap'] __all__ += numeric.__all__ __all__ += fromnumeric.__all__ -__all__ += rec.__all__ +__all__ += ['record', 'recarray', 'format_parser'] __all__ += ['chararray'] __all__ += function_base.__all__ __all__ += machar.__all__ diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index 2cbfe52be..6073166a0 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -377,7 +377,7 @@ add_newdoc('numpy.core', 'nditer', ... while not it.finished: ... it[0] = lamdaexpr(*it[1:]) ... it.iternext() - ... return it.operands[0] + ... return it.operands[0] >>> a = np.arange(5) >>> b = np.ones(5) @@ -821,7 +821,7 @@ add_newdoc('numpy.core.multiarray', 'array', ===== ========= =================================================== When ``copy=False`` and a copy is made for other reasons, the result is - the same as if ``copy=True``, with some exceptions for `A`, see the + the same as if ``copy=True``, with some exceptions for 'A', see the Notes section. The default order is 'K'. subok : bool, optional If True, then sub-classes will be passed-through, otherwise diff --git a/numpy/core/_add_newdocs_scalars.py b/numpy/core/_add_newdocs_scalars.py index b9b151224..d31f0037d 100644 --- a/numpy/core/_add_newdocs_scalars.py +++ b/numpy/core/_add_newdocs_scalars.py @@ -6,6 +6,7 @@ platform-dependent information. from numpy.core import dtype from numpy.core import numerictypes as _numerictypes from numpy.core.function_base import add_newdoc +import platform ############################################################################## # @@ -49,6 +50,8 @@ possible_aliases = numeric_type_aliases([ ]) + + def add_newdoc_for_scalar_type(obj, fixed_aliases, doc): # note: `:field: value` is rST syntax which renders as field lists. o = getattr(_numerictypes, obj) @@ -56,7 +59,7 @@ def add_newdoc_for_scalar_type(obj, fixed_aliases, doc): character_code = dtype(o).char canonical_name_doc = "" if obj == o.__name__ else ":Canonical name: `numpy.{}`\n ".format(obj) alias_doc = ''.join(":Alias: `numpy.{}`\n ".format(alias) for alias in fixed_aliases) - alias_doc += ''.join(":Alias on this platform: `numpy.{}`: {}.\n ".format(alias, doc) + alias_doc += ''.join(":Alias on this platform ({} {}): `numpy.{}`: {}.\n ".format(platform.system(), platform.machine(), alias, doc) for (alias_type, alias, doc) in possible_aliases if alias_type is o) docstring = """ {doc} diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py index 94ec8ed34..5c1d6cb63 100644 --- a/numpy/core/arrayprint.py +++ b/numpy/core/arrayprint.py @@ -41,6 +41,7 @@ from .numeric import concatenate, asarray, errstate from .numerictypes import (longlong, intc, int_, float_, complex_, bool_, flexible) from .overrides import array_function_dispatch, set_module +import operator import warnings import contextlib @@ -78,6 +79,7 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None, if legacy not in [None, False, '1.13']: warnings.warn("legacy printing option can currently only be '1.13' or " "`False`", stacklevel=3) + if threshold is not None: # forbid the bad threshold arg suggested by stack overflow, gh-12351 if not isinstance(threshold, numbers.Number): @@ -85,6 +87,14 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None, if np.isnan(threshold): raise ValueError("threshold must be non-NAN, try " "sys.maxsize for untruncated representation") + + if precision is not None: + # forbid the bad precision arg as suggested by issue #18254 + try: + options['precision'] = operator.index(precision) + except TypeError as e: + raise TypeError('precision must be an integer') from e + return options @@ -538,7 +548,7 @@ def array2string(a, max_line_width=None, precision=None, separator : str, optional Inserted between elements. prefix : str, optional - suffix: str, optional + suffix : str, optional The length of the prefix and suffix strings are used to respectively align and wrap the output. An array is typically printed as:: diff --git a/numpy/core/arrayprint.pyi b/numpy/core/arrayprint.pyi index 6aaae0320..d2a5fdef9 100644 --- a/numpy/core/arrayprint.pyi +++ b/numpy/core/arrayprint.pyi @@ -21,12 +21,12 @@ from numpy import ( longdouble, clongdouble, ) -from numpy.typing import ArrayLike, _CharLike, _FloatLike +from numpy.typing import ArrayLike, _CharLike_co, _FloatLike_co if sys.version_info > (3, 8): - from typing import Literal, TypedDict + from typing import Literal, TypedDict, SupportsIndex else: - from typing_extensions import Literal, TypedDict + from typing_extensions import Literal, TypedDict, SupportsIndex _FloatMode = Literal["fixed", "unique", "maxprec", "maxprec_equal"] @@ -40,13 +40,13 @@ class _FormatDict(TypedDict, total=False): complexfloat: Callable[[complexfloating[Any, Any]], str] longcomplexfloat: Callable[[clongdouble], str] void: Callable[[void], str] - numpystr: Callable[[_CharLike], str] + numpystr: Callable[[_CharLike_co], str] object: Callable[[object], str] all: Callable[[object], str] int_kind: Callable[[integer[Any]], str] float_kind: Callable[[floating[Any]], str] complex_kind: Callable[[complexfloating[Any, Any]], str] - str_kind: Callable[[_CharLike], str] + str_kind: Callable[[_CharLike_co], str] class _FormatOptions(TypedDict): precision: int @@ -62,7 +62,7 @@ class _FormatOptions(TypedDict): legacy: Literal[False, "1.13"] def set_printoptions( - precision: Optional[int] = ..., + precision: Optional[SupportsIndex] = ..., threshold: Optional[int] = ..., edgeitems: Optional[int] = ..., linewidth: Optional[int] = ..., @@ -79,7 +79,7 @@ def get_printoptions() -> _FormatOptions: ... def array2string( a: ndarray[Any, Any], max_line_width: Optional[int] = ..., - precision: Optional[int] = ..., + precision: Optional[SupportsIndex] = ..., suppress_small: Optional[bool] = ..., separator: str = ..., prefix: str = ..., @@ -96,7 +96,7 @@ def array2string( legacy: Optional[Literal[False, "1.13"]] = ..., ) -> str: ... def format_float_scientific( - x: _FloatLike, + x: _FloatLike_co, precision: Optional[int] = ..., unique: bool = ..., trim: Literal["k", ".", "0", "-"] = ..., @@ -105,7 +105,7 @@ def format_float_scientific( exp_digits: Optional[int] = ..., ) -> str: ... def format_float_positional( - x: _FloatLike, + x: _FloatLike_co, precision: Optional[int] = ..., unique: bool = ..., fractional: bool = ..., @@ -117,20 +117,20 @@ def format_float_positional( def array_repr( arr: ndarray[Any, Any], max_line_width: Optional[int] = ..., - precision: Optional[int] = ..., + precision: Optional[SupportsIndex] = ..., suppress_small: Optional[bool] = ..., ) -> str: ... def array_str( a: ndarray[Any, Any], max_line_width: Optional[int] = ..., - precision: Optional[int] = ..., + precision: Optional[SupportsIndex] = ..., suppress_small: Optional[bool] = ..., ) -> str: ... def set_string_function( f: Optional[Callable[[ndarray[Any, Any]], str]], repr: bool = ... ) -> None: ... def printoptions( - precision: Optional[int] = ..., + precision: Optional[SupportsIndex] = ..., threshold: Optional[int] = ..., edgeitems: Optional[int] = ..., linewidth: Optional[int] = ..., diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py index 9d7b54a1a..ab1166ad2 100644 --- a/numpy/core/defchararray.py +++ b/numpy/core/defchararray.py @@ -273,7 +273,7 @@ def str_len(a): out : ndarray Output array of integers - See also + See Also -------- builtins.len """ @@ -368,7 +368,7 @@ def mod(a, values): out : ndarray Output array of str or unicode, depending on input types - See also + See Also -------- str.__mod__ @@ -398,7 +398,7 @@ def capitalize(a): Output array of str or unicode, depending on input types - See also + See Also -------- str.capitalize @@ -443,7 +443,7 @@ def center(a, width, fillchar=' '): Output array of str or unicode, depending on input types - See also + See Also -------- str.center @@ -485,7 +485,7 @@ def count(a, sub, start=0, end=None): out : ndarray Output array of ints. - See also + See Also -------- str.count @@ -534,7 +534,7 @@ def decode(a, encoding=None, errors=None): ------- out : ndarray - See also + See Also -------- str.decode @@ -580,7 +580,7 @@ def encode(a, encoding=None, errors=None): ------- out : ndarray - See also + See Also -------- str.encode @@ -620,7 +620,7 @@ def endswith(a, suffix, start=0, end=None): out : ndarray Outputs an array of bools. - See also + See Also -------- str.endswith @@ -672,7 +672,7 @@ def expandtabs(a, tabsize=8): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.expandtabs @@ -708,7 +708,7 @@ def find(a, sub, start=0, end=None): out : ndarray or int Output array of ints. Returns -1 if `sub` is not found. - See also + See Also -------- str.find @@ -737,7 +737,7 @@ def index(a, sub, start=0, end=None): out : ndarray Output array of ints. Returns -1 if `sub` is not found. - See also + See Also -------- find, str.find @@ -765,7 +765,7 @@ def isalnum(a): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.isalnum """ @@ -791,7 +791,7 @@ def isalpha(a): out : ndarray Output array of bools - See also + See Also -------- str.isalpha """ @@ -817,7 +817,7 @@ def isdigit(a): out : ndarray Output array of bools - See also + See Also -------- str.isdigit """ @@ -844,7 +844,7 @@ def islower(a): out : ndarray Output array of bools - See also + See Also -------- str.islower """ @@ -871,7 +871,7 @@ def isspace(a): out : ndarray Output array of bools - See also + See Also -------- str.isspace """ @@ -897,7 +897,7 @@ def istitle(a): out : ndarray Output array of bools - See also + See Also -------- str.istitle """ @@ -924,7 +924,7 @@ def isupper(a): out : ndarray Output array of bools - See also + See Also -------- str.isupper """ @@ -953,7 +953,7 @@ def join(sep, seq): out : ndarray Output array of str or unicode, depending on input types - See also + See Also -------- str.join """ @@ -988,7 +988,7 @@ def ljust(a, width, fillchar=' '): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.ljust @@ -1021,7 +1021,7 @@ def lower(a): out : ndarray, {str, unicode} Output array of str or unicode, depending on input type - See also + See Also -------- str.lower @@ -1066,7 +1066,7 @@ def lstrip(a, chars=None): out : ndarray, {str, unicode} Output array of str or unicode, depending on input type - See also + See Also -------- str.lstrip @@ -1127,7 +1127,7 @@ def partition(a, sep): The output array will have an extra dimension with 3 elements per input element. - See also + See Also -------- str.partition @@ -1163,7 +1163,7 @@ def replace(a, old, new, count=None): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.replace @@ -1197,7 +1197,7 @@ def rfind(a, sub, start=0, end=None): out : ndarray Output array of ints. Return -1 on failure. - See also + See Also -------- str.rfind @@ -1227,7 +1227,7 @@ def rindex(a, sub, start=0, end=None): out : ndarray Output array of ints. - See also + See Also -------- rfind, str.rindex @@ -1258,7 +1258,7 @@ def rjust(a, width, fillchar=' '): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.rjust @@ -1299,7 +1299,7 @@ def rpartition(a, sep): type. The output array will have an extra dimension with 3 elements per input element. - See also + See Also -------- str.rpartition @@ -1339,7 +1339,7 @@ def rsplit(a, sep=None, maxsplit=None): out : ndarray Array of list objects - See also + See Also -------- str.rsplit, split @@ -1378,7 +1378,7 @@ def rstrip(a, chars=None): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.rstrip @@ -1423,7 +1423,7 @@ def split(a, sep=None, maxsplit=None): out : ndarray Array of list objects - See also + See Also -------- str.split, rsplit @@ -1459,7 +1459,7 @@ def splitlines(a, keepends=None): out : ndarray Array of list objects - See also + See Also -------- str.splitlines @@ -1495,7 +1495,7 @@ def startswith(a, prefix, start=0, end=None): out : ndarray Array of booleans - See also + See Also -------- str.startswith @@ -1528,7 +1528,7 @@ def strip(a, chars=None): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.strip @@ -1569,7 +1569,7 @@ def swapcase(a): out : ndarray, {str, unicode} Output array of str or unicode, depending on input type - See also + See Also -------- str.swapcase @@ -1609,7 +1609,7 @@ def title(a): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.title @@ -1654,7 +1654,7 @@ def translate(a, table, deletechars=None): out : ndarray Output array of str or unicode, depending on input type - See also + See Also -------- str.translate @@ -1687,7 +1687,7 @@ def upper(a): out : ndarray, {str, unicode} Output array of str or unicode, depending on input type - See also + See Also -------- str.upper @@ -1726,7 +1726,7 @@ def zfill(a, width): out : ndarray, {str, unicode} Output array of str or unicode, depending on input type - See also + See Also -------- str.zfill @@ -1760,7 +1760,7 @@ def isnumeric(a): out : ndarray, bool Array of booleans of same shape as `a`. - See also + See Also -------- unicode.isnumeric @@ -1792,7 +1792,7 @@ def isdecimal(a): out : ndarray, bool Array of booleans identical in shape to `a`. - See also + See Also -------- unicode.isdecimal @@ -2004,7 +2004,7 @@ class chararray(ndarray): """ Return (self == other) element-wise. - See also + See Also -------- equal """ @@ -2014,7 +2014,7 @@ class chararray(ndarray): """ Return (self != other) element-wise. - See also + See Also -------- not_equal """ @@ -2024,7 +2024,7 @@ class chararray(ndarray): """ Return (self >= other) element-wise. - See also + See Also -------- greater_equal """ @@ -2034,7 +2034,7 @@ class chararray(ndarray): """ Return (self <= other) element-wise. - See also + See Also -------- less_equal """ @@ -2044,7 +2044,7 @@ class chararray(ndarray): """ Return (self > other) element-wise. - See also + See Also -------- greater """ @@ -2054,7 +2054,7 @@ class chararray(ndarray): """ Return (self < other) element-wise. - See also + See Also -------- less """ @@ -2065,7 +2065,7 @@ class chararray(ndarray): Return (self + other), that is string concatenation, element-wise for a pair of array_likes of str or unicode. - See also + See Also -------- add """ @@ -2076,7 +2076,7 @@ class chararray(ndarray): Return (other + self), that is string concatenation, element-wise for a pair of array_likes of `string_` or `unicode_`. - See also + See Also -------- add """ @@ -2087,7 +2087,7 @@ class chararray(ndarray): Return (self * i), that is string multiple concatenation, element-wise. - See also + See Also -------- multiply """ @@ -2098,7 +2098,7 @@ class chararray(ndarray): Return (self * i), that is string multiple concatenation, element-wise. - See also + See Also -------- multiply """ @@ -2110,7 +2110,7 @@ class chararray(ndarray): (interpolation), element-wise for a pair of array_likes of `string_` or `unicode_`. - See also + See Also -------- mod """ @@ -2145,7 +2145,7 @@ class chararray(ndarray): Return a copy of `self` with only the first character of each element capitalized. - See also + See Also -------- char.capitalize @@ -2157,7 +2157,7 @@ class chararray(ndarray): Return a copy of `self` with its elements centered in a string of length `width`. - See also + See Also -------- center """ @@ -2168,7 +2168,7 @@ class chararray(ndarray): Returns an array with the number of non-overlapping occurrences of substring `sub` in the range [`start`, `end`]. - See also + See Also -------- char.count @@ -2179,7 +2179,7 @@ class chararray(ndarray): """ Calls `str.decode` element-wise. - See also + See Also -------- char.decode @@ -2190,7 +2190,7 @@ class chararray(ndarray): """ Calls `str.encode` element-wise. - See also + See Also -------- char.encode @@ -2202,7 +2202,7 @@ class chararray(ndarray): Returns a boolean array which is `True` where the string element in `self` ends with `suffix`, otherwise `False`. - See also + See Also -------- char.endswith @@ -2214,7 +2214,7 @@ class chararray(ndarray): Return a copy of each string element where all tab characters are replaced by one or more spaces. - See also + See Also -------- char.expandtabs @@ -2226,7 +2226,7 @@ class chararray(ndarray): For each element, return the lowest index in the string where substring `sub` is found. - See also + See Also -------- char.find @@ -2237,7 +2237,7 @@ class chararray(ndarray): """ Like `find`, but raises `ValueError` when the substring is not found. - See also + See Also -------- char.index @@ -2250,7 +2250,7 @@ class chararray(ndarray): are alphanumeric and there is at least one character, false otherwise. - See also + See Also -------- char.isalnum @@ -2263,7 +2263,7 @@ class chararray(ndarray): are alphabetic and there is at least one character, false otherwise. - See also + See Also -------- char.isalpha @@ -2275,7 +2275,7 @@ class chararray(ndarray): Returns true for each element if all characters in the string are digits and there is at least one character, false otherwise. - See also + See Also -------- char.isdigit @@ -2288,7 +2288,7 @@ class chararray(ndarray): string are lowercase and there is at least one cased character, false otherwise. - See also + See Also -------- char.islower @@ -2301,7 +2301,7 @@ class chararray(ndarray): characters in the string and there is at least one character, false otherwise. - See also + See Also -------- char.isspace @@ -2313,7 +2313,7 @@ class chararray(ndarray): Returns true for each element if the element is a titlecased string and there is at least one character, false otherwise. - See also + See Also -------- char.istitle @@ -2326,7 +2326,7 @@ class chararray(ndarray): string are uppercase and there is at least one character, false otherwise. - See also + See Also -------- char.isupper @@ -2338,7 +2338,7 @@ class chararray(ndarray): Return a string which is the concatenation of the strings in the sequence `seq`. - See also + See Also -------- char.join @@ -2350,7 +2350,7 @@ class chararray(ndarray): Return an array with the elements of `self` left-justified in a string of length `width`. - See also + See Also -------- char.ljust @@ -2362,7 +2362,7 @@ class chararray(ndarray): Return an array with the elements of `self` converted to lowercase. - See also + See Also -------- char.lower @@ -2374,7 +2374,7 @@ class chararray(ndarray): For each element in `self`, return a copy with the leading characters removed. - See also + See Also -------- char.lstrip @@ -2385,7 +2385,7 @@ class chararray(ndarray): """ Partition each element in `self` around `sep`. - See also + See Also -------- partition """ @@ -2396,7 +2396,7 @@ class chararray(ndarray): For each element in `self`, return a copy of the string with all occurrences of substring `old` replaced by `new`. - See also + See Also -------- char.replace @@ -2409,7 +2409,7 @@ class chararray(ndarray): where substring `sub` is found, such that `sub` is contained within [`start`, `end`]. - See also + See Also -------- char.rfind @@ -2421,7 +2421,7 @@ class chararray(ndarray): Like `rfind`, but raises `ValueError` when the substring `sub` is not found. - See also + See Also -------- char.rindex @@ -2433,7 +2433,7 @@ class chararray(ndarray): Return an array with the elements of `self` right-justified in a string of length `width`. - See also + See Also -------- char.rjust @@ -2444,7 +2444,7 @@ class chararray(ndarray): """ Partition each element in `self` around `sep`. - See also + See Also -------- rpartition """ @@ -2455,7 +2455,7 @@ class chararray(ndarray): For each element in `self`, return a list of the words in the string, using `sep` as the delimiter string. - See also + See Also -------- char.rsplit @@ -2467,7 +2467,7 @@ class chararray(ndarray): For each element in `self`, return a copy with the trailing characters removed. - See also + See Also -------- char.rstrip @@ -2479,7 +2479,7 @@ class chararray(ndarray): For each element in `self`, return a list of the words in the string, using `sep` as the delimiter string. - See also + See Also -------- char.split @@ -2491,7 +2491,7 @@ class chararray(ndarray): For each element in `self`, return a list of the lines in the element, breaking at line boundaries. - See also + See Also -------- char.splitlines @@ -2503,7 +2503,7 @@ class chararray(ndarray): Returns a boolean array which is `True` where the string element in `self` starts with `prefix`, otherwise `False`. - See also + See Also -------- char.startswith @@ -2515,7 +2515,7 @@ class chararray(ndarray): For each element in `self`, return a copy with the leading and trailing characters removed. - See also + See Also -------- char.strip @@ -2527,7 +2527,7 @@ class chararray(ndarray): For each element in `self`, return a copy of the string with uppercase characters converted to lowercase and vice versa. - See also + See Also -------- char.swapcase @@ -2540,7 +2540,7 @@ class chararray(ndarray): string: words start with uppercase characters, all remaining cased characters are lowercase. - See also + See Also -------- char.title @@ -2554,7 +2554,7 @@ class chararray(ndarray): `deletechars` are removed, and the remaining characters have been mapped through the given translation table. - See also + See Also -------- char.translate @@ -2566,7 +2566,7 @@ class chararray(ndarray): Return an array with the elements of `self` converted to uppercase. - See also + See Also -------- char.upper @@ -2578,7 +2578,7 @@ class chararray(ndarray): Return the numeric string left-filled with zeros in a string of length `width`. - See also + See Also -------- char.zfill @@ -2590,7 +2590,7 @@ class chararray(ndarray): For each element in `self`, return True if there are only numeric characters in the element. - See also + See Also -------- char.isnumeric @@ -2602,7 +2602,7 @@ class chararray(ndarray): For each element in `self`, return True if there are only decimal characters in the element. - See also + See Also -------- char.isdecimal diff --git a/numpy/core/einsumfunc.py b/numpy/core/einsumfunc.py index e0942beca..18157641a 100644 --- a/numpy/core/einsumfunc.py +++ b/numpy/core/einsumfunc.py @@ -327,7 +327,7 @@ def _greedy_path(input_sets, output_set, idx_dict, memory_limit): Set that represents the rhs side of the overall einsum subscript idx_dict : dictionary Dictionary of index sizes - memory_limit_limit : int + memory_limit : int The maximum number of elements in a temporary array Returns @@ -1061,14 +1061,12 @@ def einsum(*operands, out=None, optimize=False, **kwargs): See Also -------- einsum_path, dot, inner, outer, tensordot, linalg.multi_dot - - einops: + einops : similar verbose interface is provided by `einops <https://github.com/arogozhnikov/einops>`_ package to cover additional operations: transpose, reshape/flatten, repeat/tile, squeeze/unsqueeze and reductions. - - opt_einsum: + opt_einsum : `opt_einsum <https://optimized-einsum.readthedocs.io/en/stable/>`_ optimizes contraction order for einsum-like expressions in backend-agnostic manner. diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py index 52df1aad9..658b1aca5 100644 --- a/numpy/core/fromnumeric.py +++ b/numpy/core/fromnumeric.py @@ -319,34 +319,34 @@ def choose(a, choices, out=None, mode='raise'): But this omits some subtleties. Here is a fully general summary: - Given an "index" array (`a`) of integers and a sequence of `n` arrays + Given an "index" array (`a`) of integers and a sequence of ``n`` arrays (`choices`), `a` and each choice array are first broadcast, as necessary, to arrays of a common shape; calling these *Ba* and *Bchoices[i], i = 0,...,n-1* we have that, necessarily, ``Ba.shape == Bchoices[i].shape`` - for each `i`. Then, a new array with shape ``Ba.shape`` is created as + for each ``i``. Then, a new array with shape ``Ba.shape`` is created as follows: - * if ``mode=raise`` (the default), then, first of all, each element of - `a` (and thus `Ba`) must be in the range `[0, n-1]`; now, suppose that - `i` (in that range) is the value at the `(j0, j1, ..., jm)` position - in `Ba` - then the value at the same position in the new array is the - value in `Bchoices[i]` at that same position; + * if ``mode='raise'`` (the default), then, first of all, each element of + ``a`` (and thus ``Ba``) must be in the range ``[0, n-1]``; now, suppose + that ``i`` (in that range) is the value at the ``(j0, j1, ..., jm)`` + position in ``Ba`` - then the value at the same position in the new array + is the value in ``Bchoices[i]`` at that same position; - * if ``mode=wrap``, values in `a` (and thus `Ba`) may be any (signed) + * if ``mode='wrap'``, values in `a` (and thus `Ba`) may be any (signed) integer; modular arithmetic is used to map integers outside the range `[0, n-1]` back into that range; and then the new array is constructed as above; - * if ``mode=clip``, values in `a` (and thus `Ba`) may be any (signed) - integer; negative integers are mapped to 0; values greater than `n-1` - are mapped to `n-1`; and then the new array is constructed as above. + * if ``mode='clip'``, values in `a` (and thus ``Ba``) may be any (signed) + integer; negative integers are mapped to 0; values greater than ``n-1`` + are mapped to ``n-1``; and then the new array is constructed as above. Parameters ---------- a : int array - This array must contain integers in `[0, n-1]`, where `n` is the number - of choices, unless ``mode=wrap`` or ``mode=clip``, in which cases any - integers are permissible. + This array must contain integers in ``[0, n-1]``, where ``n`` is the + number of choices, unless ``mode=wrap`` or ``mode=clip``, in which + cases any integers are permissible. choices : sequence of arrays Choice arrays. `a` and all of the choices must be broadcastable to the same shape. If `choices` is itself an array (not recommended), then @@ -355,12 +355,12 @@ def choose(a, choices, out=None, mode='raise'): out : array, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. Note that `out` is always - buffered if `mode='raise'`; use other modes for better performance. + buffered if ``mode='raise'``; use other modes for better performance. mode : {'raise' (default), 'wrap', 'clip'}, optional - Specifies how indices outside `[0, n-1]` will be treated: + Specifies how indices outside ``[0, n-1]`` will be treated: * 'raise' : an exception is raised - * 'wrap' : value becomes value mod `n` + * 'wrap' : value becomes value mod ``n`` * 'clip' : values < 0 are mapped to 0, values > n-1 are mapped to n-1 Returns @@ -1381,7 +1381,7 @@ def resize(a, new_shape): -------- np.reshape : Reshape an array without changing the total size. np.pad : Enlarge and pad an array. - np.repeat: Repeat elements of an array. + np.repeat : Repeat elements of an array. ndarray.resize : resize an array in-place. Notes @@ -2007,7 +2007,7 @@ def compress(condition, a, axis=None, out=None): -------- take, choose, diag, diagonal, select ndarray.compress : Equivalent method in ndarray - extract: Equivalent method when working on 1-D arrays + extract : Equivalent method when working on 1-D arrays :ref:`ufuncs-output-type` Examples @@ -2475,14 +2475,11 @@ def cumsum(a, axis=None, dtype=None, out=None): result has the same size as `a`, and the same shape as `a` if `axis` is not None or `a` is a 1-d array. - See Also -------- sum : Sum array elements. - trapz : Integration of array values using the composite trapezoidal rule. - - diff : Calculate the n-th discrete difference along given axis. + diff : Calculate the n-th discrete difference along given axis. Notes ----- diff --git a/numpy/core/fromnumeric.pyi b/numpy/core/fromnumeric.pyi index 3b147e1d7..fc7f28a59 100644 --- a/numpy/core/fromnumeric.pyi +++ b/numpy/core/fromnumeric.pyi @@ -23,9 +23,8 @@ from numpy.typing import ( ArrayLike, _ShapeLike, _Shape, - _IntLike, - _BoolLike, - _NumberLike, + _IntLike_co, + _NumberLike_co, ) if sys.version_info >= (3, 8): @@ -98,7 +97,7 @@ def choose( ) -> _ScalarIntOrBool: ... @overload def choose( - a: Union[_IntLike, _BoolLike], choices: ArrayLike, out: Optional[ndarray] = ..., mode: _ModeKind = ... + a: _IntLike_co, choices: ArrayLike, out: Optional[ndarray] = ..., mode: _ModeKind = ... ) -> Union[integer, bool_]: ... @overload def choose( @@ -250,7 +249,7 @@ def sum( dtype: DTypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -260,7 +259,7 @@ def sum( dtype: DTypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -324,7 +323,7 @@ def amax( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -333,7 +332,7 @@ def amax( axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -342,7 +341,7 @@ def amax( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -351,7 +350,7 @@ def amin( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -360,7 +359,7 @@ def amin( axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -369,7 +368,7 @@ def amin( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @@ -387,7 +386,7 @@ def prod( dtype: DTypeLike = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -397,7 +396,7 @@ def prod( dtype: DTypeLike = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -407,7 +406,7 @@ def prod( dtype: DTypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... def cumprod( @@ -424,7 +423,7 @@ def around( ) -> _Number: ... @overload def around( - a: _NumberLike, decimals: int = ..., out: Optional[ndarray] = ... + a: _NumberLike_co, decimals: int = ..., out: Optional[ndarray] = ... ) -> number: ... @overload def around( diff --git a/numpy/core/function_base.pyi b/numpy/core/function_base.pyi index 1490bed4a..d4543f281 100644 --- a/numpy/core/function_base.pyi +++ b/numpy/core/function_base.pyi @@ -2,20 +2,17 @@ import sys from typing import overload, Tuple, Union, Sequence, Any from numpy import ndarray, inexact -from numpy.typing import ArrayLike, DTypeLike, _SupportsArray, _NumberLike +from numpy.typing import ArrayLike, DTypeLike, _SupportsArray, _NumberLike_co if sys.version_info >= (3, 8): from typing import SupportsIndex, Literal else: - from typing_extensions import Literal, Protocol - - class SupportsIndex(Protocol): - def __index__(self) -> int: ... + from typing_extensions import SupportsIndex, Literal # TODO: wait for support for recursive types _ArrayLikeNested = Sequence[Sequence[Any]] _ArrayLikeNumber = Union[ - _NumberLike, Sequence[_NumberLike], ndarray, _SupportsArray, _ArrayLikeNested + _NumberLike_co, Sequence[_NumberLike_co], ndarray, _SupportsArray, _ArrayLikeNested ] @overload def linspace( diff --git a/numpy/core/include/numpy/random/distributions.h b/numpy/core/include/numpy/random/distributions.h index c474c4d14..3ffacc8f9 100644 --- a/numpy/core/include/numpy/random/distributions.h +++ b/numpy/core/include/numpy/random/distributions.h @@ -1,6 +1,10 @@ #ifndef _RANDOMDGEN__DISTRIBUTIONS_H_ #define _RANDOMDGEN__DISTRIBUTIONS_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include "Python.h" #include "numpy/npy_common.h" #include <stddef.h> @@ -197,4 +201,8 @@ static NPY_INLINE double next_double(bitgen_t *bitgen_state) { return bitgen_state->next_double(bitgen_state->state); } +#ifdef __cplusplus +} +#endif + #endif diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py index 07179a627..b7277ac24 100644 --- a/numpy/core/multiarray.py +++ b/numpy/core/multiarray.py @@ -1441,7 +1441,7 @@ def is_busday(dates, weekmask=None, holidays=None, busdaycal=None, out=None): See Also -------- - busdaycalendar: An object that specifies a custom set of valid days. + busdaycalendar : An object that specifies a custom set of valid days. busday_offset : Applies an offset counted in valid days. busday_count : Counts how many valid days are in a half-open date range. @@ -1516,7 +1516,7 @@ def busday_offset(dates, offsets, roll=None, weekmask=None, holidays=None, See Also -------- - busdaycalendar: An object that specifies a custom set of valid days. + busdaycalendar : An object that specifies a custom set of valid days. is_busday : Returns a boolean array indicating valid days. busday_count : Counts how many valid days are in a half-open date range. @@ -1598,7 +1598,7 @@ def busday_count(begindates, enddates, weekmask=None, holidays=None, See Also -------- - busdaycalendar: An object that specifies a custom set of valid days. + busdaycalendar : An object that specifies a custom set of valid days. is_busday : Returns a boolean array indicating valid days. busday_offset : Applies an offset counted in valid days. diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index c95c48d71..086439656 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -299,7 +299,7 @@ def full(shape, fill_value, dtype=None, order='C', *, like=None): Fill value. dtype : data-type, optional The desired data-type for the array The default, None, means - `np.array(fill_value).dtype`. + ``np.array(fill_value).dtype``. order : {'C', 'F'}, optional Whether to store multidimensional data in C- or Fortran-contiguous (row- or column-wise) order in memory. @@ -1427,12 +1427,11 @@ def moveaxis(a, source, destination): See Also -------- - transpose: Permute the dimensions of an array. - swapaxes: Interchange two axes of an array. + transpose : Permute the dimensions of an array. + swapaxes : Interchange two axes of an array. Examples -------- - >>> x = np.zeros((3, 4, 5)) >>> np.moveaxis(x, 0, -1).shape (4, 5, 3) diff --git a/numpy/core/records.py b/numpy/core/records.py index 00d456658..a626a0589 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -45,7 +45,10 @@ from numpy.core.overrides import set_module from .arrayprint import get_printoptions # All of the functions allow formats to be a dtype -__all__ = ['record', 'recarray', 'format_parser'] +__all__ = [ + 'record', 'recarray', 'format_parser', + 'fromarrays', 'fromrecords', 'fromstring', 'fromfile', 'array', +] ndarray = sb.ndarray @@ -962,16 +965,16 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, Parameters ---------- - obj: any + obj : any Input object. See Notes for details on how various input types are treated. - dtype: data-type, optional + dtype : data-type, optional Valid dtype for array. - shape: int or tuple of ints, optional + shape : int or tuple of ints, optional Shape of each array. - offset: int, optional + offset : int, optional Position in the file or buffer to start reading from. - strides: tuple of ints, optional + strides : tuple of ints, optional Buffer (`buf`) is interpreted according to these strides (strides define how many bytes each array element, row, column, etc. occupy in memory). @@ -979,7 +982,7 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, If `dtype` is ``None``, these arguments are passed to `numpy.format_parser` to construct a dtype. See that function for detailed documentation. - copy: bool, optional + copy : bool, optional Whether to copy the input object (True), or to use a reference instead. This option only applies when the input is an ndarray or recarray. Defaults to True. diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 2d85e0718..378d93c06 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -317,8 +317,8 @@ def pyod(filename): out : seq list of lines of od output - Note - ---- + Notes + ----- We only implement enough to get the necessary information for long double representation, this is not intended as a compatible replacement for od. """ diff --git a/numpy/core/shape_base.py b/numpy/core/shape_base.py index e90358ba5..89e98ab30 100644 --- a/numpy/core/shape_base.py +++ b/numpy/core/shape_base.py @@ -607,7 +607,7 @@ def _block_info_recursion(arrays, max_depth, result_ndim, depth=0): The arrays to check max_depth : list of int The number of nested lists - result_ndim: int + result_ndim : int The number of dimensions in thefinal array. Returns diff --git a/numpy/core/shape_base.pyi b/numpy/core/shape_base.pyi index b20598b1a..ec40a8814 100644 --- a/numpy/core/shape_base.pyi +++ b/numpy/core/shape_base.pyi @@ -7,9 +7,7 @@ from numpy.typing import ArrayLike if sys.version_info >= (3, 8): from typing import SupportsIndex else: - from typing_extensions import Protocol - class SupportsIndex(Protocol): - def __index__(self) -> int: ... + from typing_extensions import SupportsIndex _ArrayType = TypeVar("_ArrayType", bound=ndarray) diff --git a/numpy/core/src/_simd/_simd.dispatch.c.src b/numpy/core/src/_simd/_simd.dispatch.c.src index af42192a9..e5b58a8d2 100644 --- a/numpy/core/src/_simd/_simd.dispatch.c.src +++ b/numpy/core/src/_simd/_simd.dispatch.c.src @@ -23,7 +23,8 @@ * #mul_sup = 1, 1, 1, 1, 1, 1, 0, 0, 1, 1# * #div_sup = 0, 0, 0, 0, 0, 0, 0, 0, 1, 1# * #fused_sup = 0, 0, 0, 0, 0, 0, 0, 0, 1, 1# - * #sum_sup = 0, 0, 0, 0, 1, 0, 0, 0, 1, 1# + * #sumup_sup = 1, 0, 1, 0, 0, 0, 0, 0, 0, 0# + * #sum_sup = 0, 0, 0, 0, 1, 0, 1, 0, 1, 1# * #rev64_sup = 1, 1, 1, 1, 1, 1, 0, 0, 1, 0# * #ncont_sup = 0, 0, 0, 0, 1, 1, 1, 1, 1, 1# * #shl_imm = 0, 0, 15, 15, 31, 31, 63, 63, 0, 0# @@ -365,6 +366,10 @@ SIMD_IMPL_INTRIN_3(@intrin@_@sfx@, v@sfx@, v@sfx@, v@sfx@, v@sfx@) SIMD_IMPL_INTRIN_1(sum_@sfx@, @sfx@, v@sfx@) #endif // sum_sup +#if @sumup_sup@ +SIMD_IMPL_INTRIN_1(sumup_@sfx@, @esfx@, v@sfx@) +#endif // sumup_sup + /*************************** * Math ***************************/ @@ -452,7 +457,8 @@ static PyMethodDef simd__intrinsics_methods[] = { * #mul_sup = 1, 1, 1, 1, 1, 1, 0, 0, 1, 1# * #div_sup = 0, 0, 0, 0, 0, 0, 0, 0, 1, 1# * #fused_sup = 0, 0, 0, 0, 0, 0, 0, 0, 1, 1# - * #sum_sup = 0, 0, 0, 0, 1, 0, 0, 0, 1, 1# + * #sumup_sup = 1, 0, 1, 0, 0, 0, 0, 0, 0, 0# + * #sum_sup = 0, 0, 0, 0, 1, 0, 1, 0, 1, 1# * #rev64_sup = 1, 1, 1, 1, 1, 1, 0, 0, 1, 0# * #ncont_sup = 0, 0, 0, 0, 1, 1, 1, 1, 1, 1# * #shl_imm = 0, 0, 15, 15, 31, 31, 63, 63, 0, 0# @@ -574,6 +580,9 @@ SIMD_INTRIN_DEF(@intrin@_@sfx@) SIMD_INTRIN_DEF(sum_@sfx@) #endif // sum_sup +#if @sumup_sup@ +SIMD_INTRIN_DEF(sumup_@sfx@) +#endif // sumup_sup /*************************** * Math ***************************/ diff --git a/numpy/core/src/common/simd/avx2/arithmetic.h b/numpy/core/src/common/simd/avx2/arithmetic.h index 3a3a82798..4b8258759 100644 --- a/numpy/core/src/common/simd/avx2/arithmetic.h +++ b/numpy/core/src/common/simd/avx2/arithmetic.h @@ -5,6 +5,7 @@ #ifndef _NPY_SIMD_AVX2_ARITHMETIC_H #define _NPY_SIMD_AVX2_ARITHMETIC_H +#include "../sse/utils.h" /*************************** * Addition ***************************/ @@ -117,8 +118,11 @@ } #endif // !NPY_HAVE_FMA3 -// Horizontal add: Calculates the sum of all vector elements. -NPY_FINLINE npy_uint32 npyv_sum_u32(__m256i a) +/*************************** + * Summation + ***************************/ +// reduce sum across vector +NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) { __m256i s0 = _mm256_hadd_epi32(a, a); s0 = _mm256_hadd_epi32(s0, s0); @@ -127,7 +131,14 @@ NPY_FINLINE npy_uint32 npyv_sum_u32(__m256i a) return _mm_cvtsi128_si32(s1); } -NPY_FINLINE float npyv_sum_f32(__m256 a) +NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) +{ + __m256i two = _mm256_add_epi64(a, _mm256_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2))); + __m128i one = _mm_add_epi64(_mm256_castsi256_si128(two), _mm256_extracti128_si256(two, 1)); + return (npy_uint64)npyv128_cvtsi128_si64(one); +} + +NPY_FINLINE float npyv_sum_f32(npyv_f32 a) { __m256 sum_halves = _mm256_hadd_ps(a, a); sum_halves = _mm256_hadd_ps(sum_halves, sum_halves); @@ -137,7 +148,7 @@ NPY_FINLINE float npyv_sum_f32(__m256 a) return _mm_cvtss_f32(sum); } -NPY_FINLINE double npyv_sum_f64(__m256d a) +NPY_FINLINE double npyv_sum_f64(npyv_f64 a) { __m256d sum_halves = _mm256_hadd_pd(a, a); __m128d lo = _mm256_castpd256_pd128(sum_halves); @@ -146,6 +157,24 @@ NPY_FINLINE double npyv_sum_f64(__m256d a) return _mm_cvtsd_f64(sum); } +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ + __m256i four = _mm256_sad_epu8(a, _mm256_setzero_si256()); + __m128i two = _mm_add_epi16(_mm256_castsi256_si128(four), _mm256_extracti128_si256(four, 1)); + __m128i one = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two)); + return (npy_uint16)_mm_cvtsi128_si32(one); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const npyv_u16 even_mask = _mm256_set1_epi32(0x0000FFFF); + __m256i even = _mm256_and_si256(a, even_mask); + __m256i odd = _mm256_srli_epi32(a, 16); + __m256i eight = _mm256_add_epi32(even, odd); + return npyv_sum_u32(eight); +} + #endif // _NPY_SIMD_AVX2_ARITHMETIC_H diff --git a/numpy/core/src/common/simd/avx512/arithmetic.h b/numpy/core/src/common/simd/avx512/arithmetic.h index 6f668f439..450da7ea5 100644 --- a/numpy/core/src/common/simd/avx512/arithmetic.h +++ b/numpy/core/src/common/simd/avx512/arithmetic.h @@ -6,7 +6,7 @@ #define _NPY_SIMD_AVX512_ARITHMETIC_H #include "../avx2/utils.h" - +#include "../sse/utils.h" /*************************** * Addition ***************************/ @@ -130,7 +130,7 @@ NPY_FINLINE __m512i npyv_mul_u8(__m512i a, __m512i b) #define npyv_nmulsub_f64 _mm512_fnmsub_pd /*************************** - * Reduce Sum: Calculates the sum of all vector elements. + * Summation: Calculates the sum of all vector elements. * there are three ways to implement reduce sum for AVX512: * 1- split(256) /add /split(128) /add /hadd /hadd /extract * 2- shuff(cross) /add /shuff(cross) /add /shuff /add /shuff /add /extract @@ -144,19 +144,29 @@ NPY_FINLINE __m512i npyv_mul_u8(__m512i a, __m512i b) * The third one is almost the same as the second one but only works for * intel compiler/GCC 7.1/Clang 4, we still need to support older GCC. ***************************/ - -NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) -{ - __m256i half = _mm256_add_epi32(npyv512_lower_si256(a), npyv512_higher_si256(a)); - __m128i quarter = _mm_add_epi32(_mm256_castsi256_si128(half), _mm256_extracti128_si256(half, 1)); - quarter = _mm_hadd_epi32(quarter, quarter); - return _mm_cvtsi128_si32(_mm_hadd_epi32(quarter, quarter)); -} - +// reduce sum across vector #ifdef NPY_HAVE_AVX512F_REDUCE + #define npyv_sum_u32 _mm512_reduce_add_epi32 + #define npyv_sum_u64 _mm512_reduce_add_epi64 #define npyv_sum_f32 _mm512_reduce_add_ps #define npyv_sum_f64 _mm512_reduce_add_pd #else + NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) + { + __m256i half = _mm256_add_epi32(npyv512_lower_si256(a), npyv512_higher_si256(a)); + __m128i quarter = _mm_add_epi32(_mm256_castsi256_si128(half), _mm256_extracti128_si256(half, 1)); + quarter = _mm_hadd_epi32(quarter, quarter); + return _mm_cvtsi128_si32(_mm_hadd_epi32(quarter, quarter)); + } + + NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) + { + __m256i four = _mm256_add_epi64(npyv512_lower_si256(a), npyv512_higher_si256(a)); + __m256i two = _mm256_add_epi64(four, _mm256_shuffle_epi32(four, _MM_SHUFFLE(1, 0, 3, 2))); + __m128i one = _mm_add_epi64(_mm256_castsi256_si128(two), _mm256_extracti128_si256(two, 1)); + return (npy_uint64)npyv128_cvtsi128_si64(one); + } + NPY_FINLINE float npyv_sum_f32(npyv_f32 a) { __m512 h64 = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(3, 2, 3, 2)); @@ -169,6 +179,7 @@ NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) __m512 sum4 = _mm512_add_ps(sum8, h4); return _mm_cvtss_f32(_mm512_castps512_ps128(sum4)); } + NPY_FINLINE double npyv_sum_f64(npyv_f64 a) { __m512d h64 = _mm512_shuffle_f64x2(a, a, _MM_SHUFFLE(3, 2, 3, 2)); @@ -181,4 +192,29 @@ NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) } #endif +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ +#ifdef NPY_HAVE_AVX512BW + __m512i eight = _mm512_sad_epu8(a, _mm512_setzero_si512()); + __m256i four = _mm256_add_epi16(npyv512_lower_si256(eight), npyv512_higher_si256(eight)); +#else + __m256i lo_four = _mm256_sad_epu8(npyv512_lower_si256(a), _mm256_setzero_si256()); + __m256i hi_four = _mm256_sad_epu8(npyv512_higher_si256(a), _mm256_setzero_si256()); + __m256i four = _mm256_add_epi16(lo_four, hi_four); +#endif + __m128i two = _mm_add_epi16(_mm256_castsi256_si128(four), _mm256_extracti128_si256(four, 1)); + __m128i one = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two)); + return (npy_uint16)_mm_cvtsi128_si32(one); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const npyv_u16 even_mask = _mm512_set1_epi32(0x0000FFFF); + __m512i even = _mm512_and_si512(a, even_mask); + __m512i odd = _mm512_srli_epi32(a, 16); + __m512i ff = _mm512_add_epi32(even, odd); + return npyv_sum_u32(ff); +} + #endif // _NPY_SIMD_AVX512_ARITHMETIC_H diff --git a/numpy/core/src/common/simd/neon/arithmetic.h b/numpy/core/src/common/simd/neon/arithmetic.h index 1c8bde15a..69a49f571 100644 --- a/numpy/core/src/common/simd/neon/arithmetic.h +++ b/numpy/core/src/common/simd/neon/arithmetic.h @@ -131,12 +131,21 @@ { return vfmsq_f64(vnegq_f64(c), a, b); } #endif // NPY_SIMD_F64 -// Horizontal add: Calculates the sum of all vector elements. +/*************************** + * Summation + ***************************/ +// reduce sum across vector #if NPY_SIMD_F64 #define npyv_sum_u32 vaddvq_u32 + #define npyv_sum_u64 vaddvq_u64 #define npyv_sum_f32 vaddvq_f32 #define npyv_sum_f64 vaddvq_f64 #else + NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) + { + return vget_lane_u64(vadd_u64(vget_low_u64(a), vget_high_u64(a)),0); + } + NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) { uint32x2_t a0 = vpadd_u32(vget_low_u32(a), vget_high_u32(a)); @@ -150,4 +159,24 @@ } #endif +// expand the source vector and performs sum reduce +#if NPY_SIMD_F64 + #define npyv_sumup_u8 vaddlvq_u8 + #define npyv_sumup_u16 vaddlvq_u16 +#else + NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) + { + uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(a)); + uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0)); + return vget_lane_u32(vpadd_u32(t1, t1), 0); + } + + NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) + { + uint32x4_t t0 = vpaddlq_u16(a); + uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0)); + return vget_lane_u32(vpadd_u32(t1, t1), 0); + } +#endif + #endif // _NPY_SIMD_NEON_ARITHMETIC_H diff --git a/numpy/core/src/common/simd/sse/arithmetic.h b/numpy/core/src/common/simd/sse/arithmetic.h index faf5685d9..c21b7da2d 100644 --- a/numpy/core/src/common/simd/sse/arithmetic.h +++ b/numpy/core/src/common/simd/sse/arithmetic.h @@ -148,16 +148,24 @@ NPY_FINLINE __m128i npyv_mul_u8(__m128i a, __m128i b) } #endif // !NPY_HAVE_FMA3 -// Horizontal add: Calculates the sum of all vector elements. - -NPY_FINLINE npy_uint32 npyv_sum_u32(__m128i a) +/*************************** + * Summation + ***************************/ +// reduce sum across vector +NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) { __m128i t = _mm_add_epi32(a, _mm_srli_si128(a, 8)); t = _mm_add_epi32(t, _mm_srli_si128(t, 4)); return (unsigned)_mm_cvtsi128_si32(t); } -NPY_FINLINE float npyv_sum_f32(__m128 a) +NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) +{ + __m128i one = _mm_add_epi64(a, _mm_unpackhi_epi64(a, a)); + return (npy_uint64)npyv128_cvtsi128_si64(one); +} + +NPY_FINLINE float npyv_sum_f32(npyv_f32 a) { #ifdef NPY_HAVE_SSE3 __m128 sum_halves = _mm_hadd_ps(a, a); @@ -171,7 +179,7 @@ NPY_FINLINE float npyv_sum_f32(__m128 a) #endif } -NPY_FINLINE double npyv_sum_f64(__m128d a) +NPY_FINLINE double npyv_sum_f64(npyv_f64 a) { #ifdef NPY_HAVE_SSE3 return _mm_cvtsd_f64(_mm_hadd_pd(a, a)); @@ -180,6 +188,23 @@ NPY_FINLINE double npyv_sum_f64(__m128d a) #endif } +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ + __m128i two = _mm_sad_epu8(a, _mm_setzero_si128()); + __m128i one = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two)); + return (npy_uint16)_mm_cvtsi128_si32(one); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const __m128i even_mask = _mm_set1_epi32(0x0000FFFF); + __m128i even = _mm_and_si128(a, even_mask); + __m128i odd = _mm_srli_epi32(a, 16); + __m128i four = _mm_add_epi32(even, odd); + return npyv_sum_u32(four); +} + #endif // _NPY_SIMD_SSE_ARITHMETIC_H diff --git a/numpy/core/src/common/simd/sse/sse.h b/numpy/core/src/common/simd/sse/sse.h index dc0b62f73..0bb404312 100644 --- a/numpy/core/src/common/simd/sse/sse.h +++ b/numpy/core/src/common/simd/sse/sse.h @@ -62,6 +62,7 @@ typedef struct { __m128d val[3]; } npyv_f64x3; #define npyv_nlanes_f32 4 #define npyv_nlanes_f64 2 +#include "utils.h" #include "memory.h" #include "misc.h" #include "reorder.h" diff --git a/numpy/core/src/common/simd/sse/utils.h b/numpy/core/src/common/simd/sse/utils.h new file mode 100644 index 000000000..c23def11d --- /dev/null +++ b/numpy/core/src/common/simd/sse/utils.h @@ -0,0 +1,19 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_UTILS_H +#define _NPY_SIMD_SSE_UTILS_H + +#if !defined(__x86_64__) && !defined(_M_X64) +NPY_FINLINE npy_int64 npyv128_cvtsi128_si64(__m128i a) +{ + npy_int64 NPY_DECL_ALIGNED(16) idx[2]; + _mm_store_si128((__m128i *)idx, a); + return idx[0]; +} +#else + #define npyv128_cvtsi128_si64 _mm_cvtsi128_si64 +#endif + +#endif // _NPY_SIMD_SSE_UTILS_H diff --git a/numpy/core/src/common/simd/vsx/arithmetic.h b/numpy/core/src/common/simd/vsx/arithmetic.h index 1288a52a7..7c4e32f27 100644 --- a/numpy/core/src/common/simd/vsx/arithmetic.h +++ b/numpy/core/src/common/simd/vsx/arithmetic.h @@ -116,7 +116,14 @@ #define npyv_nmulsub_f32 vec_nmadd // equivalent to -(a*b + c) #define npyv_nmulsub_f64 vec_nmadd -// Horizontal add: Calculates the sum of all vector elements. +/*************************** + * Summation + ***************************/ +// reduce sum across vector +NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) +{ + return vec_extract(vec_add(a, vec_mergel(a, a)), 0); +} NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) { @@ -135,4 +142,22 @@ NPY_FINLINE double npyv_sum_f64(npyv_f64 a) return vec_extract(a, 0) + vec_extract(a, 1); } +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ + const npyv_u32 zero = npyv_zero_u32(); + npyv_u32 four = vec_sum4s(a, zero); + npyv_s32 one = vec_sums((npyv_s32)four, (npyv_s32)zero); + return (npy_uint16)vec_extract(one, 3); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const npyv_s32 zero = npyv_zero_s32(); + npyv_u32x2 eight = npyv_expand_u32_u16(a); + npyv_u32 four = vec_add(eight.val[0], eight.val[1]); + npyv_s32 one = vec_sums((npyv_s32)four, zero); + return (npy_uint32)vec_extract(one, 3); +} + #endif // _NPY_SIMD_VSX_ARITHMETIC_H diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c index fa5d7db75..de793f87c 100644 --- a/numpy/core/src/multiarray/compiled_base.c +++ b/numpy/core/src/multiarray/compiled_base.c @@ -1037,7 +1037,7 @@ arr_ravel_multi_index(PyObject *self, PyObject *args, PyObject *kwds) NpyIter *iter = NULL; - char *kwlist[] = {"multi_index", "dims", "mode", "order", NULL}; + static char *kwlist[] = {"multi_index", "dims", "mode", "order", NULL}; memset(op, 0, sizeof(op)); dtype[0] = NULL; @@ -1232,7 +1232,7 @@ arr_unravel_index(PyObject *self, PyObject *args, PyObject *kwds) int i, ret_ndim; npy_intp ret_dims[NPY_MAXDIMS], ret_strides[NPY_MAXDIMS]; - char *kwlist[] = {"indices", "shape", "order", NULL}; + static char *kwlist[] = {"indices", "shape", "order", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&|O&:unravel_index", kwlist, diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 58571b678..ef105ff2d 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -2124,7 +2124,16 @@ PyArray_FromInterface(PyObject *origin) if (iface == NULL) { if (PyErr_Occurred()) { - return NULL; + if (PyErr_ExceptionMatches(PyExc_RecursionError) || + PyErr_ExceptionMatches(PyExc_MemoryError)) { + /* RecursionError and MemoryError are considered fatal */ + return NULL; + } + /* + * This probably be deprecated, but at least shapely raised + * a NotImplementedError expecting it to be cleared (gh-17965) + */ + PyErr_Clear(); } return Py_NotImplemented; } @@ -2392,7 +2401,13 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context) array_meth = PyArray_LookupSpecial_OnInstance(op, "__array__"); if (array_meth == NULL) { if (PyErr_Occurred()) { - return NULL; + if (PyErr_ExceptionMatches(PyExc_RecursionError) || + PyErr_ExceptionMatches(PyExc_MemoryError)) { + /* RecursionError and MemoryError are considered fatal */ + return NULL; + } + /* This probably be deprecated. */ + PyErr_Clear(); } return Py_NotImplemented; } diff --git a/numpy/core/src/multiarray/datetime_busday.c b/numpy/core/src/multiarray/datetime_busday.c index 2cf157551..f0564146d 100644 --- a/numpy/core/src/multiarray/datetime_busday.c +++ b/numpy/core/src/multiarray/datetime_busday.c @@ -934,8 +934,8 @@ NPY_NO_EXPORT PyObject * array_busday_offset(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) { - char *kwlist[] = {"dates", "offsets", "roll", - "weekmask", "holidays", "busdaycal", "out", NULL}; + static char *kwlist[] = {"dates", "offsets", "roll", + "weekmask", "holidays", "busdaycal", "out", NULL}; PyObject *dates_in = NULL, *offsets_in = NULL, *out_in = NULL; @@ -1065,8 +1065,8 @@ NPY_NO_EXPORT PyObject * array_busday_count(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) { - char *kwlist[] = {"begindates", "enddates", - "weekmask", "holidays", "busdaycal", "out", NULL}; + static char *kwlist[] = {"begindates", "enddates", + "weekmask", "holidays", "busdaycal", "out", NULL}; PyObject *dates_begin_in = NULL, *dates_end_in = NULL, *out_in = NULL; @@ -1210,8 +1210,8 @@ NPY_NO_EXPORT PyObject * array_is_busday(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) { - char *kwlist[] = {"dates", - "weekmask", "holidays", "busdaycal", "out", NULL}; + static char *kwlist[] = {"dates", + "weekmask", "holidays", "busdaycal", "out", NULL}; PyObject *dates_in = NULL, *out_in = NULL; diff --git a/numpy/core/src/multiarray/dtypemeta.c b/numpy/core/src/multiarray/dtypemeta.c index 2931977c2..b2f36d794 100644 --- a/numpy/core/src/multiarray/dtypemeta.c +++ b/numpy/core/src/multiarray/dtypemeta.c @@ -407,6 +407,19 @@ string_unicode_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other) Py_INCREF(Py_NotImplemented); return (PyArray_DTypeMeta *)Py_NotImplemented; } + if (other->type_num != NPY_STRING && other->type_num != NPY_UNICODE) { + /* Deprecated 2020-12-19, NumPy 1.21. */ + if (DEPRECATE_FUTUREWARNING( + "Promotion of numbers and bools to strings is deprecated. " + "In the future, code such as `np.concatenate((['string'], [0]))` " + "will raise an error, while `np.asarray(['string', 0])` will " + "return an array with `dtype=object`. To avoid the warning " + "while retaining a string result use `dtype='U'` (or 'S'). " + "To get an array of Python objects use `dtype=object`. " + "(Warning added in NumPy 1.21)") < 0) { + return NULL; + } + } /* * The builtin types are ordered by complexity (aside from object) here. * Arguably, we should not consider numbers and strings "common", but diff --git a/numpy/core/src/multiarray/einsum_sumprod.c.src b/numpy/core/src/multiarray/einsum_sumprod.c.src index d1b76de4e..333b8e188 100644 --- a/numpy/core/src/multiarray/einsum_sumprod.c.src +++ b/numpy/core/src/multiarray/einsum_sumprod.c.src @@ -20,28 +20,6 @@ #include "simd/simd.h" #include "common.h" -#ifdef NPY_HAVE_SSE_INTRINSICS -#define EINSUM_USE_SSE1 1 -#else -#define EINSUM_USE_SSE1 0 -#endif - -#ifdef NPY_HAVE_SSE2_INTRINSICS -#define EINSUM_USE_SSE2 1 -#else -#define EINSUM_USE_SSE2 0 -#endif - -#if EINSUM_USE_SSE1 -#include <xmmintrin.h> -#endif - -#if EINSUM_USE_SSE2 -#include <emmintrin.h> -#endif - -#define EINSUM_IS_SSE_ALIGNED(x) ((((npy_intp)x)&0xf) == 0) - // ARM/Neon don't have instructions for aligned memory access #ifdef NPY_HAVE_NEON #define EINSUM_IS_ALIGNED(x) 0 @@ -311,6 +289,77 @@ finish_after_unrolled_loop: #elif @nop@ == 2 && !@complex@ +// calculate the multiply and add operation such as dataout = data*scalar+dataout +static NPY_GCC_OPT_3 void +@name@_sum_of_products_muladd(@type@ *data, @type@ *data_out, @temptype@ scalar, npy_intp count) +{ +#if @NPYV_CHK@ // NPYV check for @type@ + /* Use aligned instructions if possible */ + const int is_aligned = EINSUM_IS_ALIGNED(data) && EINSUM_IS_ALIGNED(data_out); + const int vstep = npyv_nlanes_@sfx@; + const npyv_@sfx@ v_scalar = npyv_setall_@sfx@(scalar); + /**begin repeat2 + * #cond = if(is_aligned), else# + * #ld = loada, load# + * #st = storea, store# + */ + @cond@ { + const npy_intp vstepx4 = vstep * 4; + for (; count >= vstepx4; count -= vstepx4, data += vstepx4, data_out += vstepx4) { + /**begin repeat3 + * #i = 0, 1, 2, 3# + */ + npyv_@sfx@ b@i@ = npyv_@ld@_@sfx@(data + vstep * @i@); + npyv_@sfx@ c@i@ = npyv_@ld@_@sfx@(data_out + vstep * @i@); + /**end repeat3**/ + /**begin repeat3 + * #i = 0, 1, 2, 3# + */ + npyv_@sfx@ abc@i@ = npyv_muladd_@sfx@(v_scalar, b@i@, c@i@); + /**end repeat3**/ + /**begin repeat3 + * #i = 0, 1, 2, 3# + */ + npyv_@st@_@sfx@(data_out + vstep * @i@, abc@i@); + /**end repeat3**/ + } + } + /**end repeat2**/ + for (; count > 0; count -= vstep, data += vstep, data_out += vstep) { + npyv_@sfx@ a = npyv_load_tillz_@sfx@(data, count); + npyv_@sfx@ b = npyv_load_tillz_@sfx@(data_out, count); + npyv_store_till_@sfx@(data_out, count, npyv_muladd_@sfx@(a, v_scalar, b)); + } + npyv_cleanup(); +#else +#ifndef NPY_DISABLE_OPTIMIZATION + for (; count >= 4; count -= 4, data += 4, data_out += 4) { + /**begin repeat2 + * #i = 0, 1, 2, 3# + */ + const @type@ b@i@ = @from@(data[@i@]); + const @type@ c@i@ = @from@(data_out[@i@]); + /**end repeat2**/ + /**begin repeat2 + * #i = 0, 1, 2, 3# + */ + const @type@ abc@i@ = scalar * b@i@ + c@i@; + /**end repeat2**/ + /**begin repeat2 + * #i = 0, 1, 2, 3# + */ + data_out[@i@] = @to@(abc@i@); + /**end repeat2**/ + } +#endif // !NPY_DISABLE_OPTIMIZATION + for (; count > 0; --count, ++data, ++data_out) { + const @type@ b = @from@(*data); + const @type@ c = @from@(*data_out); + *data_out = @to@(scalar * b + c); + } +#endif // NPYV check for @type@ +} + static void @name@_sum_of_products_contig_two(int nop, char **dataptr, npy_intp const *NPY_UNUSED(strides), npy_intp count) @@ -403,242 +452,23 @@ static void @type@ *data1 = (@type@ *)dataptr[1]; @type@ *data_out = (@type@ *)dataptr[2]; -#if EINSUM_USE_SSE1 && @float32@ - __m128 a, b, value0_sse; -#elif EINSUM_USE_SSE2 && @float64@ - __m128d a, b, value0_sse; -#endif - NPY_EINSUM_DBG_PRINT1("@name@_sum_of_products_stride0_contig_outcontig_two (%d)\n", (int)count); - -/* This is placed before the main loop to make small counts faster */ -finish_after_unrolled_loop: - switch (count) { -/**begin repeat2 - * #i = 6, 5, 4, 3, 2, 1, 0# - */ - case @i@+1: - data_out[@i@] = @to@(value0 * - @from@(data1[@i@]) + - @from@(data_out[@i@])); -/**end repeat2**/ - case 0: - return; - } - -#if EINSUM_USE_SSE1 && @float32@ - value0_sse = _mm_set_ps1(value0); - - /* Use aligned instructions if possible */ - if (EINSUM_IS_SSE_ALIGNED(data1) && EINSUM_IS_SSE_ALIGNED(data_out)) { - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -/**begin repeat2 - * #i = 0, 4# - */ - a = _mm_mul_ps(value0_sse, _mm_load_ps(data1+@i@)); - b = _mm_add_ps(a, _mm_load_ps(data_out+@i@)); - _mm_store_ps(data_out+@i@, b); -/**end repeat2**/ - data1 += 8; - data_out += 8; - } - - /* Finish off the loop */ - if (count > 0) { - goto finish_after_unrolled_loop; - } - else { - return; - } - } -#elif EINSUM_USE_SSE2 && @float64@ - value0_sse = _mm_set1_pd(value0); - - /* Use aligned instructions if possible */ - if (EINSUM_IS_SSE_ALIGNED(data1) && EINSUM_IS_SSE_ALIGNED(data_out)) { - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -/**begin repeat2 - * #i = 0, 2, 4, 6# - */ - a = _mm_mul_pd(value0_sse, _mm_load_pd(data1+@i@)); - b = _mm_add_pd(a, _mm_load_pd(data_out+@i@)); - _mm_store_pd(data_out+@i@, b); -/**end repeat2**/ - data1 += 8; - data_out += 8; - } - - /* Finish off the loop */ - if (count > 0) { - goto finish_after_unrolled_loop; - } - else { - return; - } - } -#endif - - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -#if EINSUM_USE_SSE1 && @float32@ -/**begin repeat2 - * #i = 0, 4# - */ - a = _mm_mul_ps(value0_sse, _mm_loadu_ps(data1+@i@)); - b = _mm_add_ps(a, _mm_loadu_ps(data_out+@i@)); - _mm_storeu_ps(data_out+@i@, b); -/**end repeat2**/ -#elif EINSUM_USE_SSE2 && @float64@ -/**begin repeat2 - * #i = 0, 2, 4, 6# - */ - a = _mm_mul_pd(value0_sse, _mm_loadu_pd(data1+@i@)); - b = _mm_add_pd(a, _mm_loadu_pd(data_out+@i@)); - _mm_storeu_pd(data_out+@i@, b); -/**end repeat2**/ -#else -/**begin repeat2 - * #i = 0, 1, 2, 3, 4, 5, 6, 7# - */ - data_out[@i@] = @to@(value0 * - @from@(data1[@i@]) + - @from@(data_out[@i@])); -/**end repeat2**/ -#endif - data1 += 8; - data_out += 8; - } - - /* Finish off the loop */ - if (count > 0) { - goto finish_after_unrolled_loop; - } + @name@_sum_of_products_muladd(data1, data_out, value0, count); + } static void @name@_sum_of_products_contig_stride0_outcontig_two(int nop, char **dataptr, npy_intp const *NPY_UNUSED(strides), npy_intp count) { - @type@ *data0 = (@type@ *)dataptr[0]; @temptype@ value1 = @from@(*(@type@ *)dataptr[1]); + @type@ *data0 = (@type@ *)dataptr[0]; @type@ *data_out = (@type@ *)dataptr[2]; -#if EINSUM_USE_SSE1 && @float32@ - __m128 a, b, value1_sse; -#elif EINSUM_USE_SSE2 && @float64@ - __m128d a, b, value1_sse; -#endif - NPY_EINSUM_DBG_PRINT1("@name@_sum_of_products_contig_stride0_outcontig_two (%d)\n", (int)count); - -/* This is placed before the main loop to make small counts faster */ -finish_after_unrolled_loop: - switch (count) { -/**begin repeat2 - * #i = 6, 5, 4, 3, 2, 1, 0# - */ - case @i@+1: - data_out[@i@] = @to@(@from@(data0[@i@])* - value1 + - @from@(data_out[@i@])); -/**end repeat2**/ - case 0: - return; - } - -#if EINSUM_USE_SSE1 && @float32@ - value1_sse = _mm_set_ps1(value1); - - /* Use aligned instructions if possible */ - if (EINSUM_IS_SSE_ALIGNED(data0) && EINSUM_IS_SSE_ALIGNED(data_out)) { - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -/**begin repeat2 - * #i = 0, 4# - */ - a = _mm_mul_ps(_mm_load_ps(data0+@i@), value1_sse); - b = _mm_add_ps(a, _mm_load_ps(data_out+@i@)); - _mm_store_ps(data_out+@i@, b); -/**end repeat2**/ - data0 += 8; - data_out += 8; - } - - /* Finish off the loop */ - goto finish_after_unrolled_loop; - } -#elif EINSUM_USE_SSE2 && @float64@ - value1_sse = _mm_set1_pd(value1); - - /* Use aligned instructions if possible */ - if (EINSUM_IS_SSE_ALIGNED(data0) && EINSUM_IS_SSE_ALIGNED(data_out)) { - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -/**begin repeat2 - * #i = 0, 2, 4, 6# - */ - a = _mm_mul_pd(_mm_load_pd(data0+@i@), value1_sse); - b = _mm_add_pd(a, _mm_load_pd(data_out+@i@)); - _mm_store_pd(data_out+@i@, b); -/**end repeat2**/ - data0 += 8; - data_out += 8; - } - - /* Finish off the loop */ - goto finish_after_unrolled_loop; - } -#endif - - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -#if EINSUM_USE_SSE1 && @float32@ -/**begin repeat2 - * #i = 0, 4# - */ - a = _mm_mul_ps(_mm_loadu_ps(data0+@i@), value1_sse); - b = _mm_add_ps(a, _mm_loadu_ps(data_out+@i@)); - _mm_storeu_ps(data_out+@i@, b); -/**end repeat2**/ -#elif EINSUM_USE_SSE2 && @float64@ -/**begin repeat2 - * #i = 0, 2, 4, 6# - */ - a = _mm_mul_pd(_mm_loadu_pd(data0+@i@), value1_sse); - b = _mm_add_pd(a, _mm_loadu_pd(data_out+@i@)); - _mm_storeu_pd(data_out+@i@, b); -/**end repeat2**/ -#else -/**begin repeat2 - * #i = 0, 1, 2, 3, 4, 5, 6, 7# - */ - data_out[@i@] = @to@(@from@(data0[@i@])* - value1 + - @from@(data_out[@i@])); -/**end repeat2**/ -#endif - data0 += 8; - data_out += 8; - } - - /* Finish off the loop */ - goto finish_after_unrolled_loop; + @name@_sum_of_products_muladd(data0, data_out, value1, count); } static NPY_GCC_OPT_3 void diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index d64962f87..8b9b67387 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -2328,7 +2328,7 @@ PyArray_MapIterNext(PyArrayMapIterObject *mit) * @param Number of indices * @param The array that is being iterated * - * @return 0 on success -1 on failure + * @return 0 on success -1 on failure (broadcasting or too many fancy indices) */ static int mapiter_fill_info(PyArrayMapIterObject *mit, npy_index_info *indices, @@ -2369,6 +2369,17 @@ mapiter_fill_info(PyArrayMapIterObject *mit, npy_index_info *indices, } } + /* Before contunuing, ensure that there are not too fancy indices */ + if (indices[i].type & HAS_FANCY) { + if (NPY_UNLIKELY(j >= NPY_MAXDIMS)) { + PyErr_Format(PyExc_IndexError, + "too many advanced (array) indices. This probably " + "means you are indexing with too many booleans. " + "(more than %d found)", NPY_MAXDIMS); + return -1; + } + } + /* (iterating) fancy index, store the iterator */ if (indices[i].type == HAS_FANCY) { mit->fancy_strides[j] = PyArray_STRIDE(arr, curr_dim); @@ -2655,6 +2666,7 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type, /* For shape reporting on error */ PyArrayObject *original_extra_op = extra_op; + /* NOTE: MAXARGS is the actual limit (2*NPY_MAXDIMS is index number one) */ PyArrayObject *index_arrays[NPY_MAXDIMS]; PyArray_Descr *intp_descr; PyArray_Descr *dtypes[NPY_MAXDIMS]; /* borrowed references */ diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index 8bcf591a2..04ce53ed7 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -2289,7 +2289,7 @@ array_dot(PyArrayObject *self, PyObject *args, PyObject *kwds) { PyObject *a = (PyObject *)self, *b, *o = NULL; PyArrayObject *ret; - char* kwlist[] = {"b", "out", NULL }; + static char* kwlist[] = {"b", "out", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:dot", kwlist, &b, &o)) { diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index dfd27a0bc..2c00c498b 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -2319,7 +2319,7 @@ array_matrixproduct(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject* kwds) { PyObject *v, *a, *o = NULL; PyArrayObject *ret; - char* kwlist[] = {"a", "b", "out", NULL }; + static char* kwlist[] = {"a", "b", "out", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:matrixproduct", kwlist, &a, &v, &o)) { diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index e480628e7..10f304fe7 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -2711,7 +2711,7 @@ static PyObject * /* TODO: include type name in error message, which is not @name@ */ PyObject *obj = NULL; - char *kwnames[] = {"", NULL}; /* positional-only */ + static char *kwnames[] = {"", NULL}; /* positional-only */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwnames, &obj)) { return NULL; } @@ -2799,7 +2799,7 @@ static PyObject * object_arrtype_new(PyTypeObject *NPY_UNUSED(type), PyObject *args, PyObject *kwds) { PyObject *obj = Py_None; - char *kwnames[] = {"", NULL}; /* positional-only */ + static char *kwnames[] = {"", NULL}; /* positional-only */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:object_", kwnames, &obj)) { return NULL; } @@ -2825,7 +2825,7 @@ static PyObject * PyObject *obj = NULL, *meta_obj = NULL; Py@Name@ScalarObject *ret; - char *kwnames[] = {"", "", NULL}; /* positional-only */ + static char *kwnames[] = {"", "", NULL}; /* positional-only */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwnames, &obj, &meta_obj)) { return NULL; } @@ -2884,7 +2884,7 @@ bool_arrtype_new(PyTypeObject *NPY_UNUSED(type), PyObject *args, PyObject *kwds) PyObject *obj = NULL; PyArrayObject *arr; - char *kwnames[] = {"", NULL}; /* positional-only */ + static char *kwnames[] = {"", NULL}; /* positional-only */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:bool_", kwnames, &obj)) { return NULL; } @@ -2995,7 +2995,7 @@ void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *obj, *arr; PyObject *new = NULL; - char *kwnames[] = {"", NULL}; /* positional-only */ + static char *kwnames[] = {"", NULL}; /* positional-only */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:void", kwnames, &obj)) { return NULL; } diff --git a/numpy/core/src/multiarray/usertypes.c b/numpy/core/src/multiarray/usertypes.c index a1ed46f13..15d46800c 100644 --- a/numpy/core/src/multiarray/usertypes.c +++ b/numpy/core/src/multiarray/usertypes.c @@ -235,7 +235,7 @@ PyArray_RegisterDataType(PyArray_Descr *descr) !PyDict_CheckExact(descr->fields)) { PyErr_Format(PyExc_ValueError, "Failed to register dtype for %S: Legacy user dtypes " - "using `NPY_ITEM_IS_POINTER` or `NPY_ITEM_REFCOUNT` are" + "using `NPY_ITEM_IS_POINTER` or `NPY_ITEM_REFCOUNT` are " "unsupported. It is possible to create such a dtype only " "if it is a structured dtype with names and fields " "hardcoded at registration time.\n" diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c index be48be079..c46346118 100644 --- a/numpy/core/src/umath/ufunc_type_resolution.c +++ b/numpy/core/src/umath/ufunc_type_resolution.c @@ -111,14 +111,18 @@ raise_no_loop_found_error( return -1; } for (i = 0; i < ufunc->nargs; ++i) { - Py_INCREF(dtypes[i]); - PyTuple_SET_ITEM(dtypes_tup, i, (PyObject *)dtypes[i]); + PyObject *tmp = Py_None; + if (dtypes[i] != NULL) { + tmp = (PyObject *)dtypes[i]; + } + Py_INCREF(tmp); + PyTuple_SET_ITEM(dtypes_tup, i, tmp); } /* produce an error object */ exc_value = PyTuple_Pack(2, ufunc, dtypes_tup); Py_DECREF(dtypes_tup); - if (exc_value == NULL){ + if (exc_value == NULL) { return -1; } PyErr_SetObject(exc_type, exc_value); @@ -329,10 +333,23 @@ PyUFunc_SimpleBinaryComparisonTypeResolver(PyUFuncObject *ufunc, } if (type_tup == NULL) { - /* Input types are the result type */ - out_dtypes[0] = PyArray_ResultType(2, operands, 0, NULL); - if (out_dtypes[0] == NULL) { - return -1; + /* + * DEPRECATED NumPy 1.20, 2020-12. + * This check is required to avoid the FutureWarning that + * ResultType will give for number->string promotions. + * (We never supported flexible dtypes here.) + */ + if (!PyArray_ISFLEXIBLE(operands[0]) && + !PyArray_ISFLEXIBLE(operands[1])) { + out_dtypes[0] = PyArray_ResultType(2, operands, 0, NULL); + if (out_dtypes[0] == NULL) { + return -1; + } + } + else { + /* Not doing anything will lead to a loop no found error. */ + out_dtypes[0] = PyArray_DESCR(operands[0]); + Py_INCREF(out_dtypes[0]); } out_dtypes[1] = out_dtypes[0]; Py_INCREF(out_dtypes[1]); @@ -488,6 +505,30 @@ PyUFunc_SimpleUniformOperationTypeResolver( out_dtypes[0] = ensure_dtype_nbo(PyArray_DESCR(operands[0])); } else { + int iop; + npy_bool has_flexible = 0; + npy_bool has_object = 0; + for (iop = 0; iop < ufunc->nin; iop++) { + if (PyArray_ISOBJECT(operands[iop])) { + has_object = 1; + } + if (PyArray_ISFLEXIBLE(operands[iop])) { + has_flexible = 1; + } + } + if (NPY_UNLIKELY(has_flexible && !has_object)) { + /* + * DEPRECATED NumPy 1.20, 2020-12. + * This check is required to avoid the FutureWarning that + * ResultType will give for number->string promotions. + * (We never supported flexible dtypes here.) + */ + for (iop = 0; iop < ufunc->nin; iop++) { + out_dtypes[iop] = PyArray_DESCR(operands[iop]); + Py_INCREF(out_dtypes[iop]); + } + return raise_no_loop_found_error(ufunc, out_dtypes); + } out_dtypes[0] = PyArray_ResultType(ufunc->nin, operands, 0, NULL); } if (out_dtypes[0] == NULL) { diff --git a/numpy/core/tests/test_array_coercion.py b/numpy/core/tests/test_array_coercion.py index 08b32dfcc..45c792ad2 100644 --- a/numpy/core/tests/test_array_coercion.py +++ b/numpy/core/tests/test_array_coercion.py @@ -234,6 +234,7 @@ class TestScalarDiscovery: # Additionally to string this test also runs into a corner case # with datetime promotion (the difference is the promotion order). + @pytest.mark.filterwarnings("ignore:Promotion of numbers:FutureWarning") def test_scalar_promotion(self): for sc1, sc2 in product(scalar_instances(), scalar_instances()): sc1, sc2 = sc1.values[0], sc2.values[0] @@ -702,17 +703,19 @@ class TestArrayLikes: @pytest.mark.parametrize("attribute", ["__array_interface__", "__array__", "__array_struct__"]) - def test_bad_array_like_attributes(self, attribute): - # Check that errors during attribute retrieval are raised unless - # they are Attribute errors. + @pytest.mark.parametrize("error", [RecursionError, MemoryError]) + def test_bad_array_like_attributes(self, attribute, error): + # RecursionError and MemoryError are considered fatal. All errors + # (except AttributeError) should probably be raised in the future, + # but shapely made use of it, so it will require a deprecation. class BadInterface: def __getattr__(self, attr): if attr == attribute: - raise RuntimeError + raise error super().__getattr__(attr) - with pytest.raises(RuntimeError): + with pytest.raises(error): np.array(BadInterface()) @pytest.mark.parametrize("error", [RecursionError, MemoryError]) diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py index a2703d81b..2c5f1577d 100644 --- a/numpy/core/tests/test_arrayprint.py +++ b/numpy/core/tests/test_arrayprint.py @@ -923,6 +923,9 @@ class TestPrintOptions: assert_raises(TypeError, np.set_printoptions, threshold='1') assert_raises(TypeError, np.set_printoptions, threshold=b'1') + assert_raises(TypeError, np.set_printoptions, precision='1') + assert_raises(TypeError, np.set_printoptions, precision=1.5) + def test_unicode_object_array(): expected = "array(['é'], dtype=object)" x = np.array([u'\xe9'], dtype=object) diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 5498e1cf9..459a89eaa 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -687,16 +687,16 @@ class TestDeprecatedGlobals(_DeprecationTestCase): reason='module-level __getattr__ not supported') def test_type_aliases(self): # from builtins - self.assert_deprecated(lambda: np.bool) - self.assert_deprecated(lambda: np.int) - self.assert_deprecated(lambda: np.float) - self.assert_deprecated(lambda: np.complex) - self.assert_deprecated(lambda: np.object) - self.assert_deprecated(lambda: np.str) + self.assert_deprecated(lambda: np.bool(True)) + self.assert_deprecated(lambda: np.int(1)) + self.assert_deprecated(lambda: np.float(1)) + self.assert_deprecated(lambda: np.complex(1)) + self.assert_deprecated(lambda: np.object()) + self.assert_deprecated(lambda: np.str('abc')) # from np.compat - self.assert_deprecated(lambda: np.long) - self.assert_deprecated(lambda: np.unicode) + self.assert_deprecated(lambda: np.long(1)) + self.assert_deprecated(lambda: np.unicode('abc')) class TestMatrixInOuter(_DeprecationTestCase): @@ -1100,3 +1100,41 @@ class TestNoseDecoratorsDeprecated(_DeprecationTestCase): count += 1 assert_(count == 3) self.assert_deprecated(_test_parametrize) + + +class TestStringPromotion(_DeprecationTestCase): + # Deprecated 2020-12-19, NumPy 1.21 + warning_cls = FutureWarning + message = "Promotion of numbers and bools to strings is deprecated." + + @pytest.mark.parametrize("dtype", "?bhilqpBHILQPefdgFDG") + @pytest.mark.parametrize("string_dt", ["S", "U"]) + def test_deprecated(self, dtype, string_dt): + self.assert_deprecated(lambda: np.promote_types(dtype, string_dt)) + + # concatenate has to be able to promote to find the result dtype: + arr1 = np.ones(3, dtype=dtype) + arr2 = np.ones(3, dtype=string_dt) + self.assert_deprecated(lambda: np.concatenate((arr1, arr2), axis=0)) + self.assert_deprecated(lambda: np.concatenate((arr1, arr2), axis=None)) + + # coercing to an array is similar, but will fall-back to `object` + # (when raising the FutureWarning, this already happens) + self.assert_deprecated(lambda: np.array([arr1[0], arr2[0]]), + exceptions=()) + + @pytest.mark.parametrize("dtype", "?bhilqpBHILQPefdgFDG") + @pytest.mark.parametrize("string_dt", ["S", "U"]) + def test_not_deprecated(self, dtype, string_dt): + # The ufunc type resolvers run into this, but giving a futurewarning + # here is unnecessary (it ends up as an error anyway), so test that + # no warning is given: + arr1 = np.ones(3, dtype=dtype) + arr2 = np.ones(3, dtype=string_dt) + + # Adding two arrays uses result_type normally, which would fail: + with pytest.raises(TypeError): + self.assert_not_deprecated(lambda: arr1 + arr2) + # np.equal uses a different type resolver: + with pytest.raises(TypeError): + self.assert_not_deprecated(lambda: np.equal(arr1, arr2)) diff --git a/numpy/core/tests/test_half.py b/numpy/core/tests/test_half.py index 1b6fd21e1..449a01d21 100644 --- a/numpy/core/tests/test_half.py +++ b/numpy/core/tests/test_half.py @@ -71,8 +71,10 @@ class TestHalf: def test_half_conversion_to_string(self, string_dt): # Currently uses S/U32 (which is sufficient for float32) expected_dt = np.dtype(f"{string_dt}32") - assert np.promote_types(np.float16, string_dt) == expected_dt - assert np.promote_types(string_dt, np.float16) == expected_dt + with pytest.warns(FutureWarning): + assert np.promote_types(np.float16, string_dt) == expected_dt + with pytest.warns(FutureWarning): + assert np.promote_types(string_dt, np.float16) == expected_dt arr = np.ones(3, dtype=np.float16).astype(string_dt) assert arr.dtype == expected_dt diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index 667c49240..73dbc429c 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -3,6 +3,8 @@ import warnings import functools import operator +import pytest + import numpy as np from numpy.core._multiarray_tests import array_indexing from itertools import product @@ -547,6 +549,21 @@ class TestIndexing: assert_array_equal(arr[0], np.array("asdfg", dtype="c")) assert arr[0, 1] == b"s" # make sure not all were set to "a" for both + @pytest.mark.parametrize("index", + [True, False, np.array([0])]) + @pytest.mark.parametrize("num", [32, 40]) + @pytest.mark.parametrize("original_ndim", [1, 32]) + def test_too_many_advanced_indices(self, index, num, original_ndim): + # These are limitations based on the number of arguments we can process. + # For `num=32` (and all boolean cases), the result is actually define; + # but the use of NpyIter (NPY_MAXARGS) limits it for technical reasons. + arr = np.ones((1,) * original_ndim) + with pytest.raises(IndexError): + arr[(index,) * num] + with pytest.raises(IndexError): + arr[(index,) * num] = 1. + + class TestFieldIndexing: def test_scalar_return_type(self): # Field access on an array should return an array, even if it diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index 5e6472ae5..94f61baca 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -1365,6 +1365,7 @@ def test_iter_copy(): @pytest.mark.parametrize("dtype", np.typecodes["All"]) @pytest.mark.parametrize("loop_dtype", np.typecodes["All"]) +@pytest.mark.filterwarnings("ignore::numpy.ComplexWarning") def test_iter_copy_casts(dtype, loop_dtype): # Ensure the dtype is never flexible: if loop_dtype.lower() == "m": diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index 6de9e3764..cdfecc0f5 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -847,10 +847,12 @@ class TestTypes: assert_equal(np.promote_types('<i8', '<i8'), np.dtype('i8')) assert_equal(np.promote_types('>i8', '>i8'), np.dtype('i8')) - assert_equal(np.promote_types('>i8', '>U16'), np.dtype('U21')) - assert_equal(np.promote_types('<i8', '<U16'), np.dtype('U21')) - assert_equal(np.promote_types('>U16', '>i8'), np.dtype('U21')) - assert_equal(np.promote_types('<U16', '<i8'), np.dtype('U21')) + with pytest.warns(FutureWarning, + match="Promotion of numbers and bools to strings"): + assert_equal(np.promote_types('>i8', '>U16'), np.dtype('U21')) + assert_equal(np.promote_types('<i8', '<U16'), np.dtype('U21')) + assert_equal(np.promote_types('>U16', '>i8'), np.dtype('U21')) + assert_equal(np.promote_types('<U16', '<i8'), np.dtype('U21')) assert_equal(np.promote_types('<S5', '<U8'), np.dtype('U8')) assert_equal(np.promote_types('>S5', '>U8'), np.dtype('U8')) @@ -897,32 +899,38 @@ class TestTypes: promote_types = np.promote_types S = string_dtype - # Promote numeric with unsized string: - assert_equal(promote_types('bool', S), np.dtype(S+'5')) - assert_equal(promote_types('b', S), np.dtype(S+'4')) - assert_equal(promote_types('u1', S), np.dtype(S+'3')) - assert_equal(promote_types('u2', S), np.dtype(S+'5')) - assert_equal(promote_types('u4', S), np.dtype(S+'10')) - assert_equal(promote_types('u8', S), np.dtype(S+'20')) - assert_equal(promote_types('i1', S), np.dtype(S+'4')) - assert_equal(promote_types('i2', S), np.dtype(S+'6')) - assert_equal(promote_types('i4', S), np.dtype(S+'11')) - assert_equal(promote_types('i8', S), np.dtype(S+'21')) - # Promote numeric with sized string: - assert_equal(promote_types('bool', S+'1'), np.dtype(S+'5')) - assert_equal(promote_types('bool', S+'30'), np.dtype(S+'30')) - assert_equal(promote_types('b', S+'1'), np.dtype(S+'4')) - assert_equal(promote_types('b', S+'30'), np.dtype(S+'30')) - assert_equal(promote_types('u1', S+'1'), np.dtype(S+'3')) - assert_equal(promote_types('u1', S+'30'), np.dtype(S+'30')) - assert_equal(promote_types('u2', S+'1'), np.dtype(S+'5')) - assert_equal(promote_types('u2', S+'30'), np.dtype(S+'30')) - assert_equal(promote_types('u4', S+'1'), np.dtype(S+'10')) - assert_equal(promote_types('u4', S+'30'), np.dtype(S+'30')) - assert_equal(promote_types('u8', S+'1'), np.dtype(S+'20')) - assert_equal(promote_types('u8', S+'30'), np.dtype(S+'30')) - # Promote with object: - assert_equal(promote_types('O', S+'30'), np.dtype('O')) + + with pytest.warns(FutureWarning, + match="Promotion of numbers and bools to strings") as record: + # Promote numeric with unsized string: + assert_equal(promote_types('bool', S), np.dtype(S+'5')) + assert_equal(promote_types('b', S), np.dtype(S+'4')) + assert_equal(promote_types('u1', S), np.dtype(S+'3')) + assert_equal(promote_types('u2', S), np.dtype(S+'5')) + assert_equal(promote_types('u4', S), np.dtype(S+'10')) + assert_equal(promote_types('u8', S), np.dtype(S+'20')) + assert_equal(promote_types('i1', S), np.dtype(S+'4')) + assert_equal(promote_types('i2', S), np.dtype(S+'6')) + assert_equal(promote_types('i4', S), np.dtype(S+'11')) + assert_equal(promote_types('i8', S), np.dtype(S+'21')) + # Promote numeric with sized string: + assert_equal(promote_types('bool', S+'1'), np.dtype(S+'5')) + assert_equal(promote_types('bool', S+'30'), np.dtype(S+'30')) + assert_equal(promote_types('b', S+'1'), np.dtype(S+'4')) + assert_equal(promote_types('b', S+'30'), np.dtype(S+'30')) + assert_equal(promote_types('u1', S+'1'), np.dtype(S+'3')) + assert_equal(promote_types('u1', S+'30'), np.dtype(S+'30')) + assert_equal(promote_types('u2', S+'1'), np.dtype(S+'5')) + assert_equal(promote_types('u2', S+'30'), np.dtype(S+'30')) + assert_equal(promote_types('u4', S+'1'), np.dtype(S+'10')) + assert_equal(promote_types('u4', S+'30'), np.dtype(S+'30')) + assert_equal(promote_types('u8', S+'1'), np.dtype(S+'20')) + assert_equal(promote_types('u8', S+'30'), np.dtype(S+'30')) + # Promote with object: + assert_equal(promote_types('O', S+'30'), np.dtype('O')) + + assert len(record) == 22 # each string promotion gave one warning + @pytest.mark.parametrize(["dtype1", "dtype2"], [[np.dtype("V6"), np.dtype("V10")], @@ -972,6 +980,7 @@ class TestTypes: assert res.isnative @pytest.mark.slow + @pytest.mark.filterwarnings('ignore:Promotion of numbers:FutureWarning') @pytest.mark.parametrize(["dtype1", "dtype2"], itertools.product( list(np.typecodes["All"]) + diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 831e48e8b..5faa9923c 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -782,7 +782,9 @@ class TestRegression: # Ticket #514 s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" t = [] - np.hstack((t, s)) + with pytest.warns(FutureWarning, + match="Promotion of numbers and bools to strings"): + np.hstack((t, s)) def test_arr_transpose(self): # Ticket #516 diff --git a/numpy/core/tests/test_shape_base.py b/numpy/core/tests/test_shape_base.py index 9922c9173..a0c72f9d0 100644 --- a/numpy/core/tests/test_shape_base.py +++ b/numpy/core/tests/test_shape_base.py @@ -256,7 +256,7 @@ class TestConcatenate: r = np.concatenate((a, b), axis=None) assert_equal(r.size, a.size + len(b)) assert_equal(r.dtype, a.dtype) - r = np.concatenate((a, b, c), axis=None) + r = np.concatenate((a, b, c), axis=None, dtype="U") d = array(['0.0', '1.0', '2.0', '3.0', '0', '1', '2', 'x']) assert_array_equal(r, d) @@ -377,7 +377,8 @@ class TestConcatenate: # Note that U0 and S0 should be deprecated eventually and changed to # actually give the empty string result (together with `np.array`) res = np.concatenate(arrs, axis=axis, dtype=string_dt, casting="unsafe") - assert res.dtype == np.promote_types("d", string_dt) + # The actual dtype should be identical to a cast (of a double array): + assert res.dtype == np.array(1.).astype(string_dt).dtype @pytest.mark.parametrize("axis", [None, 0]) def test_string_dtype_does_not_inspect(self, axis): diff --git a/numpy/core/tests/test_simd.py b/numpy/core/tests/test_simd.py index 23a5bb6c3..1d1a111be 100644 --- a/numpy/core/tests/test_simd.py +++ b/numpy/core/tests/test_simd.py @@ -736,11 +736,9 @@ class _SIMD_ALL(_Test_Utility): def test_arithmetic_reduce_sum(self): """ Test reduce sum intrinics: - npyv_sum_u32 - npyv_sum_f32 - npyv_sum_f64 + npyv_sum_##sfx """ - if self.sfx not in ("u32", "f32", "f64"): + if self.sfx not in ("u32", "u64", "f32", "f64"): return # reduce sum data = self._data() @@ -750,6 +748,21 @@ class _SIMD_ALL(_Test_Utility): vsum = self.sum(vdata) assert vsum == data_sum + def test_arithmetic_reduce_sumup(self): + """ + Test extend reduce sum intrinics: + npyv_sumup_##sfx + """ + if self.sfx not in ("u8", "u16"): + return + rdata = (0, self.nlanes, self._int_min(), self._int_max()-self.nlanes) + for r in rdata: + data = self._data(r) + vdata = self.load(data) + data_sum = sum(data) + vsum = self.sumup(vdata) + assert vsum == data_sum + def test_mask_conditional(self): """ Conditional addition and subtraction for all supported data types. diff --git a/numpy/ctypeslib.py b/numpy/ctypeslib.py index e8f7750fe..dbc683a6b 100644 --- a/numpy/ctypeslib.py +++ b/numpy/ctypeslib.py @@ -4,7 +4,7 @@ ============================ See Also ---------- +-------- load_library : Load a C library. ndpointer : Array restype/argtype with verification. as_ctypes : Create a ctypes array from an ndarray. @@ -49,7 +49,8 @@ Then, we're ready to call ``foo_func``: >>> _lib.foo_func(out, len(out)) #doctest: +SKIP """ -__all__ = ['load_library', 'ndpointer', 'c_intp', 'as_ctypes', 'as_array'] +__all__ = ['load_library', 'ndpointer', 'c_intp', 'as_ctypes', 'as_array', + 'as_ctypes_type'] import os from numpy import ( diff --git a/numpy/ctypeslib.pyi b/numpy/ctypeslib.pyi index cacc97d68..125c20f89 100644 --- a/numpy/ctypeslib.pyi +++ b/numpy/ctypeslib.pyi @@ -1,7 +1,10 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] load_library: Any ndpointer: Any c_intp: Any as_ctypes: Any as_array: Any +as_ctypes_type: Any diff --git a/numpy/distutils/command/build_ext.py b/numpy/distutils/command/build_ext.py index 448f7941c..99c6be873 100644 --- a/numpy/distutils/command/build_ext.py +++ b/numpy/distutils/command/build_ext.py @@ -569,8 +569,11 @@ class build_ext (old_build_ext): objects = list(objects) unlinkable_fobjects = list(unlinkable_fobjects) - # Expand possible fake static libraries to objects - for lib in libraries: + # Expand possible fake static libraries to objects; + # make sure to iterate over a copy of the list as + # "fake" libraries will be removed as they are + # enountered + for lib in libraries[:]: for libdir in library_dirs: fake_lib = os.path.join(libdir, lib + '.fobjects') if os.path.isfile(fake_lib): diff --git a/numpy/distutils/conv_template.py b/numpy/distutils/conv_template.py index e46db0663..65efab062 100644 --- a/numpy/distutils/conv_template.py +++ b/numpy/distutils/conv_template.py @@ -218,7 +218,7 @@ def parse_string(astr, env, level, line) : val = env[name] except KeyError: msg = 'line %d: no definition of key "%s"'%(line, name) - raise ValueError(msg) + raise ValueError(msg) from None return val code = [lineno] diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py index 4730a5a09..812461538 100644 --- a/numpy/distutils/fcompiler/__init__.py +++ b/numpy/distutils/fcompiler/__init__.py @@ -976,7 +976,7 @@ def is_free_format(file): with open(file, encoding='latin1') as f: line = f.readline() n = 10000 # the number of non-comment lines to scan for hints - if _has_f_header(line): + if _has_f_header(line) or _has_fix_header(line): n = 0 elif _has_f90_header(line): n = 0 diff --git a/numpy/distutils/tests/test_build_ext.py b/numpy/distutils/tests/test_build_ext.py new file mode 100644 index 000000000..c007159f5 --- /dev/null +++ b/numpy/distutils/tests/test_build_ext.py @@ -0,0 +1,72 @@ +'''Tests for numpy.distutils.build_ext.''' + +import os +import subprocess +import sys +from textwrap import indent, dedent +import pytest + +@pytest.mark.slow +def test_multi_fortran_libs_link(tmp_path): + ''' + Ensures multiple "fake" static libraries are correctly linked. + see gh-18295 + ''' + + # We need to make sure we actually have an f77 compiler. + # This is nontrivial, so we'll borrow the utilities + # from f2py tests: + from numpy.f2py.tests.util import has_f77_compiler + if not has_f77_compiler(): + pytest.skip('No F77 compiler found') + + # make some dummy sources + with open(tmp_path / '_dummy1.f', 'w') as fid: + fid.write(indent(dedent('''\ + FUNCTION dummy_one() + RETURN + END FUNCTION'''), prefix=' '*6)) + with open(tmp_path / '_dummy2.f', 'w') as fid: + fid.write(indent(dedent('''\ + FUNCTION dummy_two() + RETURN + END FUNCTION'''), prefix=' '*6)) + with open(tmp_path / '_dummy.c', 'w') as fid: + # doesn't need to load - just needs to exist + fid.write('int PyInit_dummyext;') + + # make a setup file + with open(tmp_path / 'setup.py', 'w') as fid: + srctree = os.path.join(os.path.dirname(__file__), '..', '..', '..') + fid.write(dedent(f'''\ + def configuration(parent_package="", top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration("", parent_package, top_path) + config.add_library("dummy1", sources=["_dummy1.f"]) + config.add_library("dummy2", sources=["_dummy2.f"]) + config.add_extension("dummyext", sources=["_dummy.c"], libraries=["dummy1", "dummy2"]) + return config + + + if __name__ == "__main__": + import sys + sys.path.insert(0, r"{srctree}") + from numpy.distutils.core import setup + setup(**configuration(top_path="").todict())''')) + + # build the test extensino and "install" into a temporary directory + build_dir = tmp_path + subprocess.check_call([sys.executable, 'setup.py', 'build', 'install', + '--prefix', str(tmp_path / 'installdir'), + '--record', str(tmp_path / 'tmp_install_log.txt'), + ], + cwd=str(build_dir), + ) + # get the path to the so + so = None + with open(tmp_path /'tmp_install_log.txt') as fid: + for line in fid: + if 'dummyext' in line: + so = line.strip() + break + assert so is not None diff --git a/numpy/emath.pyi b/numpy/emath.pyi index 032ec9505..5aae84b6c 100644 --- a/numpy/emath.pyi +++ b/numpy/emath.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] sqrt: Any log: Any diff --git a/numpy/f2py/__init__.pyi b/numpy/f2py/__init__.pyi index 602517957..50594c1e3 100644 --- a/numpy/f2py/__init__.pyi +++ b/numpy/f2py/__init__.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] run_main: Any compile: Any diff --git a/numpy/f2py/auxfuncs.py b/numpy/f2py/auxfuncs.py index 80b150655..5250fea84 100644 --- a/numpy/f2py/auxfuncs.py +++ b/numpy/f2py/auxfuncs.py @@ -257,6 +257,7 @@ def ismodule(rout): def isfunction(rout): return 'block' in rout and 'function' == rout['block'] + def isfunction_wrap(rout): if isintent_c(rout): return 0 @@ -284,6 +285,10 @@ def hasassumedshape(rout): return False +def requiresf90wrapper(rout): + return ismoduleroutine(rout) or hasassumedshape(rout) + + def isroutine(rout): return isfunction(rout) or issubroutine(rout) diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py index 26b43e7e6..40496ccf1 100644 --- a/numpy/f2py/cfuncs.py +++ b/numpy/f2py/cfuncs.py @@ -549,7 +549,12 @@ cppmacros["F2PY_THREAD_LOCAL_DECL"] = """\ #define F2PY_THREAD_LOCAL_DECL __declspec(thread) #elif defined(__STDC_VERSION__) \\ && (__STDC_VERSION__ >= 201112L) \\ - && !defined(__STDC_NO_THREADS__) + && !defined(__STDC_NO_THREADS__) \\ + && (!defined(__GLIBC__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 12)) +/* __STDC_NO_THREADS__ was first defined in a maintenance release of glibc 2.12, + see https://lists.gnu.org/archive/html/commit-hurd/2012-07/msg00180.html, + so `!defined(__STDC_NO_THREADS__)` may give false positive for the existence + of `threads.h` when using an older release of glibc 2.12 */ #include <threads.h> #define F2PY_THREAD_LOCAL_DECL thread_local #elif defined(__GNUC__) \\ diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index d27845796..1149633c0 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -3113,7 +3113,7 @@ def crack2fortrangen(block, tab='\n', as_interface=False): result = ' result (%s)' % block['result'] if block['result'] not in argsl: argsl.append(block['result']) - body = crack2fortrangen(block['body'], tab + tabchar) + body = crack2fortrangen(block['body'], tab + tabchar, as_interface=as_interface) vars = vars2fortran( block, block['vars'], argsl, tab + tabchar, as_interface=as_interface) mess = '' @@ -3231,8 +3231,13 @@ def vars2fortran(block, vars, args, tab='', as_interface=False): show(vars) outmess('vars2fortran: No definition for argument "%s".\n' % a) continue - if a == block['name'] and not block['block'] == 'function': - continue + if a == block['name']: + if block['block'] != 'function' or block.get('result'): + # 1) skip declaring a variable that name matches with + # subroutine name + # 2) skip declaring function when its type is + # declared via `result` construction + continue if 'typespec' not in vars[a]: if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']: if a in args: diff --git a/numpy/f2py/func2subr.py b/numpy/f2py/func2subr.py index e9976f43c..21d4c009c 100644 --- a/numpy/f2py/func2subr.py +++ b/numpy/f2py/func2subr.py @@ -130,7 +130,7 @@ def createfuncwrapper(rout, signature=0): l = l + ', ' + fortranname if need_interface: for line in rout['saved_interface'].split('\n'): - if line.lstrip().startswith('use '): + if line.lstrip().startswith('use ') and '__user__' not in line: add(line) args = args[1:] @@ -222,7 +222,7 @@ def createsubrwrapper(rout, signature=0): if need_interface: for line in rout['saved_interface'].split('\n'): - if line.lstrip().startswith('use '): + if line.lstrip().startswith('use ') and '__user__' not in line: add(line) dumped_args = [] @@ -247,7 +247,10 @@ def createsubrwrapper(rout, signature=0): pass else: add('interface') - add(rout['saved_interface'].lstrip()) + for line in rout['saved_interface'].split('\n'): + if line.lstrip().startswith('use ') and '__user__' in line: + continue + add(line) add('end interface') sargs = ', '.join([a for a in args if a not in extra_args]) diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py index f1490527e..4e1cf0c7d 100755 --- a/numpy/f2py/rules.py +++ b/numpy/f2py/rules.py @@ -73,7 +73,7 @@ from .auxfuncs import ( issubroutine, issubroutine_wrap, isthreadsafe, isunsigned, isunsigned_char, isunsigned_chararray, isunsigned_long_long, isunsigned_long_longarray, isunsigned_short, isunsigned_shortarray, - l_and, l_not, l_or, outmess, replace, stripcomma, + l_and, l_not, l_or, outmess, replace, stripcomma, requiresf90wrapper ) from . import capi_maps @@ -1184,9 +1184,12 @@ def buildmodule(m, um): nb1['args'] = a nb_list.append(nb1) for nb in nb_list: + # requiresf90wrapper must be called before buildapi as it + # rewrites assumed shape arrays as automatic arrays. + isf90 = requiresf90wrapper(nb) api, wrap = buildapi(nb) if wrap: - if ismoduleroutine(nb): + if isf90: funcwrappers2.append(wrap) else: funcwrappers.append(wrap) @@ -1288,7 +1291,10 @@ def buildmodule(m, um): 'C It contains Fortran 77 wrappers to fortran functions.\n') lines = [] for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'): - if l and l[0] == ' ': + if 0 <= l.find('!') < 66: + # don't split comment lines + lines.append(l + '\n') + elif l and l[0] == ' ': while len(l) >= 66: lines.append(l[:66] + '\n &') l = l[66:] @@ -1310,7 +1316,10 @@ def buildmodule(m, um): '! It contains Fortran 90 wrappers to fortran functions.\n') lines = [] for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'): - if len(l) > 72 and l[0] == ' ': + if 0 <= l.find('!') < 72: + # don't split comment lines + lines.append(l + '\n') + elif len(l) > 72 and l[0] == ' ': lines.append(l[:72] + '&\n &') l = l[72:] while len(l) > 66: diff --git a/numpy/f2py/tests/test_callback.py b/numpy/f2py/tests/test_callback.py index 81650a819..37736af21 100644 --- a/numpy/f2py/tests/test_callback.py +++ b/numpy/f2py/tests/test_callback.py @@ -211,3 +211,28 @@ class TestF77CallbackPythonTLS(TestF77Callback): compiler-provided """ options = ["-DF2PY_USE_PYTHON_TLS"] + + +class TestF90Callback(util.F2PyTest): + + suffix = '.f90' + + code = textwrap.dedent( + """ + function gh17797(f, y) result(r) + external f + integer(8) :: r, f + integer(8), dimension(:) :: y + r = f(0) + r = r + sum(y) + end function gh17797 + """) + + def test_gh17797(self): + + def incr(x): + return x + 123 + + y = np.array([1, 2, 3], dtype=np.int64) + r = self.module.gh17797(incr, y) + assert r == 123 + 1 + 2 + 3 diff --git a/numpy/lib/__init__.pyi b/numpy/lib/__init__.pyi index 413e2ae1b..a8eb24207 100644 --- a/numpy/lib/__init__.pyi +++ b/numpy/lib/__init__.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] emath: Any math: Any @@ -175,3 +177,4 @@ nanquantile: Any histogram: Any histogramdd: Any histogram_bin_edges: Any +NumpyVersion: Any diff --git a/numpy/lib/_datasource.py b/numpy/lib/_datasource.py index 7a23b1651..c790a6462 100644 --- a/numpy/lib/_datasource.py +++ b/numpy/lib/_datasource.py @@ -35,7 +35,6 @@ Example:: """ import os -import shutil import io from numpy.core.overrides import set_module @@ -257,6 +256,8 @@ class DataSource: def __del__(self): # Remove temp directories if hasattr(self, '_istmpdest') and self._istmpdest: + import shutil + shutil.rmtree(self._destpath) def _iszip(self, filename): @@ -319,8 +320,9 @@ class DataSource: Creates a copy of the file in the datasource cache. """ - # We import these here because importing urllib is slow and + # We import these here because importing them is slow and # a significant fraction of numpy's total import time. + import shutil from urllib.request import urlopen from urllib.error import URLError diff --git a/numpy/lib/nanfunctions.py b/numpy/lib/nanfunctions.py index 409016adb..a02ad779f 100644 --- a/numpy/lib/nanfunctions.py +++ b/numpy/lib/nanfunctions.py @@ -613,7 +613,7 @@ def nansum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue): -------- numpy.sum : Sum across array propagating NaNs. isnan : Show which elements are NaN. - isfinite: Show which elements are not NaN or +/-inf. + isfinite : Show which elements are not NaN or +/-inf. Notes ----- diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py index f0596444e..9dfeee527 100644 --- a/numpy/lib/shape_base.py +++ b/numpy/lib/shape_base.py @@ -69,13 +69,13 @@ def take_along_axis(arr, indices, axis): Parameters ---------- - arr: ndarray (Ni..., M, Nk...) + arr : ndarray (Ni..., M, Nk...) Source array - indices: ndarray (Ni..., J, Nk...) + indices : ndarray (Ni..., J, Nk...) Indices to take along each 1d slice of `arr`. This must match the dimension of arr, but dimensions Ni and Nj only need to broadcast against `arr`. - axis: int + axis : int The axis to take 1d slices along. If axis is None, the input array is treated as if it had first been flattened to 1d, for consistency with `sort` and `argsort`. @@ -190,16 +190,16 @@ def put_along_axis(arr, indices, values, axis): Parameters ---------- - arr: ndarray (Ni..., M, Nk...) + arr : ndarray (Ni..., M, Nk...) Destination array. - indices: ndarray (Ni..., J, Nk...) + indices : ndarray (Ni..., J, Nk...) Indices to change along each 1d slice of `arr`. This must match the dimension of arr, but dimensions in Ni and Nj may be 1 to broadcast against `arr`. - values: array_like (Ni..., J, Nk...) + values : array_like (Ni..., J, Nk...) values to insert at those indices. Its shape and dimension are broadcast to match that of `indices`. - axis: int + axis : int The axis to take 1d slices along. If axis is None, the destination array is treated as if a flattened 1d view had been created of it. diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index aa4499764..534ab683c 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -580,7 +580,7 @@ class TestSaveTxt: memoryerror_raised.value = False try: # The test takes at least 6GB of memory, writes a file larger - # than 4GB + # than 4GB. This tests the ``allowZip64`` kwarg to ``zipfile`` test_data = np.asarray([np.random.rand( np.random.randint(50,100),4) for i in range(800000)], dtype=object) @@ -599,6 +599,9 @@ class TestSaveTxt: p.join() if memoryerror_raised.value: raise MemoryError("Child process raised a MemoryError exception") + # -9 indicates a SIGKILL, probably an OOM. + if p.exitcode == -9: + pytest.xfail("subprocess got a SIGKILL, apparently free memory was not sufficient") assert p.exitcode == 0 class LoadTxtBase: diff --git a/numpy/lib/tests/test_regression.py b/numpy/lib/tests/test_regression.py index 55df2a675..94fac7ef0 100644 --- a/numpy/lib/tests/test_regression.py +++ b/numpy/lib/tests/test_regression.py @@ -1,3 +1,5 @@ +import pytest + import os import numpy as np @@ -62,7 +64,8 @@ class TestRegression: def test_mem_string_concat(self): # Ticket #469 x = np.array([]) - np.append(x, 'asdasd\tasdasd') + with pytest.warns(FutureWarning): + np.append(x, 'asdasd\tasdasd') def test_poly_div(self): # Ticket #553 diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py index 2b4cbdfbb..960797b68 100644 --- a/numpy/lib/twodim_base.py +++ b/numpy/lib/twodim_base.py @@ -6,11 +6,12 @@ import functools from numpy.core.numeric import ( asanyarray, arange, zeros, greater_equal, multiply, ones, asarray, where, int8, int16, int32, int64, empty, promote_types, diagonal, - nonzero + nonzero, indices ) from numpy.core.overrides import set_array_function_like_doc, set_module from numpy.core import overrides from numpy.core import iinfo +from numpy.lib.stride_tricks import broadcast_to __all__ = [ @@ -894,7 +895,10 @@ def tril_indices(n, k=0, m=None): [-10, -10, -10, -10]]) """ - return nonzero(tri(n, m, k=k, dtype=bool)) + tri_ = tri(n, m, k=k, dtype=bool) + + return tuple(broadcast_to(inds, tri_.shape)[tri_] + for inds in indices(tri_.shape, sparse=True)) def _trilu_indices_form_dispatcher(arr, k=None): @@ -1010,7 +1014,10 @@ def triu_indices(n, k=0, m=None): [ 12, 13, 14, -1]]) """ - return nonzero(~tri(n, m, k=k-1, dtype=bool)) + tri_ = ~tri(n, m, k=k - 1, dtype=bool) + + return tuple(broadcast_to(inds, tri_.shape)[tri_] + for inds in indices(tri_.shape, sparse=True)) @array_function_dispatch(_trilu_indices_form_dispatcher) diff --git a/numpy/ma/__init__.pyi b/numpy/ma/__init__.pyi index d1259abcc..66dfe40de 100644 --- a/numpy/ma/__init__.pyi +++ b/numpy/ma/__init__.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] core: Any extras: Any diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 54cb12f17..38a0a8b50 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -399,10 +399,10 @@ def _recursive_set_fill_value(fillvalue, dt): Parameters ---------- - fillvalue: scalar or array_like + fillvalue : scalar or array_like Scalar or array representing the fill value. If it is of shorter length than the number of fields in dt, it will be resized. - dt: dtype + dt : dtype The structured dtype for which to create the fill value. Returns @@ -5220,7 +5220,7 @@ class MaskedArray(ndarray): -------- numpy.ndarray.mean : corresponding function for ndarrays numpy.mean : Equivalent function - numpy.ma.average: Weighted average. + numpy.ma.average : Weighted average. Examples -------- @@ -6913,8 +6913,7 @@ def compressed(x): See Also -------- - ma.MaskedArray.compressed - Equivalent method. + ma.MaskedArray.compressed : Equivalent method. """ return asanyarray(x).compressed() @@ -7343,12 +7342,12 @@ def choose(indices, choices, out=None, mode='raise'): Given an array of integers and a list of n choice arrays, this method will create a new array that merges each of the choice arrays. Where a - value in `a` is i, the new array will have the value that choices[i] + value in `index` is i, the new array will have the value that choices[i] contains in the same place. Parameters ---------- - a : ndarray of ints + indices : ndarray of ints This array must contain integers in ``[0, n-1]``, where n is the number of choices. choices : sequence of arrays diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index 96e64914a..a775a15bf 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -1217,7 +1217,7 @@ def union1d(ar1, ar2): The output is always a masked array. See `numpy.union1d` for more details. - See also + See Also -------- numpy.union1d : Equivalent function for ndarrays. diff --git a/numpy/matrixlib/__init__.pyi b/numpy/matrixlib/__init__.pyi index b240bb327..b9005c4aa 100644 --- a/numpy/matrixlib/__init__.pyi +++ b/numpy/matrixlib/__init__.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] matrix: Any bmat: Any diff --git a/numpy/polynomial/_polybase.py b/numpy/polynomial/_polybase.py index ef3f9896d..b04b8e66b 100644 --- a/numpy/polynomial/_polybase.py +++ b/numpy/polynomial/_polybase.py @@ -757,9 +757,6 @@ class ABCPolyBase(abc.ABC): Conversion between domains and class types can result in numerically ill defined series. - Examples - -------- - """ if kind is None: kind = self.__class__ diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py index 4d0a4f483..d24fc738f 100644 --- a/numpy/polynomial/chebyshev.py +++ b/numpy/polynomial/chebyshev.py @@ -1149,9 +1149,6 @@ def chebval(x, c, tensor=True): ----- The evaluation uses Clenshaw recursion, aka synthetic division. - Examples - -------- - """ c = np.array(c, ndmin=1, copy=True) if c.dtype.char in '?bBhHiIlLqQpP': diff --git a/numpy/polynomial/legendre.py b/numpy/polynomial/legendre.py index 23ddd07ca..cd4da2a79 100644 --- a/numpy/polynomial/legendre.py +++ b/numpy/polynomial/legendre.py @@ -605,9 +605,6 @@ def legpow(c, pow, maxpower=16): -------- legadd, legsub, legmulx, legmul, legdiv - Examples - -------- - """ return pu._pow(legmul, c, pow, maxpower) @@ -890,9 +887,6 @@ def legval(x, c, tensor=True): ----- The evaluation uses Clenshaw recursion, aka synthetic division. - Examples - -------- - """ c = np.array(c, ndmin=1, copy=False) if c.dtype.char in '?bBhHiIlLqQpP': diff --git a/numpy/polynomial/polyutils.py b/numpy/polynomial/polyutils.py index d81ee9754..01879ecbc 100644 --- a/numpy/polynomial/polyutils.py +++ b/numpy/polynomial/polyutils.py @@ -509,7 +509,7 @@ def _fromroots(line_f, mul_f, roots): The ``<type>line`` function, such as ``polyline`` mul_f : function(array_like, array_like) -> ndarray The ``<type>mul`` function, such as ``polymul`` - roots : + roots See the ``<type>fromroots`` functions for more detail """ if len(roots) == 0: @@ -537,7 +537,7 @@ def _valnd(val_f, c, *args): ---------- val_f : function(array_like, array_like, tensor: bool) -> array_like The ``<type>val`` function, such as ``polyval`` - c, args : + c, args See the ``<type>val<n>d`` functions for more detail """ args = [np.asanyarray(a) for a in args] @@ -567,7 +567,7 @@ def _gridnd(val_f, c, *args): ---------- val_f : function(array_like, array_like, tensor: bool) -> array_like The ``<type>val`` function, such as ``polyval`` - c, args : + c, args See the ``<type>grid<n>d`` functions for more detail """ for xi in args: @@ -586,7 +586,7 @@ def _div(mul_f, c1, c2): ---------- mul_f : function(array_like, array_like) -> array_like The ``<type>mul`` function, such as ``polymul`` - c1, c2 : + c1, c2 See the ``<type>div`` functions for more detail """ # c1, c2 are trimmed copies @@ -646,7 +646,7 @@ def _fit(vander_f, x, y, deg, rcond=None, full=False, w=None): ---------- vander_f : function(array_like, int) -> ndarray The 1d vander function, such as ``polyvander`` - c1, c2 : + c1, c2 See the ``<type>fit`` functions for more detail """ x = np.asarray(x) + 0.0 @@ -732,12 +732,12 @@ def _pow(mul_f, c, pow, maxpower): Parameters ---------- - vander_f : function(array_like, int) -> ndarray - The 1d vander function, such as ``polyvander`` - pow, maxpower : - See the ``<type>pow`` functions for more detail mul_f : function(array_like, array_like) -> ndarray The ``<type>mul`` function, such as ``polymul`` + c : array_like + 1-D array of array of series coefficients + pow, maxpower + See the ``<type>pow`` functions for more detail """ # c is a trimmed copy [c] = as_series([c]) diff --git a/numpy/random/__init__.pyi b/numpy/random/__init__.pyi index f7c3cfafe..bd5ece536 100644 --- a/numpy/random/__init__.pyi +++ b/numpy/random/__init__.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] beta: Any binomial: Any diff --git a/numpy/random/_examples/cffi/parse.py b/numpy/random/_examples/cffi/parse.py index 73d8646c7..daff6bdec 100644 --- a/numpy/random/_examples/cffi/parse.py +++ b/numpy/random/_examples/cffi/parse.py @@ -17,11 +17,20 @@ def parse_distributions_h(ffi, inc_dir): continue s.append(line) ffi.cdef('\n'.join(s)) - + with open(os.path.join(inc_dir, 'random', 'distributions.h')) as fid: s = [] in_skip = 0 + ignoring = False for line in fid: + # check for and remove extern "C" guards + if ignoring: + if line.strip().startswith('#endif'): + ignoring = False + continue + if line.strip().startswith('#ifdef __cplusplus'): + ignoring = True + # massage the include file if line.strip().startswith('#'): continue diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index e00bc4d98..1c4689a70 100644 --- a/numpy/random/_generator.pyx +++ b/numpy/random/_generator.pyx @@ -2,6 +2,7 @@ #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 import operator import warnings +from collections.abc import Sequence from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport (Py_INCREF, PyFloat_AsDouble) @@ -598,7 +599,7 @@ cdef class Generator: """ choice(a, size=None, replace=True, p=None, axis=0, shuffle=True) - Generates a random sample from a given 1-D array + Generates a random sample from a given array Parameters ---------- @@ -664,6 +665,13 @@ cdef class Generator: array([3,1,0]) # random >>> #This is equivalent to rng.permutation(np.arange(5))[:3] + Generate a uniform random sample from a 2-D array along the first + axis (the default), without replacement: + + >>> rng.choice([[0, 1, 2], [3, 4, 5], [6, 7, 8]], 2, replace=False) + array([[3, 4, 5], # random + [0, 1, 2]]) + Generate a non-uniform random sample from np.arange(5) of size 3 without replacement: @@ -1092,7 +1100,7 @@ cdef class Generator: 0.0 # may vary >>> abs(sigma - np.std(s, ddof=1)) - 0.1 # may vary + 0.0 # may vary Display the histogram of the samples, along with the probability density function: @@ -4347,14 +4355,14 @@ cdef class Generator: """ shuffle(x, axis=0) - Modify a sequence in-place by shuffling its contents. + Modify an array or sequence in-place by shuffling its contents. The order of sub-arrays is changed but their contents remains the same. Parameters ---------- - x : array_like - The array or list to be shuffled. + x : ndarray or MutableSequence + The array, list or mutable sequence to be shuffled. axis : int, optional The axis which `x` is shuffled along. Default is 0. It is only supported on `ndarray` objects. @@ -4414,7 +4422,11 @@ cdef class Generator: with self.lock, nogil: _shuffle_raw_wrap(&self._bitgen, n, 1, itemsize, stride, x_ptr, buf_ptr) - elif isinstance(x, np.ndarray) and x.ndim and x.size: + elif isinstance(x, np.ndarray): + if x.size == 0: + # shuffling is a no-op + return + x = np.swapaxes(x, 0, axis) buf = np.empty_like(x[0, ...]) with self.lock: @@ -4428,6 +4440,15 @@ cdef class Generator: x[i] = buf else: # Untyped path. + if not isinstance(x, Sequence): + # See gh-18206. We may decide to deprecate here in the future. + warnings.warn( + "`x` isn't a recognized object; `shuffle` is not guaranteed " + "to behave correctly. E.g., non-numpy array/tensor objects " + "with view semantics may contain duplicates after shuffling.", + UserWarning, stacklevel=2 + ) + if axis != 0: raise NotImplementedError("Axis argument is only supported " "on ndarray objects") diff --git a/numpy/random/_pickle.py b/numpy/random/_pickle.py index 29ff69644..71b01d6cd 100644 --- a/numpy/random/_pickle.py +++ b/numpy/random/_pickle.py @@ -19,7 +19,7 @@ def __generator_ctor(bit_generator_name='MT19937'): Parameters ---------- - bit_generator_name: str + bit_generator_name : str String containing the core BitGenerator Returns @@ -42,7 +42,7 @@ def __bit_generator_ctor(bit_generator_name='MT19937'): Parameters ---------- - bit_generator_name: str + bit_generator_name : str String containing the name of the BitGenerator Returns @@ -65,7 +65,7 @@ def __randomstate_ctor(bit_generator_name='MT19937'): Parameters ---------- - bit_generator_name: str + bit_generator_name : str String containing the core BitGenerator Returns diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index d43e7f5aa..df8d7e380 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -2,6 +2,7 @@ #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 import operator import warnings +from collections.abc import Sequence import numpy as np @@ -4402,8 +4403,8 @@ cdef class RandomState: Parameters ---------- - x : array_like - The array or list to be shuffled. + x : ndarray or MutableSequence + The array, list or mutable sequence to be shuffled. Returns ------- @@ -4456,7 +4457,11 @@ cdef class RandomState: self._shuffle_raw(n, sizeof(np.npy_intp), stride, x_ptr, buf_ptr) else: self._shuffle_raw(n, itemsize, stride, x_ptr, buf_ptr) - elif isinstance(x, np.ndarray) and x.ndim and x.size: + elif isinstance(x, np.ndarray): + if x.size == 0: + # shuffling is a no-op + return + buf = np.empty_like(x[0, ...]) with self.lock: for i in reversed(range(1, n)): @@ -4468,6 +4473,15 @@ cdef class RandomState: x[i] = buf else: # Untyped path. + if not isinstance(x, Sequence): + # See gh-18206. We may decide to deprecate here in the future. + warnings.warn( + "`x` isn't a recognized object; `shuffle` is not guaranteed " + "to behave correctly. E.g., non-numpy array/tensor objects " + "with view semantics may contain duplicates after shuffling.", + UserWarning, stacklevel=2 + ) + with self.lock: for i in reversed(range(1, n)): j = random_interval(&self._bitgen, i) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index c4fb5883c..47c81584c 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -960,6 +960,14 @@ class TestRandomDist: random.shuffle(actual, axis=-1) assert_array_equal(actual, desired) + def test_shuffle_custom_axis_empty(self): + random = Generator(MT19937(self.seed)) + desired = np.array([]).reshape((0, 6)) + for axis in (0, 1): + actual = np.array([]).reshape((0, 6)) + random.shuffle(actual, axis=axis) + assert_array_equal(actual, desired) + def test_shuffle_axis_nonsquare(self): y1 = np.arange(20).reshape(2, 10) y2 = y1.copy() @@ -993,6 +1001,11 @@ class TestRandomDist: arr = [[1, 2, 3], [4, 5, 6]] assert_raises(NotImplementedError, random.shuffle, arr, 1) + arr = np.array(3) + assert_raises(TypeError, random.shuffle, arr) + arr = np.ones((3, 2)) + assert_raises(np.AxisError, random.shuffle, arr, 2) + def test_permutation(self): random = Generator(MT19937(self.seed)) alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] @@ -1004,7 +1017,7 @@ class TestRandomDist: arr_2d = np.atleast_2d([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]).T actual = random.permutation(arr_2d) assert_array_equal(actual, np.atleast_2d(desired).T) - + bad_x_str = "abcd" assert_raises(np.AxisError, random.permutation, bad_x_str) diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index c13fc39e3..5f8b39ef9 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -510,6 +510,21 @@ class TestRandomDist: assert_equal( sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask])) + def test_shuffle_memoryview(self): + # gh-18273 + # allow graceful handling of memoryviews + # (treat the same as arrays) + np.random.seed(self.seed) + a = np.arange(5).data + np.random.shuffle(a) + assert_equal(np.asarray(a), [0, 1, 4, 3, 2]) + rng = np.random.RandomState(self.seed) + rng.shuffle(a) + assert_equal(np.asarray(a), [0, 1, 2, 3, 4]) + rng = np.random.default_rng(self.seed) + rng.shuffle(a) + assert_equal(np.asarray(a), [4, 1, 0, 3, 2]) + def test_beta(self): np.random.seed(self.seed) actual = np.random.beta(.1, .9, size=(3, 2)) diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index b70a04347..7f5f08050 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -642,7 +642,7 @@ class TestRandomDist: a = np.array([42, 1, 2]) p = [None, None, None] assert_raises(ValueError, random.choice, a, p=p) - + def test_choice_p_non_contiguous(self): p = np.ones(10) / 5 p[1::2] = 3.0 @@ -699,6 +699,10 @@ class TestRandomDist: assert_equal( sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask])) + def test_shuffle_invalid_objects(self): + x = np.array(3) + assert_raises(TypeError, random.shuffle, x) + def test_permutation(self): random.seed(self.seed) alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] diff --git a/numpy/rec.pyi b/numpy/rec.pyi index c70ee5374..883e2dd5b 100644 --- a/numpy/rec.pyi +++ b/numpy/rec.pyi @@ -1,5 +1,12 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] record: Any recarray: Any format_parser: Any +fromarrays: Any +fromrecords: Any +fromstring: Any +fromfile: Any +array: Any diff --git a/numpy/testing/__init__.pyi b/numpy/testing/__init__.pyi index c394a387d..7dad2c9db 100644 --- a/numpy/testing/__init__.pyi +++ b/numpy/testing/__init__.pyi @@ -1,4 +1,6 @@ -from typing import Any +from typing import Any, List + +__all__: List[str] assert_equal: Any assert_almost_equal: Any diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py index 86bba57be..8147789fb 100644 --- a/numpy/typing/__init__.py +++ b/numpy/typing/__init__.py @@ -184,13 +184,15 @@ class NBitBase: .. code-block:: python - >>> from typing import TypeVar, TYPE_CHECKING + >>> from __future__ import annotations + >>> from typing import TypeVar, Union, TYPE_CHECKING >>> import numpy as np >>> import numpy.typing as npt - >>> T = TypeVar("T", bound=npt.NBitBase) + >>> T1 = TypeVar("T1", bound=npt.NBitBase) + >>> T2 = TypeVar("T2", bound=npt.NBitBase) - >>> def add(a: "np.floating[T]", b: "np.integer[T]") -> "np.floating[T]": + >>> def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[Union[T1, T2]]: ... return a + b >>> a = np.float16() @@ -283,35 +285,55 @@ from ._char_codes import ( _ObjectCodes, ) from ._scalars import ( - _CharLike, - _BoolLike, - _UIntLike, - _IntLike, - _FloatLike, - _ComplexLike, - _TD64Like, - _NumberLike, - _ScalarLike, - _VoidLike, + _CharLike_co, + _BoolLike_co, + _UIntLike_co, + _IntLike_co, + _FloatLike_co, + _ComplexLike_co, + _TD64Like_co, + _NumberLike_co, + _ScalarLike_co, + _VoidLike_co, ) from ._shape import _Shape, _ShapeLike -from ._dtype_like import _SupportsDType, _VoidDTypeLike, DTypeLike +from ._dtype_like import ( + DTypeLike as DTypeLike, + _SupportsDType, + _VoidDTypeLike, + _DTypeLikeBool, + _DTypeLikeUInt, + _DTypeLikeInt, + _DTypeLikeFloat, + _DTypeLikeComplex, + _DTypeLikeTD64, + _DTypeLikeDT64, + _DTypeLikeObject, + _DTypeLikeVoid, + _DTypeLikeStr, + _DTypeLikeBytes, +) from ._array_like import ( - ArrayLike, + ArrayLike as ArrayLike, _ArrayLike, _NestedSequence, + _RecursiveSequence, _SupportsArray, - _ArrayLikeBool, - _ArrayLikeUInt, - _ArrayLikeInt, - _ArrayLikeFloat, - _ArrayLikeComplex, - _ArrayLikeTD64, - _ArrayLikeDT64, - _ArrayLikeObject, - _ArrayLikeVoid, - _ArrayLikeStr, - _ArrayLikeBytes, + _ArrayND, + _ArrayOrScalar, + _ArrayLikeBool_co, + _ArrayLikeUInt_co, + _ArrayLikeInt_co, + _ArrayLikeFloat_co, + _ArrayLikeComplex_co, + _ArrayLikeNumber_co, + _ArrayLikeTD64_co, + _ArrayLikeDT64_co, + _ArrayLikeObject_co, + _ArrayLikeVoid_co, + _ArrayLikeStr_co, + _ArrayLikeBytes_co, + ) if __doc__ is not None: diff --git a/numpy/typing/_array_like.py b/numpy/typing/_array_like.py index d6473442c..133f38800 100644 --- a/numpy/typing/_array_like.py +++ b/numpy/typing/_array_like.py @@ -12,6 +12,7 @@ from numpy import ( integer, floating, complexfloating, + number, timedelta64, datetime64, object_, @@ -33,15 +34,17 @@ else: HAVE_PROTOCOL = True _T = TypeVar("_T") +_ScalarType = TypeVar("_ScalarType", bound=generic) _DType = TypeVar("_DType", bound="dtype[Any]") +_DType_co = TypeVar("_DType_co", covariant=True, bound="dtype[Any]") if TYPE_CHECKING or HAVE_PROTOCOL: # The `_SupportsArray` protocol only cares about the default dtype # (i.e. `dtype=None`) of the to-be returned array. # Concrete implementations of the protocol are responsible for adding # any and all remaining overloads - class _SupportsArray(Protocol[_DType]): - def __array__(self, dtype: None = ...) -> ndarray[Any, _DType]: ... + class _SupportsArray(Protocol[_DType_co]): + def __array__(self, dtype: None = ...) -> ndarray[Any, _DType_co]: ... else: _SupportsArray = Any @@ -78,41 +81,52 @@ ArrayLike = Union[ ], ] -# `ArrayLike<X>`: array-like objects that can be coerced into `X` +# `ArrayLike<X>_co`: array-like objects that can be coerced into `X` # given the casting rules `same_kind` -_ArrayLikeBool = _ArrayLike[ +_ArrayLikeBool_co = _ArrayLike[ "dtype[bool_]", bool, ] -_ArrayLikeUInt = _ArrayLike[ +_ArrayLikeUInt_co = _ArrayLike[ "dtype[Union[bool_, unsignedinteger[Any]]]", bool, ] -_ArrayLikeInt = _ArrayLike[ +_ArrayLikeInt_co = _ArrayLike[ "dtype[Union[bool_, integer[Any]]]", Union[bool, int], ] -_ArrayLikeFloat = _ArrayLike[ +_ArrayLikeFloat_co = _ArrayLike[ "dtype[Union[bool_, integer[Any], floating[Any]]]", Union[bool, int, float], ] -_ArrayLikeComplex = _ArrayLike[ +_ArrayLikeComplex_co = _ArrayLike[ "dtype[Union[bool_, integer[Any], floating[Any], complexfloating[Any, Any]]]", Union[bool, int, float, complex], ] -_ArrayLikeTD64 = _ArrayLike[ +_ArrayLikeNumber_co = _ArrayLike[ + "dtype[Union[bool_, number[Any]]]", + Union[bool, int, float, complex], +] +_ArrayLikeTD64_co = _ArrayLike[ "dtype[Union[bool_, integer[Any], timedelta64]]", Union[bool, int], ] -_ArrayLikeDT64 = _NestedSequence[_SupportsArray["dtype[datetime64]"]] -_ArrayLikeObject = _NestedSequence[_SupportsArray["dtype[object_]"]] +_ArrayLikeDT64_co = _NestedSequence[_SupportsArray["dtype[datetime64]"]] +_ArrayLikeObject_co = _NestedSequence[_SupportsArray["dtype[object_]"]] -_ArrayLikeVoid = _NestedSequence[_SupportsArray["dtype[void]"]] -_ArrayLikeStr = _ArrayLike[ +_ArrayLikeVoid_co = _NestedSequence[_SupportsArray["dtype[void]"]] +_ArrayLikeStr_co = _ArrayLike[ "dtype[str_]", str, ] -_ArrayLikeBytes = _ArrayLike[ +_ArrayLikeBytes_co = _ArrayLike[ "dtype[bytes_]", bytes, ] + +if TYPE_CHECKING: + _ArrayND = ndarray[Any, dtype[_ScalarType]] + _ArrayOrScalar = Union[_ScalarType, _ArrayND[_ScalarType]] +else: + _ArrayND = Any + _ArrayOrScalar = Any diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.py index 8f464cc75..1591ca144 100644 --- a/numpy/typing/_callable.py +++ b/numpy/typing/_callable.py @@ -8,6 +8,8 @@ See the `Mypy documentation`_ on protocols for more details. """ +from __future__ import annotations + import sys from typing import ( Union, @@ -21,6 +23,7 @@ from typing import ( from numpy import ( ndarray, + dtype, generic, bool_, timedelta64, @@ -37,14 +40,14 @@ from numpy import ( ) from ._nbit import _NBitInt from ._scalars import ( - _BoolLike, - _IntLike, - _FloatLike, - _ComplexLike, - _NumberLike, + _BoolLike_co, + _IntLike_co, + _FloatLike_co, + _ComplexLike_co, + _NumberLike_co, ) from . import NBitBase -from ._array_like import ArrayLike +from ._array_like import ArrayLike, _ArrayOrScalar if sys.version_info >= (3, 8): from typing import Protocol @@ -58,11 +61,12 @@ else: HAVE_PROTOCOL = True if TYPE_CHECKING or HAVE_PROTOCOL: - _T = TypeVar("_T") - _2Tuple = Tuple[_T, _T] + _T1 = TypeVar("_T1") + _T2 = TypeVar("_T2") + _2Tuple = Tuple[_T1, _T1] - _NBit_co = TypeVar("_NBit_co", covariant=True, bound=NBitBase) - _NBit = TypeVar("_NBit", bound=NBitBase) + _NBit1 = TypeVar("_NBit1", bound=NBitBase) + _NBit2 = TypeVar("_NBit2", bound=NBitBase) _IntType = TypeVar("_IntType", bound=integer) _FloatType = TypeVar("_FloatType", bound=floating) @@ -72,7 +76,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolOp(Protocol[_GenericType_co]): @overload - def __call__(self, __other: _BoolLike) -> _GenericType_co: ... + def __call__(self, __other: _BoolLike_co) -> _GenericType_co: ... @overload # platform dependent def __call__(self, __other: int) -> int_: ... @overload @@ -84,7 +88,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolBitOp(Protocol[_GenericType_co]): @overload - def __call__(self, __other: _BoolLike) -> _GenericType_co: ... + def __call__(self, __other: _BoolLike_co) -> _GenericType_co: ... @overload # platform dependent def __call__(self, __other: int) -> int_: ... @overload @@ -105,7 +109,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolTrueDiv(Protocol): @overload - def __call__(self, __other: Union[float, _IntLike]) -> float64: ... + def __call__(self, __other: Union[float, _IntLike_co]) -> float64: ... @overload def __call__(self, __other: complex) -> complex128: ... @overload @@ -113,7 +117,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolMod(Protocol): @overload - def __call__(self, __other: _BoolLike) -> int8: ... + def __call__(self, __other: _BoolLike_co) -> int8: ... @overload # platform dependent def __call__(self, __other: int) -> int_: ... @overload @@ -125,7 +129,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolDivMod(Protocol): @overload - def __call__(self, __other: _BoolLike) -> _2Tuple[int8]: ... + def __call__(self, __other: _BoolLike_co) -> _2Tuple[int8]: ... @overload # platform dependent def __call__(self, __other: int) -> _2Tuple[int_]: ... @overload @@ -139,11 +143,11 @@ if TYPE_CHECKING or HAVE_PROTOCOL: @overload def __call__(self, __other: timedelta64) -> _NumberType_co: ... @overload - def __call__(self, __other: _FloatLike) -> timedelta64: ... + def __call__(self, __other: _FloatLike_co) -> timedelta64: ... - class _IntTrueDiv(Protocol[_NBit_co]): + class _IntTrueDiv(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> floating[_NBit_co]: ... + def __call__(self, __other: bool) -> floating[_NBit1]: ... @overload def __call__(self, __other: int) -> floating[_NBitInt]: ... @overload @@ -151,12 +155,12 @@ if TYPE_CHECKING or HAVE_PROTOCOL: @overload def __call__(self, __other: complex) -> complex128: ... @overload - def __call__(self, __other: integer[_NBit]) -> floating[Union[_NBit_co, _NBit]]: ... + def __call__(self, __other: integer[_NBit2]) -> floating[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntOp(Protocol[_NBit_co]): + class _UnsignedIntOp(Protocol[_NBit1]): # NOTE: `uint64 + signedinteger -> float64` @overload - def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> unsignedinteger[_NBit1]: ... @overload def __call__( self, __other: Union[int, signedinteger[Any]] @@ -167,24 +171,24 @@ if TYPE_CHECKING or HAVE_PROTOCOL: def __call__(self, __other: complex) -> complex128: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> unsignedinteger[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntBitOp(Protocol[_NBit_co]): + class _UnsignedIntBitOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> unsignedinteger[_NBit1]: ... @overload def __call__(self, __other: int) -> signedinteger[Any]: ... @overload def __call__(self, __other: signedinteger[Any]) -> signedinteger[Any]: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> unsignedinteger[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntMod(Protocol[_NBit_co]): + class _UnsignedIntMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> unsignedinteger[_NBit1]: ... @overload def __call__( self, __other: Union[int, signedinteger[Any]] @@ -193,12 +197,12 @@ if TYPE_CHECKING or HAVE_PROTOCOL: def __call__(self, __other: float) -> float64: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> unsignedinteger[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntDivMod(Protocol[_NBit_co]): + class _UnsignedIntDivMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ... + def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit1]]: ... @overload def __call__( self, __other: Union[int, signedinteger[Any]] @@ -207,120 +211,120 @@ if TYPE_CHECKING or HAVE_PROTOCOL: def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> _2Tuple[unsignedinteger[Union[_NBit_co, _NBit]]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> _2Tuple[unsignedinteger[Union[_NBit1, _NBit2]]]: ... - class _SignedIntOp(Protocol[_NBit_co]): + class _SignedIntOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> signedinteger[_NBit1]: ... @overload - def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__(self, __other: complex) -> complex128: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> signedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: signedinteger[_NBit2] + ) -> signedinteger[Union[_NBit1, _NBit2]]: ... - class _SignedIntBitOp(Protocol[_NBit_co]): + class _SignedIntBitOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> signedinteger[_NBit1]: ... @overload - def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit1, _NBitInt]]: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> signedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: signedinteger[_NBit2] + ) -> signedinteger[Union[_NBit1, _NBit2]]: ... - class _SignedIntMod(Protocol[_NBit_co]): + class _SignedIntMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> signedinteger[_NBit1]: ... @overload - def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> signedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: signedinteger[_NBit2] + ) -> signedinteger[Union[_NBit1, _NBit2]]: ... - class _SignedIntDivMod(Protocol[_NBit_co]): + class _SignedIntDivMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ... + def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit1]]: ... @overload - def __call__(self, __other: int) -> _2Tuple[signedinteger[Union[_NBit_co, _NBitInt]]]: ... + def __call__(self, __other: int) -> _2Tuple[signedinteger[Union[_NBit1, _NBitInt]]]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> _2Tuple[signedinteger[Union[_NBit_co, _NBit]]]: ... + self, __other: signedinteger[_NBit2] + ) -> _2Tuple[signedinteger[Union[_NBit1, _NBit2]]]: ... - class _FloatOp(Protocol[_NBit_co]): + class _FloatOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> floating[_NBit_co]: ... + def __call__(self, __other: bool) -> floating[_NBit1]: ... @overload - def __call__(self, __other: int) -> floating[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> floating[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__(self, __other: complex) -> complex128: ... @overload def __call__( - self, __other: Union[integer[_NBit], floating[_NBit]] - ) -> floating[Union[_NBit_co, _NBit]]: ... + self, __other: Union[integer[_NBit2], floating[_NBit2]] + ) -> floating[Union[_NBit1, _NBit2]]: ... - class _FloatMod(Protocol[_NBit_co]): + class _FloatMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> floating[_NBit_co]: ... + def __call__(self, __other: bool) -> floating[_NBit1]: ... @overload - def __call__(self, __other: int) -> floating[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> floating[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__( - self, __other: Union[integer[_NBit], floating[_NBit]] - ) -> floating[Union[_NBit_co, _NBit]]: ... + self, __other: Union[integer[_NBit2], floating[_NBit2]] + ) -> floating[Union[_NBit1, _NBit2]]: ... - class _FloatDivMod(Protocol[_NBit_co]): + class _FloatDivMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> _2Tuple[floating[_NBit_co]]: ... + def __call__(self, __other: bool) -> _2Tuple[floating[_NBit1]]: ... @overload - def __call__(self, __other: int) -> _2Tuple[floating[Union[_NBit_co, _NBitInt]]]: ... + def __call__(self, __other: int) -> _2Tuple[floating[Union[_NBit1, _NBitInt]]]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload def __call__( - self, __other: Union[integer[_NBit], floating[_NBit]] - ) -> _2Tuple[floating[Union[_NBit_co, _NBit]]]: ... + self, __other: Union[integer[_NBit2], floating[_NBit2]] + ) -> _2Tuple[floating[Union[_NBit1, _NBit2]]]: ... - class _ComplexOp(Protocol[_NBit_co]): + class _ComplexOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> complexfloating[_NBit_co, _NBit_co]: ... + def __call__(self, __other: bool) -> complexfloating[_NBit1, _NBit1]: ... @overload - def __call__(self, __other: int) -> complexfloating[Union[_NBit_co, _NBitInt], Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> complexfloating[Union[_NBit1, _NBitInt], Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: Union[float, complex]) -> complex128: ... @overload def __call__( self, __other: Union[ - integer[_NBit], - floating[_NBit], - complexfloating[_NBit, _NBit], + integer[_NBit2], + floating[_NBit2], + complexfloating[_NBit2, _NBit2], ] - ) -> complexfloating[Union[_NBit_co, _NBit], Union[_NBit_co, _NBit]]: ... + ) -> complexfloating[Union[_NBit1, _NBit2], Union[_NBit1, _NBit2]]: ... class _NumberOp(Protocol): - def __call__(self, __other: _NumberLike) -> number: ... + def __call__(self, __other: _NumberLike_co) -> Any: ... - class _ComparisonOp(Protocol[_T]): + class _ComparisonOp(Protocol[_T1, _T2]): @overload - def __call__(self, __other: _T) -> bool_: ... + def __call__(self, __other: _T1) -> bool_: ... @overload - def __call__(self, __other: ArrayLike) -> Union[ndarray, bool_]: ... + def __call__(self, __other: _T2) -> _ArrayOrScalar[bool_]: ... else: _BoolOp = Any diff --git a/numpy/typing/_dtype_like.py b/numpy/typing/_dtype_like.py index 1953bd5fc..f86b4a67c 100644 --- a/numpy/typing/_dtype_like.py +++ b/numpy/typing/_dtype_like.py @@ -1,7 +1,7 @@ import sys -from typing import Any, List, Sequence, Tuple, Union, TYPE_CHECKING +from typing import Any, List, Sequence, Tuple, Union, Type, TypeVar, TYPE_CHECKING -from numpy import dtype +import numpy as np from ._shape import _ShapeLike if sys.version_info >= (3, 8): @@ -15,6 +15,48 @@ else: else: HAVE_PROTOCOL = True +from ._char_codes import ( + _BoolCodes, + _UInt8Codes, + _UInt16Codes, + _UInt32Codes, + _UInt64Codes, + _Int8Codes, + _Int16Codes, + _Int32Codes, + _Int64Codes, + _Float16Codes, + _Float32Codes, + _Float64Codes, + _Complex64Codes, + _Complex128Codes, + _ByteCodes, + _ShortCodes, + _IntCCodes, + _IntPCodes, + _IntCodes, + _LongLongCodes, + _UByteCodes, + _UShortCodes, + _UIntCCodes, + _UIntPCodes, + _UIntCodes, + _ULongLongCodes, + _HalfCodes, + _SingleCodes, + _DoubleCodes, + _LongDoubleCodes, + _CSingleCodes, + _CDoubleCodes, + _CLongDoubleCodes, + _DT64Codes, + _TD64Codes, + _StrCodes, + _BytesCodes, + _VoidCodes, + _ObjectCodes, +) + _DTypeLikeNested = Any # TODO: wait for support for recursive types if TYPE_CHECKING or HAVE_PROTOCOL: @@ -30,9 +72,12 @@ if TYPE_CHECKING or HAVE_PROTOCOL: itemsize: int aligned: bool + _DType_co = TypeVar("_DType_co", covariant=True, bound=np.dtype) + # A protocol for anything with the dtype attribute - class _SupportsDType(Protocol): - dtype: _DTypeLikeNested + class _SupportsDType(Protocol[_DType_co]): + @property + def dtype(self) -> _DType_co: ... else: _DTypeDict = Any @@ -61,13 +106,13 @@ _VoidDTypeLike = Union[ # Anything that can be coerced into numpy.dtype. # Reference: https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html DTypeLike = Union[ - dtype, + np.dtype, # default data type (float64) None, # array-scalar types and generic types type, # TODO: enumerate these when we add type hints for numpy scalars # anything with a dtype attribute - _SupportsDType, + "_SupportsDType[np.dtype[Any]]", # character codes, type strings or comma-separated fields, e.g., 'float64' str, _VoidDTypeLike, @@ -79,3 +124,107 @@ DTypeLike = Union[ # therefore not included in the Union defining `DTypeLike`. # # 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 = Union[ + Type[bool], + Type[np.bool_], + "np.dtype[np.bool_]", + "_SupportsDType[np.dtype[np.bool_]]", + _BoolCodes, +] +_DTypeLikeUInt = Union[ + Type[np.unsignedinteger], + "np.dtype[np.unsignedinteger]", + "_SupportsDType[np.dtype[np.unsignedinteger]]", + _UInt8Codes, + _UInt16Codes, + _UInt32Codes, + _UInt64Codes, + _UByteCodes, + _UShortCodes, + _UIntCCodes, + _UIntPCodes, + _UIntCodes, + _ULongLongCodes, +] +_DTypeLikeInt = Union[ + Type[int], + Type[np.signedinteger], + "np.dtype[np.signedinteger]", + "_SupportsDType[np.dtype[np.signedinteger]]", + _Int8Codes, + _Int16Codes, + _Int32Codes, + _Int64Codes, + _ByteCodes, + _ShortCodes, + _IntCCodes, + _IntPCodes, + _IntCodes, + _LongLongCodes, +] +_DTypeLikeFloat = Union[ + Type[float], + Type[np.floating], + "np.dtype[np.floating]", + "_SupportsDType[np.dtype[np.floating]]", + _Float16Codes, + _Float32Codes, + _Float64Codes, + _HalfCodes, + _SingleCodes, + _DoubleCodes, + _LongDoubleCodes, +] +_DTypeLikeComplex = Union[ + Type[complex], + Type[np.complexfloating], + "np.dtype[np.complexfloating]", + "_SupportsDType[np.dtype[np.complexfloating]]", + _Complex64Codes, + _Complex128Codes, + _CSingleCodes, + _CDoubleCodes, + _CLongDoubleCodes, +] +_DTypeLikeDT64 = Union[ + Type[np.timedelta64], + "np.dtype[np.timedelta64]", + "_SupportsDType[np.dtype[np.timedelta64]]", + _TD64Codes, +] +_DTypeLikeTD64 = Union[ + Type[np.datetime64], + "np.dtype[np.datetime64]", + "_SupportsDType[np.dtype[np.datetime64]]", + _DT64Codes, +] +_DTypeLikeStr = Union[ + Type[str], + Type[np.str_], + "np.dtype[np.str_]", + "_SupportsDType[np.dtype[np.str_]]", + _StrCodes, +] +_DTypeLikeBytes = Union[ + Type[bytes], + Type[np.bytes_], + "np.dtype[np.bytes_]", + "_SupportsDType[np.dtype[np.bytes_]]", + _BytesCodes, +] +_DTypeLikeVoid = Union[ + Type[np.void], + "np.dtype[np.void]", + "_SupportsDType[np.dtype[np.void]]", + _VoidCodes, + _VoidDTypeLike, +] +_DTypeLikeObject = Union[ + type, + "np.dtype[np.object_]", + "_SupportsDType[np.dtype[np.object_]]", + _ObjectCodes, +] diff --git a/numpy/typing/_scalars.py b/numpy/typing/_scalars.py index 90b2eff7b..516b996dc 100644 --- a/numpy/typing/_scalars.py +++ b/numpy/typing/_scalars.py @@ -2,22 +2,22 @@ from typing import Union, Tuple, Any import numpy as np -# NOTE: `_StrLike` and `_BytesLike` are pointless, as `np.str_` and `np.bytes_` -# are already subclasses of their builtin counterpart +# NOTE: `_StrLike_co` and `_BytesLike_co` are pointless, as `np.str_` and +# `np.bytes_` are already subclasses of their builtin counterpart -_CharLike = Union[str, bytes] +_CharLike_co = Union[str, bytes] -# The 6 `<X>Like` type-aliases below represent all scalars that can be +# The 6 `<X>Like_co` type-aliases below represent all scalars that can be # coerced into `<X>` (with the casting rule `same_kind`) -_BoolLike = Union[bool, np.bool_] -_UIntLike = Union[_BoolLike, np.unsignedinteger] -_IntLike = Union[_BoolLike, int, np.integer] -_FloatLike = Union[_IntLike, float, np.floating] -_ComplexLike = Union[_FloatLike, complex, np.complexfloating] -_TD64Like = Union[_IntLike, np.timedelta64] +_BoolLike_co = Union[bool, np.bool_] +_UIntLike_co = Union[_BoolLike_co, np.unsignedinteger] +_IntLike_co = Union[_BoolLike_co, int, np.integer] +_FloatLike_co = Union[_IntLike_co, float, np.floating] +_ComplexLike_co = Union[_FloatLike_co, complex, np.complexfloating] +_TD64Like_co = Union[_IntLike_co, np.timedelta64] -_NumberLike = Union[int, float, complex, np.number, np.bool_] -_ScalarLike = Union[ +_NumberLike_co = Union[int, float, complex, np.number, np.bool_] +_ScalarLike_co = Union[ int, float, complex, @@ -26,5 +26,5 @@ _ScalarLike = Union[ np.generic, ] -# `_VoidLike` is technically not a scalar, but it's close enough -_VoidLike = Union[Tuple[Any, ...], np.void] +# `_VoidLike_co` is technically not a scalar, but it's close enough +_VoidLike_co = Union[Tuple[Any, ...], np.void] diff --git a/numpy/typing/tests/data/fail/arithmetic.py b/numpy/typing/tests/data/fail/arithmetic.py index f32eddc4b..bad7040b9 100644 --- a/numpy/typing/tests/data/fail/arithmetic.py +++ b/numpy/typing/tests/data/fail/arithmetic.py @@ -1,9 +1,39 @@ +from typing import List, Any import numpy as np b_ = np.bool_() dt = np.datetime64(0, "D") td = np.timedelta64(0, "D") +AR_b: np.ndarray[Any, np.dtype[np.bool_]] +AR_f: np.ndarray[Any, np.dtype[np.float64]] +AR_c: np.ndarray[Any, np.dtype[np.complex128]] +AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] +AR_M: np.ndarray[Any, np.dtype[np.datetime64]] + +AR_LIKE_b: List[bool] +AR_LIKE_f: List[float] +AR_LIKE_c: List[complex] +AR_LIKE_m: List[np.timedelta64] +AR_LIKE_M: List[np.datetime64] + +# NOTE: mypys `NoReturn` errors are, unfortunately, not that great +_1 = AR_b - AR_LIKE_b # E: Need type annotation +_2 = AR_LIKE_b - AR_b # E: Need type annotation + +AR_f - AR_LIKE_m # E: Unsupported operand types +AR_f - AR_LIKE_M # E: Unsupported operand types +AR_c - AR_LIKE_m # E: Unsupported operand types +AR_c - AR_LIKE_M # E: Unsupported operand types + +AR_m - AR_LIKE_f # E: Unsupported operand types +AR_M - AR_LIKE_f # E: Unsupported operand types +AR_m - AR_LIKE_c # E: Unsupported operand types +AR_M - AR_LIKE_c # E: Unsupported operand types + +AR_m - AR_LIKE_M # E: Unsupported operand types +AR_LIKE_m - AR_M # E: Unsupported operand types + b_ - b_ # E: No overload variant dt + dt # E: Unsupported operand types diff --git a/numpy/typing/tests/data/fail/array_constructors.py b/numpy/typing/tests/data/fail/array_constructors.py index 9cb59fe5f..f13fdacb2 100644 --- a/numpy/typing/tests/data/fail/array_constructors.py +++ b/numpy/typing/tests/data/fail/array_constructors.py @@ -7,10 +7,10 @@ np.require(a, requirements=1) # E: No overload variant np.require(a, requirements="TEST") # E: incompatible type np.zeros("test") # E: incompatible type -np.zeros() # E: Too few arguments +np.zeros() # E: Missing positional argument np.ones("test") # E: incompatible type -np.ones() # E: Too few arguments +np.ones() # E: Missing positional argument np.array(0, float, True) # E: Too many positional diff --git a/numpy/typing/tests/data/fail/comparisons.py b/numpy/typing/tests/data/fail/comparisons.py new file mode 100644 index 000000000..cad1c6555 --- /dev/null +++ b/numpy/typing/tests/data/fail/comparisons.py @@ -0,0 +1,28 @@ +from typing import Any +import numpy as np + +AR_i: np.ndarray[Any, np.dtype[np.int64]] +AR_f: np.ndarray[Any, np.dtype[np.float64]] +AR_c: np.ndarray[Any, np.dtype[np.complex128]] +AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] +AR_M: np.ndarray[Any, np.dtype[np.datetime64]] + +AR_f > AR_m # E: Unsupported operand types +AR_c > AR_m # E: Unsupported operand types + +AR_m > AR_f # E: Unsupported operand types +AR_m > AR_c # E: Unsupported operand types + +AR_i > AR_M # E: Unsupported operand types +AR_f > AR_M # E: Unsupported operand types +AR_m > AR_M # E: Unsupported operand types + +AR_M > AR_i # E: Unsupported operand types +AR_M > AR_f # E: Unsupported operand types +AR_M > AR_m # E: Unsupported operand types + +# Unfortunately `NoReturn` errors are not the most descriptive +_1 = AR_i > str() # E: Need type annotation +_2 = AR_i > bytes() # E: Need type annotation +_3 = str() > AR_M # E: Need type annotation +_4 = bytes() > AR_M # E: Need type annotation diff --git a/numpy/typing/tests/data/fail/dtype.py b/numpy/typing/tests/data/fail/dtype.py index 7d4783d8f..7d419a1d1 100644 --- a/numpy/typing/tests/data/fail/dtype.py +++ b/numpy/typing/tests/data/fail/dtype.py @@ -1,10 +1,16 @@ import numpy as np -class Test: - not_dtype = float +class Test1: + not_dtype = np.dtype(float) -np.dtype(Test()) # E: No overload variant of "dtype" matches + +class Test2: + dtype = float + + +np.dtype(Test1()) # E: No overload variant of "dtype" matches +np.dtype(Test2()) # E: incompatible type np.dtype( # E: No overload variant of "dtype" matches { diff --git a/numpy/typing/tests/data/fail/modules.py b/numpy/typing/tests/data/fail/modules.py index 5e2d820ab..b80fd9ede 100644 --- a/numpy/typing/tests/data/fail/modules.py +++ b/numpy/typing/tests/data/fail/modules.py @@ -8,3 +8,7 @@ np.warnings # E: Module has no attribute np.sys # E: Module has no attribute np.os # E: Module has no attribute np.math # E: Module has no attribute + +np.__NUMPY_SETUP__ # E: Module has no attribute +np.__deprecated_attrs__ # E: Module has no attribute +np.__expired_functions__ # E: Module has no attribute diff --git a/numpy/typing/tests/data/fail/scalars.py b/numpy/typing/tests/data/fail/scalars.py index f09740875..0aeff398f 100644 --- a/numpy/typing/tests/data/fail/scalars.py +++ b/numpy/typing/tests/data/fail/scalars.py @@ -1,5 +1,6 @@ import numpy as np +f2: np.float16 f8: np.float64 # Construction @@ -74,3 +75,8 @@ f8.item((0, 1)) # E: incompatible type f8.squeeze(axis=1) # E: incompatible type f8.squeeze(axis=(0, 1)) # E: incompatible type f8.transpose(1) # E: incompatible type + +def func(a: np.float32) -> None: ... + +func(f2) # E: incompatible type +func(f8) # E: incompatible type diff --git a/numpy/typing/tests/data/mypy.ini b/numpy/typing/tests/data/mypy.ini index 35cfbec89..548f76261 100644 --- a/numpy/typing/tests/data/mypy.ini +++ b/numpy/typing/tests/data/mypy.ini @@ -1,5 +1,6 @@ [mypy] plugins = numpy.typing.mypy_plugin +show_absolute_path = True [mypy-numpy] ignore_errors = True diff --git a/numpy/typing/tests/data/pass/arithmetic.py b/numpy/typing/tests/data/pass/arithmetic.py index ffbaf2975..4840d1fab 100644 --- a/numpy/typing/tests/data/pass/arithmetic.py +++ b/numpy/typing/tests/data/pass/arithmetic.py @@ -1,3 +1,6 @@ +from __future__ import annotations + +from typing import Any import numpy as np c16 = np.complex128(1) @@ -20,8 +23,149 @@ c = complex(1) f = float(1) i = int(1) -AR = np.ones(1, dtype=np.float64) -AR.setflags(write=False) + +class Object: + def __array__(self, dtype: None = None) -> np.ndarray[Any, np.dtype[np.object_]]: + ret = np.empty((), dtype=object) + ret[()] = self + return ret + + def __sub__(self, value: Any) -> Object: + return self + + def __rsub__(self, value: Any) -> Object: + return self + + +AR_b: np.ndarray[Any, np.dtype[np.bool_]] = np.array([True]) +AR_u: np.ndarray[Any, np.dtype[np.uint32]] = np.array([1], dtype=np.uint32) +AR_i: np.ndarray[Any, np.dtype[np.int64]] = np.array([1]) +AR_f: np.ndarray[Any, np.dtype[np.float64]] = np.array([1.0]) +AR_c: np.ndarray[Any, np.dtype[np.complex128]] = np.array([1j]) +AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] = np.array([np.timedelta64(1, "D")]) +AR_M: np.ndarray[Any, np.dtype[np.datetime64]] = np.array([np.datetime64(1, "D")]) +AR_O: np.ndarray[Any, np.dtype[np.object_]] = np.array([Object()]) + +AR_LIKE_b = [True] +AR_LIKE_u = [np.uint32(1)] +AR_LIKE_i = [1] +AR_LIKE_f = [1.0] +AR_LIKE_c = [1j] +AR_LIKE_m = [np.timedelta64(1, "D")] +AR_LIKE_M = [np.datetime64(1, "D")] +AR_LIKE_O = [Object()] + +# Array subtractions + +AR_b - AR_LIKE_u +AR_b - AR_LIKE_i +AR_b - AR_LIKE_f +AR_b - AR_LIKE_c +AR_b - AR_LIKE_m +AR_b - AR_LIKE_O + +AR_LIKE_u - AR_b +AR_LIKE_i - AR_b +AR_LIKE_f - AR_b +AR_LIKE_c - AR_b +AR_LIKE_m - AR_b +AR_LIKE_M - AR_b +AR_LIKE_O - AR_b + +AR_u - AR_LIKE_b +AR_u - AR_LIKE_u +AR_u - AR_LIKE_i +AR_u - AR_LIKE_f +AR_u - AR_LIKE_c +AR_u - AR_LIKE_m +AR_u - AR_LIKE_O + +AR_LIKE_b - AR_u +AR_LIKE_u - AR_u +AR_LIKE_i - AR_u +AR_LIKE_f - AR_u +AR_LIKE_c - AR_u +AR_LIKE_m - AR_u +AR_LIKE_M - AR_u +AR_LIKE_O - AR_u + +AR_i - AR_LIKE_b +AR_i - AR_LIKE_u +AR_i - AR_LIKE_i +AR_i - AR_LIKE_f +AR_i - AR_LIKE_c +AR_i - AR_LIKE_m +AR_i - AR_LIKE_O + +AR_LIKE_b - AR_i +AR_LIKE_u - AR_i +AR_LIKE_i - AR_i +AR_LIKE_f - AR_i +AR_LIKE_c - AR_i +AR_LIKE_m - AR_i +AR_LIKE_M - AR_i +AR_LIKE_O - AR_i + +AR_f - AR_LIKE_b +AR_f - AR_LIKE_u +AR_f - AR_LIKE_i +AR_f - AR_LIKE_f +AR_f - AR_LIKE_c +AR_f - AR_LIKE_O + +AR_LIKE_b - AR_f +AR_LIKE_u - AR_f +AR_LIKE_i - AR_f +AR_LIKE_f - AR_f +AR_LIKE_c - AR_f +AR_LIKE_O - AR_f + +AR_c - AR_LIKE_b +AR_c - AR_LIKE_u +AR_c - AR_LIKE_i +AR_c - AR_LIKE_f +AR_c - AR_LIKE_c +AR_c - AR_LIKE_O + +AR_LIKE_b - AR_c +AR_LIKE_u - AR_c +AR_LIKE_i - AR_c +AR_LIKE_f - AR_c +AR_LIKE_c - AR_c +AR_LIKE_O - AR_c + +AR_m - AR_LIKE_b +AR_m - AR_LIKE_u +AR_m - AR_LIKE_i +AR_m - AR_LIKE_m + +AR_LIKE_b - AR_m +AR_LIKE_u - AR_m +AR_LIKE_i - AR_m +AR_LIKE_m - AR_m +AR_LIKE_M - AR_m + +AR_M - AR_LIKE_b +AR_M - AR_LIKE_u +AR_M - AR_LIKE_i +AR_M - AR_LIKE_m +AR_M - AR_LIKE_M + +AR_LIKE_M - AR_M + +AR_O - AR_LIKE_b +AR_O - AR_LIKE_u +AR_O - AR_LIKE_i +AR_O - AR_LIKE_f +AR_O - AR_LIKE_c +AR_O - AR_LIKE_O + +AR_LIKE_b - AR_O +AR_LIKE_u - AR_O +AR_LIKE_i - AR_O +AR_LIKE_f - AR_O +AR_LIKE_c - AR_O +AR_LIKE_O - AR_O # unary ops @@ -34,7 +178,7 @@ AR.setflags(write=False) -u8 -u4 -td --AR +-AR_f +c16 +c8 @@ -45,7 +189,7 @@ AR.setflags(write=False) +u8 +u4 +td -+AR ++AR_f abs(c16) abs(c8) @@ -57,7 +201,7 @@ abs(u8) abs(u4) abs(td) abs(b_) -abs(AR) +abs(AR_f) # Time structures @@ -129,7 +273,7 @@ c16 + b c16 + c c16 + f c16 + i -c16 + AR +c16 + AR_f c16 + c16 f8 + c16 @@ -142,7 +286,7 @@ b + c16 c + c16 f + c16 i + c16 -AR + c16 +AR_f + c16 c8 + c16 c8 + f8 @@ -155,7 +299,7 @@ c8 + b c8 + c c8 + f c8 + i -c8 + AR +c8 + AR_f c16 + c8 f8 + c8 @@ -168,7 +312,7 @@ b + c8 c + c8 f + c8 i + c8 -AR + c8 +AR_f + c8 # Float @@ -181,7 +325,7 @@ f8 + b f8 + c f8 + f f8 + i -f8 + AR +f8 + AR_f f8 + f8 i8 + f8 @@ -192,7 +336,7 @@ b + f8 c + f8 f + f8 i + f8 -AR + f8 +AR_f + f8 f4 + f8 f4 + i8 @@ -203,7 +347,7 @@ f4 + b f4 + c f4 + f f4 + i -f4 + AR +f4 + AR_f f8 + f4 i8 + f4 @@ -214,7 +358,7 @@ b + f4 c + f4 f + f4 i + f4 -AR + f4 +AR_f + f4 # Int @@ -227,7 +371,7 @@ i8 + b i8 + c i8 + f i8 + i -i8 + AR +i8 + AR_f u8 + u8 u8 + i4 @@ -237,7 +381,7 @@ u8 + b u8 + c u8 + f u8 + i -u8 + AR +u8 + AR_f i8 + i8 u8 + i8 @@ -248,7 +392,7 @@ b + i8 c + i8 f + i8 i + i8 -AR + i8 +AR_f + i8 u8 + u8 i4 + u8 @@ -258,14 +402,14 @@ b + u8 c + u8 f + u8 i + u8 -AR + u8 +AR_f + u8 i4 + i8 i4 + i4 i4 + i i4 + b_ i4 + b -i4 + AR +i4 + AR_f u4 + i8 u4 + i4 @@ -274,14 +418,14 @@ u4 + u4 u4 + i u4 + b_ u4 + b -u4 + AR +u4 + AR_f i8 + i4 i4 + i4 i + i4 b_ + i4 b + i4 -AR + i4 +AR_f + i4 i8 + u4 i4 + u4 @@ -290,4 +434,4 @@ u4 + u4 b_ + u4 b + u4 i + u4 -AR + u4 +AR_f + u4 diff --git a/numpy/typing/tests/data/pass/comparisons.py b/numpy/typing/tests/data/pass/comparisons.py index b298117a6..ce41de435 100644 --- a/numpy/typing/tests/data/pass/comparisons.py +++ b/numpy/typing/tests/data/pass/comparisons.py @@ -1,3 +1,6 @@ +from __future__ import annotations + +from typing import Any import numpy as np c16 = np.complex128() @@ -20,11 +23,62 @@ c = complex() f = float() i = int() -AR = np.array([0], dtype=np.int64) -AR.setflags(write=False) - SEQ = (0, 1, 2, 3, 4) +AR_b: np.ndarray[Any, np.dtype[np.bool_]] = np.array([True]) +AR_u: np.ndarray[Any, np.dtype[np.uint32]] = np.array([1], dtype=np.uint32) +AR_i: np.ndarray[Any, np.dtype[np.int_]] = np.array([1]) +AR_f: np.ndarray[Any, np.dtype[np.float_]] = np.array([1.0]) +AR_c: np.ndarray[Any, np.dtype[np.complex_]] = np.array([1.0j]) +AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] = np.array([np.timedelta64("1")]) +AR_M: np.ndarray[Any, np.dtype[np.datetime64]] = np.array([np.datetime64("1")]) +AR_O: np.ndarray[Any, np.dtype[np.object_]] = np.array([1], dtype=object) + +# Arrays + +AR_b > AR_b +AR_b > AR_u +AR_b > AR_i +AR_b > AR_f +AR_b > AR_c + +AR_u > AR_b +AR_u > AR_u +AR_u > AR_i +AR_u > AR_f +AR_u > AR_c + +AR_i > AR_b +AR_i > AR_u +AR_i > AR_i +AR_i > AR_f +AR_i > AR_c + +AR_f > AR_b +AR_f > AR_u +AR_f > AR_i +AR_f > AR_f +AR_f > AR_c + +AR_c > AR_b +AR_c > AR_u +AR_c > AR_i +AR_c > AR_f +AR_c > AR_c + +AR_m > AR_b +AR_m > AR_u +AR_m > AR_i +AR_b > AR_m +AR_u > AR_m +AR_i > AR_m + +AR_M > AR_M + +AR_O > AR_O +1 > AR_O +AR_O > 1 + # Time structures dt > dt @@ -33,7 +87,7 @@ td > td td > i td > i4 td > i8 -td > AR +td > AR_i td > SEQ # boolean @@ -51,7 +105,7 @@ b_ > f4 b_ > c b_ > c16 b_ > c8 -b_ > AR +b_ > AR_i b_ > SEQ # Complex @@ -67,7 +121,7 @@ c16 > b c16 > c c16 > f c16 > i -c16 > AR +c16 > AR_i c16 > SEQ c16 > c16 @@ -81,7 +135,7 @@ b > c16 c > c16 f > c16 i > c16 -AR > c16 +AR_i > c16 SEQ > c16 c8 > c16 @@ -95,7 +149,7 @@ c8 > b c8 > c c8 > f c8 > i -c8 > AR +c8 > AR_i c8 > SEQ c16 > c8 @@ -109,7 +163,7 @@ b > c8 c > c8 f > c8 i > c8 -AR > c8 +AR_i > c8 SEQ > c8 # Float @@ -123,7 +177,7 @@ f8 > b f8 > c f8 > f f8 > i -f8 > AR +f8 > AR_i f8 > SEQ f8 > f8 @@ -135,7 +189,7 @@ b > f8 c > f8 f > f8 i > f8 -AR > f8 +AR_i > f8 SEQ > f8 f4 > f8 @@ -147,7 +201,7 @@ f4 > b f4 > c f4 > f f4 > i -f4 > AR +f4 > AR_i f4 > SEQ f8 > f4 @@ -159,7 +213,7 @@ b > f4 c > f4 f > f4 i > f4 -AR > f4 +AR_i > f4 SEQ > f4 # Int @@ -173,7 +227,7 @@ i8 > b i8 > c i8 > f i8 > i -i8 > AR +i8 > AR_i i8 > SEQ u8 > u8 @@ -184,7 +238,7 @@ u8 > b u8 > c u8 > f u8 > i -u8 > AR +u8 > AR_i u8 > SEQ i8 > i8 @@ -196,7 +250,7 @@ b > i8 c > i8 f > i8 i > i8 -AR > i8 +AR_i > i8 SEQ > i8 u8 > u8 @@ -207,7 +261,7 @@ b > u8 c > u8 f > u8 i > u8 -AR > u8 +AR_i > u8 SEQ > u8 i4 > i8 @@ -215,7 +269,7 @@ i4 > i4 i4 > i i4 > b_ i4 > b -i4 > AR +i4 > AR_i i4 > SEQ u4 > i8 @@ -225,7 +279,7 @@ u4 > u4 u4 > i u4 > b_ u4 > b -u4 > AR +u4 > AR_i u4 > SEQ i8 > i4 @@ -233,7 +287,7 @@ i4 > i4 i > i4 b_ > i4 b > i4 -AR > i4 +AR_i > i4 SEQ > i4 i8 > u4 @@ -243,5 +297,5 @@ u4 > u4 b_ > u4 b > u4 i > u4 -AR > u4 +AR_i > u4 SEQ > u4 diff --git a/numpy/typing/tests/data/pass/modules.py b/numpy/typing/tests/data/pass/modules.py new file mode 100644 index 000000000..2fdb69eb3 --- /dev/null +++ b/numpy/typing/tests/data/pass/modules.py @@ -0,0 +1,31 @@ +import numpy as np +from numpy import f2py + +np.char +np.ctypeslib +np.emath +np.fft +np.lib +np.linalg +np.ma +np.matrixlib +np.polynomial +np.random +np.rec +np.testing +np.version + +np.__path__ +np.__version__ +np.__git_version__ + +np.__all__ +np.char.__all__ +np.ctypeslib.__all__ +np.emath.__all__ +np.lib.__all__ +np.ma.__all__ +np.random.__all__ +np.rec.__all__ +np.testing.__all__ +f2py.__all__ diff --git a/numpy/typing/tests/data/pass/scalars.py b/numpy/typing/tests/data/pass/scalars.py index 2f2643e8e..c3f4ddbcc 100644 --- a/numpy/typing/tests/data/pass/scalars.py +++ b/numpy/typing/tests/data/pass/scalars.py @@ -166,6 +166,11 @@ c16.transpose() # Aliases np.str0() +np.bool8() +np.bytes0() +np.string_() +np.object0() +np.void0(0) np.byte() np.short() diff --git a/numpy/typing/tests/data/reveal/arithmetic.py b/numpy/typing/tests/data/reveal/arithmetic.py index 8574df936..1a0f595c5 100644 --- a/numpy/typing/tests/data/reveal/arithmetic.py +++ b/numpy/typing/tests/data/reveal/arithmetic.py @@ -1,3 +1,4 @@ +from typing import Any, List import numpy as np c16 = np.complex128() @@ -20,8 +21,143 @@ c = complex() f = float() i = int() -AR = np.array([0], dtype=np.float64) -AR.setflags(write=False) +AR_b: np.ndarray[Any, np.dtype[np.bool_]] +AR_u: np.ndarray[Any, np.dtype[np.uint32]] +AR_i: np.ndarray[Any, np.dtype[np.int64]] +AR_f: np.ndarray[Any, np.dtype[np.float64]] +AR_c: np.ndarray[Any, np.dtype[np.complex128]] +AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] +AR_M: np.ndarray[Any, np.dtype[np.datetime64]] +AR_O: np.ndarray[Any, np.dtype[np.object_]] + +AR_LIKE_b: List[bool] +AR_LIKE_u: List[np.uint32] +AR_LIKE_i: List[int] +AR_LIKE_f: List[float] +AR_LIKE_c: List[complex] +AR_LIKE_m: List[np.timedelta64] +AR_LIKE_M: List[np.datetime64] +AR_LIKE_O: List[np.object_] + +# Array subtraction + +reveal_type(AR_b - AR_LIKE_u) # E: Union[numpy.unsignedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.unsignedinteger[Any]]]] +reveal_type(AR_b - AR_LIKE_i) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_b - AR_LIKE_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_b - AR_LIKE_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_b - AR_LIKE_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_b - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_u - AR_b) # E: Union[numpy.unsignedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.unsignedinteger[Any]]]] +reveal_type(AR_LIKE_i - AR_b) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_LIKE_f - AR_b) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_c - AR_b) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_m - AR_b) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_M - AR_b) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_LIKE_O - AR_b) # E: Any + +reveal_type(AR_u - AR_LIKE_b) # E: Union[numpy.unsignedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.unsignedinteger[Any]]]] +reveal_type(AR_u - AR_LIKE_u) # E: Union[numpy.unsignedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.unsignedinteger[Any]]]] +reveal_type(AR_u - AR_LIKE_i) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_u - AR_LIKE_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_u - AR_LIKE_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_u - AR_LIKE_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_u - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_b - AR_u) # E: Union[numpy.unsignedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.unsignedinteger[Any]]]] +reveal_type(AR_LIKE_u - AR_u) # E: Union[numpy.unsignedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.unsignedinteger[Any]]]] +reveal_type(AR_LIKE_i - AR_u) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_LIKE_f - AR_u) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_c - AR_u) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_m - AR_u) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_M - AR_u) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_LIKE_O - AR_u) # E: Any + +reveal_type(AR_i - AR_LIKE_b) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_i - AR_LIKE_u) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_i - AR_LIKE_i) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_i - AR_LIKE_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_i - AR_LIKE_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_i - AR_LIKE_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_i - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_b - AR_i) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_LIKE_u - AR_i) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_LIKE_i - AR_i) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] +reveal_type(AR_LIKE_f - AR_i) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_c - AR_i) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_m - AR_i) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_M - AR_i) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_LIKE_O - AR_i) # E: Any + +reveal_type(AR_f - AR_LIKE_b) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_f - AR_LIKE_u) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_f - AR_LIKE_i) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_f - AR_LIKE_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_f - AR_LIKE_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_f - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_b - AR_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_u - AR_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_i - AR_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_f - AR_f) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] +reveal_type(AR_LIKE_c - AR_f) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_O - AR_f) # E: Any + +reveal_type(AR_c - AR_LIKE_b) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_c - AR_LIKE_u) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_c - AR_LIKE_i) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_c - AR_LIKE_f) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_c - AR_LIKE_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_c - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_b - AR_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_u - AR_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_i - AR_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_f - AR_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_c - AR_c) # E: Union[numpy.complexfloating[Any, Any], numpy.ndarray[Any, numpy.dtype[numpy.complexfloating[Any, Any]]]] +reveal_type(AR_LIKE_O - AR_c) # E: Any + +reveal_type(AR_m - AR_LIKE_b) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_m - AR_LIKE_u) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_m - AR_LIKE_i) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_m - AR_LIKE_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_m - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_b - AR_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_u - AR_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_i - AR_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_m - AR_m) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_M - AR_m) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_LIKE_O - AR_m) # E: Any + +reveal_type(AR_M - AR_LIKE_b) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_M - AR_LIKE_u) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_M - AR_LIKE_i) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_M - AR_LIKE_m) # E: Union[numpy.datetime64, numpy.ndarray[Any, numpy.dtype[numpy.datetime64]]] +reveal_type(AR_M - AR_LIKE_M) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_M - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_M - AR_M) # E: Union[numpy.timedelta64, numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]] +reveal_type(AR_LIKE_O - AR_M) # E: Any + +reveal_type(AR_O - AR_LIKE_b) # E: Any +reveal_type(AR_O - AR_LIKE_u) # E: Any +reveal_type(AR_O - AR_LIKE_i) # E: Any +reveal_type(AR_O - AR_LIKE_f) # E: Any +reveal_type(AR_O - AR_LIKE_c) # E: Any +reveal_type(AR_O - AR_LIKE_m) # E: Any +reveal_type(AR_O - AR_LIKE_M) # E: Any +reveal_type(AR_O - AR_LIKE_O) # E: Any + +reveal_type(AR_LIKE_b - AR_O) # E: Any +reveal_type(AR_LIKE_u - AR_O) # E: Any +reveal_type(AR_LIKE_i - AR_O) # E: Any +reveal_type(AR_LIKE_f - AR_O) # E: Any +reveal_type(AR_LIKE_c - AR_O) # E: Any +reveal_type(AR_LIKE_m - AR_O) # E: Any +reveal_type(AR_LIKE_M - AR_O) # E: Any +reveal_type(AR_LIKE_O - AR_O) # E: Any # unary ops @@ -34,7 +170,7 @@ reveal_type(-i4) # E: {int32} reveal_type(-u8) # E: {uint64} reveal_type(-u4) # E: {uint32} reveal_type(-td) # E: numpy.timedelta64 -reveal_type(-AR) # E: Any +reveal_type(-AR_f) # E: Any reveal_type(+c16) # E: {complex128} reveal_type(+c8) # E: {complex64} @@ -45,7 +181,7 @@ reveal_type(+i4) # E: {int32} reveal_type(+u8) # E: {uint64} reveal_type(+u4) # E: {uint32} reveal_type(+td) # E: numpy.timedelta64 -reveal_type(+AR) # E: Any +reveal_type(+AR_f) # E: Any reveal_type(abs(c16)) # E: {float64} reveal_type(abs(c8)) # E: {float32} @@ -57,7 +193,7 @@ reveal_type(abs(u8)) # E: {uint64} reveal_type(abs(u4)) # E: {uint32} reveal_type(abs(td)) # E: numpy.timedelta64 reveal_type(abs(b_)) # E: numpy.bool_ -reveal_type(abs(AR)) # E: Any +reveal_type(abs(AR_f)) # E: Any # Time structures @@ -128,7 +264,7 @@ reveal_type(c16 + c) # E: {complex128} reveal_type(c16 + f) # E: {complex128} reveal_type(c16 + i) # E: {complex128} -reveal_type(c16 + AR) # E: Any +reveal_type(c16 + AR_f) # E: Any reveal_type(c16 + c16) # E: {complex128} reveal_type(f8 + c16) # E: {complex128} @@ -141,7 +277,7 @@ reveal_type(b + c16) # E: {complex128} reveal_type(c + c16) # E: {complex128} reveal_type(f + c16) # E: {complex128} reveal_type(i + c16) # E: {complex128} -reveal_type(AR + c16) # E: Any +reveal_type(AR_f + c16) # E: Any reveal_type(c8 + c16) # E: {complex128} reveal_type(c8 + f8) # E: {complex128} @@ -154,7 +290,7 @@ reveal_type(c8 + b) # E: {complex64} reveal_type(c8 + c) # E: {complex128} reveal_type(c8 + f) # E: {complex128} reveal_type(c8 + i) # E: numpy.complexfloating[{_NBitInt}, {_NBitInt}] -reveal_type(c8 + AR) # E: Any +reveal_type(c8 + AR_f) # E: Any reveal_type(c16 + c8) # E: {complex128} reveal_type(f8 + c8) # E: {complex128} @@ -167,7 +303,7 @@ reveal_type(b + c8) # E: {complex64} reveal_type(c + c8) # E: {complex128} reveal_type(f + c8) # E: {complex128} reveal_type(i + c8) # E: numpy.complexfloating[{_NBitInt}, {_NBitInt}] -reveal_type(AR + c8) # E: Any +reveal_type(AR_f + c8) # E: Any # Float @@ -180,7 +316,7 @@ reveal_type(f8 + b) # E: {float64} reveal_type(f8 + c) # E: {complex128} reveal_type(f8 + f) # E: {float64} reveal_type(f8 + i) # E: {float64} -reveal_type(f8 + AR) # E: Any +reveal_type(f8 + AR_f) # E: Any reveal_type(f8 + f8) # E: {float64} reveal_type(i8 + f8) # E: {float64} @@ -191,7 +327,7 @@ reveal_type(b + f8) # E: {float64} reveal_type(c + f8) # E: {complex128} reveal_type(f + f8) # E: {float64} reveal_type(i + f8) # E: {float64} -reveal_type(AR + f8) # E: Any +reveal_type(AR_f + f8) # E: Any reveal_type(f4 + f8) # E: {float64} reveal_type(f4 + i8) # E: {float64} @@ -202,7 +338,7 @@ reveal_type(f4 + b) # E: {float32} reveal_type(f4 + c) # E: {complex128} reveal_type(f4 + f) # E: {float64} reveal_type(f4 + i) # E: numpy.floating[{_NBitInt}] -reveal_type(f4 + AR) # E: Any +reveal_type(f4 + AR_f) # E: Any reveal_type(f8 + f4) # E: {float64} reveal_type(i8 + f4) # E: {float64} @@ -213,7 +349,7 @@ reveal_type(b + f4) # E: {float32} reveal_type(c + f4) # E: {complex128} reveal_type(f + f4) # E: {float64} reveal_type(i + f4) # E: numpy.floating[{_NBitInt}] -reveal_type(AR + f4) # E: Any +reveal_type(AR_f + f4) # E: Any # Int @@ -226,7 +362,7 @@ reveal_type(i8 + b) # E: {int64} reveal_type(i8 + c) # E: {complex128} reveal_type(i8 + f) # E: {float64} reveal_type(i8 + i) # E: {int64} -reveal_type(i8 + AR) # E: Any +reveal_type(i8 + AR_f) # E: Any reveal_type(u8 + u8) # E: {uint64} reveal_type(u8 + i4) # E: Union[numpy.signedinteger[Any], {float64}] @@ -236,7 +372,7 @@ reveal_type(u8 + b) # E: {uint64} reveal_type(u8 + c) # E: {complex128} reveal_type(u8 + f) # E: {float64} reveal_type(u8 + i) # E: Union[numpy.signedinteger[Any], {float64}] -reveal_type(u8 + AR) # E: Any +reveal_type(u8 + AR_f) # E: Any reveal_type(i8 + i8) # E: {int64} reveal_type(u8 + i8) # E: Union[numpy.signedinteger[Any], {float64}] @@ -247,7 +383,7 @@ reveal_type(b + i8) # E: {int64} reveal_type(c + i8) # E: {complex128} reveal_type(f + i8) # E: {float64} reveal_type(i + i8) # E: {int64} -reveal_type(AR + i8) # E: Any +reveal_type(AR_f + i8) # E: Any reveal_type(u8 + u8) # E: {uint64} reveal_type(i4 + u8) # E: Union[numpy.signedinteger[Any], {float64}] @@ -257,14 +393,14 @@ reveal_type(b + u8) # E: {uint64} reveal_type(c + u8) # E: {complex128} reveal_type(f + u8) # E: {float64} reveal_type(i + u8) # E: Union[numpy.signedinteger[Any], {float64}] -reveal_type(AR + u8) # E: Any +reveal_type(AR_f + u8) # E: Any reveal_type(i4 + i8) # E: {int64} reveal_type(i4 + i4) # E: {int32} reveal_type(i4 + i) # E: {int_} reveal_type(i4 + b_) # E: {int32} reveal_type(i4 + b) # E: {int32} -reveal_type(i4 + AR) # E: Any +reveal_type(i4 + AR_f) # E: Any reveal_type(u4 + i8) # E: Union[numpy.signedinteger[Any], {float64}] reveal_type(u4 + i4) # E: Union[numpy.signedinteger[Any], {float64}] @@ -273,14 +409,14 @@ reveal_type(u4 + u4) # E: {uint32} reveal_type(u4 + i) # E: Union[numpy.signedinteger[Any], {float64}] reveal_type(u4 + b_) # E: {uint32} reveal_type(u4 + b) # E: {uint32} -reveal_type(u4 + AR) # E: Any +reveal_type(u4 + AR_f) # E: Any reveal_type(i8 + i4) # E: {int64} reveal_type(i4 + i4) # E: {int32} reveal_type(i + i4) # E: {int_} reveal_type(b_ + i4) # E: {int32} reveal_type(b + i4) # E: {int32} -reveal_type(AR + i4) # E: Any +reveal_type(AR_f + i4) # E: Any reveal_type(i8 + u4) # E: Union[numpy.signedinteger[Any], {float64}] reveal_type(i4 + u4) # E: Union[numpy.signedinteger[Any], {float64}] @@ -289,4 +425,4 @@ reveal_type(u4 + u4) # E: {uint32} reveal_type(b_ + u4) # E: {uint32} reveal_type(b + u4) # E: {uint32} reveal_type(i + u4) # E: Union[numpy.signedinteger[Any], {float64}] -reveal_type(AR + u4) # E: Any +reveal_type(AR_f + u4) # E: Any diff --git a/numpy/typing/tests/data/reveal/comparisons.py b/numpy/typing/tests/data/reveal/comparisons.py index 507f713c7..5053a9e82 100644 --- a/numpy/typing/tests/data/reveal/comparisons.py +++ b/numpy/typing/tests/data/reveal/comparisons.py @@ -33,8 +33,13 @@ reveal_type(td > td) # E: numpy.bool_ reveal_type(td > i) # E: numpy.bool_ reveal_type(td > i4) # E: numpy.bool_ reveal_type(td > i8) # E: numpy.bool_ -reveal_type(td > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(td > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] + +reveal_type(td > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(td > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(AR > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(AR > td) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > td) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] # boolean @@ -51,8 +56,8 @@ reveal_type(b_ > f4) # E: numpy.bool_ reveal_type(b_ > c) # E: numpy.bool_ reveal_type(b_ > c16) # E: numpy.bool_ reveal_type(b_ > c8) # E: numpy.bool_ -reveal_type(b_ > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(b_ > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(b_ > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(b_ > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] # Complex @@ -67,8 +72,8 @@ reveal_type(c16 > b) # E: numpy.bool_ reveal_type(c16 > c) # E: numpy.bool_ reveal_type(c16 > f) # E: numpy.bool_ reveal_type(c16 > i) # E: numpy.bool_ -reveal_type(c16 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(c16 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(c16 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(c16 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(c16 > c16) # E: numpy.bool_ reveal_type(f8 > c16) # E: numpy.bool_ @@ -81,8 +86,8 @@ reveal_type(b > c16) # E: numpy.bool_ reveal_type(c > c16) # E: numpy.bool_ reveal_type(f > c16) # E: numpy.bool_ reveal_type(i > c16) # E: numpy.bool_ -reveal_type(AR > c16) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > c16) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > c16) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > c16) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(c8 > c16) # E: numpy.bool_ reveal_type(c8 > f8) # E: numpy.bool_ @@ -95,8 +100,8 @@ reveal_type(c8 > b) # E: numpy.bool_ reveal_type(c8 > c) # E: numpy.bool_ reveal_type(c8 > f) # E: numpy.bool_ reveal_type(c8 > i) # E: numpy.bool_ -reveal_type(c8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(c8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(c8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(c8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(c16 > c8) # E: numpy.bool_ reveal_type(f8 > c8) # E: numpy.bool_ @@ -109,8 +114,8 @@ reveal_type(b > c8) # E: numpy.bool_ reveal_type(c > c8) # E: numpy.bool_ reveal_type(f > c8) # E: numpy.bool_ reveal_type(i > c8) # E: numpy.bool_ -reveal_type(AR > c8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > c8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > c8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > c8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] # Float @@ -123,8 +128,8 @@ reveal_type(f8 > b) # E: numpy.bool_ reveal_type(f8 > c) # E: numpy.bool_ reveal_type(f8 > f) # E: numpy.bool_ reveal_type(f8 > i) # E: numpy.bool_ -reveal_type(f8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(f8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(f8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(f8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(f8 > f8) # E: numpy.bool_ reveal_type(i8 > f8) # E: numpy.bool_ @@ -135,8 +140,8 @@ reveal_type(b > f8) # E: numpy.bool_ reveal_type(c > f8) # E: numpy.bool_ reveal_type(f > f8) # E: numpy.bool_ reveal_type(i > f8) # E: numpy.bool_ -reveal_type(AR > f8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > f8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > f8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > f8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(f4 > f8) # E: numpy.bool_ reveal_type(f4 > i8) # E: numpy.bool_ @@ -147,8 +152,8 @@ reveal_type(f4 > b) # E: numpy.bool_ reveal_type(f4 > c) # E: numpy.bool_ reveal_type(f4 > f) # E: numpy.bool_ reveal_type(f4 > i) # E: numpy.bool_ -reveal_type(f4 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(f4 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(f4 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(f4 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(f8 > f4) # E: numpy.bool_ reveal_type(i8 > f4) # E: numpy.bool_ @@ -159,8 +164,8 @@ reveal_type(b > f4) # E: numpy.bool_ reveal_type(c > f4) # E: numpy.bool_ reveal_type(f > f4) # E: numpy.bool_ reveal_type(i > f4) # E: numpy.bool_ -reveal_type(AR > f4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > f4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > f4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > f4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] # Int @@ -173,8 +178,8 @@ reveal_type(i8 > b) # E: numpy.bool_ reveal_type(i8 > c) # E: numpy.bool_ reveal_type(i8 > f) # E: numpy.bool_ reveal_type(i8 > i) # E: numpy.bool_ -reveal_type(i8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(i8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(i8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(i8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(u8 > u8) # E: numpy.bool_ reveal_type(u8 > i4) # E: numpy.bool_ @@ -184,8 +189,8 @@ reveal_type(u8 > b) # E: numpy.bool_ reveal_type(u8 > c) # E: numpy.bool_ reveal_type(u8 > f) # E: numpy.bool_ reveal_type(u8 > i) # E: numpy.bool_ -reveal_type(u8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(u8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(u8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(u8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(i8 > i8) # E: numpy.bool_ reveal_type(u8 > i8) # E: numpy.bool_ @@ -196,8 +201,8 @@ reveal_type(b > i8) # E: numpy.bool_ reveal_type(c > i8) # E: numpy.bool_ reveal_type(f > i8) # E: numpy.bool_ reveal_type(i > i8) # E: numpy.bool_ -reveal_type(AR > i8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > i8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > i8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > i8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(u8 > u8) # E: numpy.bool_ reveal_type(i4 > u8) # E: numpy.bool_ @@ -207,16 +212,16 @@ reveal_type(b > u8) # E: numpy.bool_ reveal_type(c > u8) # E: numpy.bool_ reveal_type(f > u8) # E: numpy.bool_ reveal_type(i > u8) # E: numpy.bool_ -reveal_type(AR > u8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > u8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > u8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > u8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(i4 > i8) # E: numpy.bool_ reveal_type(i4 > i4) # E: numpy.bool_ reveal_type(i4 > i) # E: numpy.bool_ reveal_type(i4 > b_) # E: numpy.bool_ reveal_type(i4 > b) # E: numpy.bool_ -reveal_type(i4 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(i4 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(i4 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(i4 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(u4 > i8) # E: numpy.bool_ reveal_type(u4 > i4) # E: numpy.bool_ @@ -225,16 +230,16 @@ reveal_type(u4 > u4) # E: numpy.bool_ reveal_type(u4 > i) # E: numpy.bool_ reveal_type(u4 > b_) # E: numpy.bool_ reveal_type(u4 > b) # E: numpy.bool_ -reveal_type(u4 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(u4 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(u4 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(u4 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(i8 > i4) # E: numpy.bool_ reveal_type(i4 > i4) # E: numpy.bool_ reveal_type(i > i4) # E: numpy.bool_ reveal_type(b_ > i4) # E: numpy.bool_ reveal_type(b > i4) # E: numpy.bool_ -reveal_type(AR > i4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > i4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > i4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > i4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] reveal_type(i8 > u4) # E: numpy.bool_ reveal_type(i4 > u4) # E: numpy.bool_ @@ -243,5 +248,5 @@ reveal_type(u4 > u4) # E: numpy.bool_ reveal_type(b_ > u4) # E: numpy.bool_ reveal_type(b > u4) # E: numpy.bool_ reveal_type(i > u4) # E: numpy.bool_ -reveal_type(AR > u4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] -reveal_type(SEQ > u4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_] +reveal_type(AR > u4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] +reveal_type(SEQ > u4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]] diff --git a/numpy/typing/tests/data/reveal/mod.py b/numpy/typing/tests/data/reveal/mod.py index 989ef99fd..4a913f11a 100644 --- a/numpy/typing/tests/data/reveal/mod.py +++ b/numpy/typing/tests/data/reveal/mod.py @@ -1,3 +1,4 @@ +from typing import Any import numpy as np f8 = np.float64() @@ -15,21 +16,18 @@ b = bool() f = float() i = int() -AR = np.array([1], dtype=np.bool_) -AR.setflags(write=False) - -AR2 = np.array([1], dtype=np.timedelta64) -AR2.setflags(write=False) +AR_b: np.ndarray[Any, np.dtype[np.bool_]] +AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] # Time structures reveal_type(td % td) # E: numpy.timedelta64 -reveal_type(AR2 % td) # E: Any -reveal_type(td % AR2) # E: Any +reveal_type(AR_m % td) # E: Any +reveal_type(td % AR_m) # E: Any reveal_type(divmod(td, td)) # E: Tuple[{int64}, numpy.timedelta64] -reveal_type(divmod(AR2, td)) # E: Tuple[Any, Any] -reveal_type(divmod(td, AR2)) # E: Tuple[Any, Any] +reveal_type(divmod(AR_m, td)) # E: Union[Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.timedelta64], Tuple[numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[numpy.typing._64Bit]]], numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]]] +reveal_type(divmod(td, AR_m)) # E: Union[Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.timedelta64], Tuple[numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[numpy.typing._64Bit]]], numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]]]] # Bool @@ -40,7 +38,7 @@ reveal_type(b_ % b_) # E: {int8} reveal_type(b_ % i8) # E: {int64} reveal_type(b_ % u8) # E: {uint64} reveal_type(b_ % f8) # E: {float64} -reveal_type(b_ % AR) # E: Any +reveal_type(b_ % AR_b) # E: Union[{int8}, numpy.ndarray[Any, numpy.dtype[{int8}]]] reveal_type(divmod(b_, b)) # E: Tuple[{int8}, {int8}] reveal_type(divmod(b_, i)) # E: Tuple[{int_}, {int_}] @@ -49,7 +47,7 @@ reveal_type(divmod(b_, b_)) # E: Tuple[{int8}, {int8}] reveal_type(divmod(b_, i8)) # E: Tuple[{int64}, {int64}] reveal_type(divmod(b_, u8)) # E: Tuple[{uint64}, {uint64}] reveal_type(divmod(b_, f8)) # E: Tuple[{float64}, {float64}] -reveal_type(divmod(b_, AR)) # E: Tuple[Any, Any] +reveal_type(divmod(b_, AR_b)) # E: Tuple[Union[{int8}, numpy.ndarray[Any, numpy.dtype[{int8}]]], Union[{int8}, numpy.ndarray[Any, numpy.dtype[{int8}]]]] reveal_type(b % b_) # E: {int8} reveal_type(i % b_) # E: {int_} @@ -58,7 +56,7 @@ reveal_type(b_ % b_) # E: {int8} reveal_type(i8 % b_) # E: {int64} reveal_type(u8 % b_) # E: {uint64} reveal_type(f8 % b_) # E: {float64} -reveal_type(AR % b_) # E: Any +reveal_type(AR_b % b_) # E: Union[{int8}, numpy.ndarray[Any, numpy.dtype[{int8}]]] reveal_type(divmod(b, b_)) # E: Tuple[{int8}, {int8}] reveal_type(divmod(i, b_)) # E: Tuple[{int_}, {int_}] @@ -67,7 +65,7 @@ reveal_type(divmod(b_, b_)) # E: Tuple[{int8}, {int8}] reveal_type(divmod(i8, b_)) # E: Tuple[{int64}, {int64}] reveal_type(divmod(u8, b_)) # E: Tuple[{uint64}, {uint64}] reveal_type(divmod(f8, b_)) # E: Tuple[{float64}, {float64}] -reveal_type(divmod(AR, b_)) # E: Tuple[Any, Any] +reveal_type(divmod(AR_b, b_)) # E: Tuple[Union[{int8}, numpy.ndarray[Any, numpy.dtype[{int8}]]], Union[{int8}, numpy.ndarray[Any, numpy.dtype[{int8}]]]] # int @@ -80,7 +78,7 @@ reveal_type(i4 % i8) # E: {int64} reveal_type(i4 % f8) # E: {float64} reveal_type(i4 % i4) # E: {int32} reveal_type(i4 % f4) # E: {float32} -reveal_type(i8 % AR) # E: Any +reveal_type(i8 % AR_b) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] reveal_type(divmod(i8, b)) # E: Tuple[{int64}, {int64}] reveal_type(divmod(i8, i)) # E: Tuple[{int64}, {int64}] @@ -91,7 +89,7 @@ reveal_type(divmod(i8, i4)) # E: Tuple[{int64}, {int64}] reveal_type(divmod(i8, f4)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(i4, i4)) # E: Tuple[{int32}, {int32}] reveal_type(divmod(i4, f4)) # E: Tuple[{float32}, {float32}] -reveal_type(divmod(i8, AR)) # E: Tuple[Any, Any] +reveal_type(divmod(i8, AR_b)) # E: Tuple[Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]], Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]]] reveal_type(b % i8) # E: {int64} reveal_type(i % i8) # E: {int64} @@ -102,7 +100,7 @@ reveal_type(i8 % i4) # E: {int64} reveal_type(f8 % i4) # E: {float64} reveal_type(i4 % i4) # E: {int32} reveal_type(f4 % i4) # E: {float32} -reveal_type(AR % i8) # E: Any +reveal_type(AR_b % i8) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]] reveal_type(divmod(b, i8)) # E: Tuple[{int64}, {int64}] reveal_type(divmod(i, i8)) # E: Tuple[{int64}, {int64}] @@ -113,7 +111,7 @@ reveal_type(divmod(i4, i8)) # E: Tuple[{int64}, {int64}] reveal_type(divmod(f4, i8)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(i4, i4)) # E: Tuple[{int32}, {int32}] reveal_type(divmod(f4, i4)) # E: Tuple[{float32}, {float32}] -reveal_type(divmod(AR, i8)) # E: Tuple[Any, Any] +reveal_type(divmod(AR_b, i8)) # E: Tuple[Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]], Union[numpy.signedinteger[Any], numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]]] # float @@ -122,7 +120,7 @@ reveal_type(f8 % i) # E: {float64} reveal_type(f8 % f) # E: {float64} reveal_type(i8 % f4) # E: {float64} reveal_type(f4 % f4) # E: {float32} -reveal_type(f8 % AR) # E: Any +reveal_type(f8 % AR_b) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] reveal_type(divmod(f8, b)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f8, i)) # E: Tuple[{float64}, {float64}] @@ -130,7 +128,7 @@ reveal_type(divmod(f8, f)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f8, f8)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f8, f4)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f4, f4)) # E: Tuple[{float32}, {float32}] -reveal_type(divmod(f8, AR)) # E: Tuple[Any, Any] +reveal_type(divmod(f8, AR_b)) # E: Tuple[Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]], Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]]] reveal_type(b % f8) # E: {float64} reveal_type(i % f8) # E: {float64} @@ -138,7 +136,7 @@ reveal_type(f % f8) # E: {float64} reveal_type(f8 % f8) # E: {float64} reveal_type(f8 % f8) # E: {float64} reveal_type(f4 % f4) # E: {float32} -reveal_type(AR % f8) # E: Any +reveal_type(AR_b % f8) # E: Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]] reveal_type(divmod(b, f8)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(i, f8)) # E: Tuple[{float64}, {float64}] @@ -146,4 +144,4 @@ reveal_type(divmod(f, f8)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f8, f8)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f4, f8)) # E: Tuple[{float64}, {float64}] reveal_type(divmod(f4, f4)) # E: Tuple[{float32}, {float32}] -reveal_type(divmod(AR, f8)) # E: Tuple[Any, Any] +reveal_type(divmod(AR_b, f8)) # E: Tuple[Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]], Union[numpy.floating[Any], numpy.ndarray[Any, numpy.dtype[numpy.floating[Any]]]]] diff --git a/numpy/typing/tests/data/reveal/modules.py b/numpy/typing/tests/data/reveal/modules.py index 406463152..75513f2b0 100644 --- a/numpy/typing/tests/data/reveal/modules.py +++ b/numpy/typing/tests/data/reveal/modules.py @@ -1,4 +1,5 @@ import numpy as np +from numpy import f2py reveal_type(np) # E: ModuleType @@ -18,3 +19,18 @@ reveal_type(np.version) # E: ModuleType # TODO: Remove when annotations have been added to `np.testing.assert_equal` reveal_type(np.testing.assert_equal) # E: Any + +reveal_type(np.__path__) # E: list[builtins.str] +reveal_type(np.__version__) # E: str +reveal_type(np.__git_version__) # E: str + +reveal_type(np.__all__) # E: list[builtins.str] +reveal_type(np.char.__all__) # E: list[builtins.str] +reveal_type(np.ctypeslib.__all__) # E: list[builtins.str] +reveal_type(np.emath.__all__) # E: list[builtins.str] +reveal_type(np.lib.__all__) # E: list[builtins.str] +reveal_type(np.ma.__all__) # E: list[builtins.str] +reveal_type(np.random.__all__) # E: list[builtins.str] +reveal_type(np.rec.__all__) # E: list[builtins.str] +reveal_type(np.testing.__all__) # E: list[builtins.str] +reveal_type(f2py.__all__) # E: list[builtins.str] diff --git a/numpy/typing/tests/data/reveal/nbit_base_example.py b/numpy/typing/tests/data/reveal/nbit_base_example.py index 99fb71560..d34f6f69a 100644 --- a/numpy/typing/tests/data/reveal/nbit_base_example.py +++ b/numpy/typing/tests/data/reveal/nbit_base_example.py @@ -2,9 +2,10 @@ from typing import TypeVar, Union import numpy as np import numpy.typing as npt -T = TypeVar("T", bound=npt.NBitBase) +T1 = TypeVar("T1", bound=npt.NBitBase) +T2 = TypeVar("T2", bound=npt.NBitBase) -def add(a: np.floating[T], b: np.integer[T]) -> np.floating[T]: +def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[Union[T1, T2]]: return a + b i8: np.int64 diff --git a/numpy/typing/tests/data/reveal/scalars.py b/numpy/typing/tests/data/reveal/scalars.py index faa7ac3d2..fa94aa49b 100644 --- a/numpy/typing/tests/data/reveal/scalars.py +++ b/numpy/typing/tests/data/reveal/scalars.py @@ -30,6 +30,11 @@ reveal_type(np.str0('foo')) # E: numpy.str_ # Aliases reveal_type(np.unicode_()) # E: numpy.str_ reveal_type(np.str0()) # E: numpy.str_ +reveal_type(np.bool8()) # E: numpy.bool_ +reveal_type(np.bytes0()) # E: numpy.bytes_ +reveal_type(np.string_()) # E: numpy.bytes_ +reveal_type(np.object0()) # E: numpy.object_ +reveal_type(np.void0(0)) # E: numpy.void reveal_type(np.byte()) # E: {byte} reveal_type(np.short()) # E: {short} diff --git a/numpy/typing/tests/test_typing.py b/numpy/typing/tests/test_typing.py index 18520a757..324312a92 100644 --- a/numpy/typing/tests/test_typing.py +++ b/numpy/typing/tests/test_typing.py @@ -25,15 +25,48 @@ REVEAL_DIR = os.path.join(DATA_DIR, "reveal") MYPY_INI = os.path.join(DATA_DIR, "mypy.ini") CACHE_DIR = os.path.join(DATA_DIR, ".mypy_cache") +#: A dictionary with file names as keys and lists of the mypy stdout as values. +#: To-be populated by `run_mypy`. +OUTPUT_MYPY: Dict[str, List[str]] = {} + + +def _key_func(key: str) -> str: + """Split at the first occurance of the ``:`` character. + + Windows drive-letters (*e.g.* ``C:``) are ignored herein. + """ + drive, tail = os.path.splitdrive(key) + return os.path.join(drive, tail.split(":", 1)[0]) + @pytest.mark.slow @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed") -@pytest.fixture(scope="session", autouse=True) -def clear_cache() -> None: - """Clears the mypy cache before running any of the typing tests.""" +@pytest.fixture(scope="module", autouse=True) +def run_mypy() -> None: + """Clears the cache and run mypy before running any of the typing tests. + + The mypy results are cached in `OUTPUT_MYPY` for further use. + + """ if os.path.isdir(CACHE_DIR): shutil.rmtree(CACHE_DIR) + for directory in (PASS_DIR, REVEAL_DIR, FAIL_DIR): + # Run mypy + stdout, stderr, _ = api.run([ + "--config-file", + MYPY_INI, + "--cache-dir", + CACHE_DIR, + directory, + ]) + assert not stderr, directory + stdout = stdout.replace('*', '') + + # Parse the output + iterator = itertools.groupby(stdout.split("\n"), key=_key_func) + OUTPUT_MYPY.update((k, list(v)) for k, v in iterator if k) + def get_test_cases(directory): for root, _, files in os.walk(directory): @@ -54,15 +87,9 @@ def get_test_cases(directory): @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed") @pytest.mark.parametrize("path", get_test_cases(PASS_DIR)) def test_success(path): - stdout, stderr, exitcode = api.run([ - "--config-file", - MYPY_INI, - "--cache-dir", - CACHE_DIR, - path, - ]) - assert exitcode == 0, stdout - assert re.match(r"Success: no issues found in \d+ source files?", stdout.strip()) + # Alias `OUTPUT_MYPY` so that it appears in the local namespace + output_mypy = OUTPUT_MYPY + assert path not in output_mypy @pytest.mark.slow @@ -71,29 +98,14 @@ def test_success(path): def test_fail(path): __tracebackhide__ = True - stdout, stderr, exitcode = api.run([ - "--config-file", - MYPY_INI, - "--cache-dir", - CACHE_DIR, - path, - ]) - assert exitcode != 0 - with open(path) as fin: lines = fin.readlines() errors = defaultdict(lambda: "") - error_lines = stdout.rstrip("\n").split("\n") - assert re.match( - r"Found \d+ errors? in \d+ files? \(checked \d+ source files?\)", - error_lines[-1].strip(), - ) - for error_line in error_lines[:-1]: - error_line = error_line.strip() - if not error_line: - continue + output_mypy = OUTPUT_MYPY + assert path in output_mypy + for error_line in output_mypy[path]: match = re.match( r"^.+\.py:(?P<lineno>\d+): (error|note): .+$", error_line, @@ -215,23 +227,12 @@ def _parse_reveals(file: IO[str]) -> List[str]: def test_reveal(path): __tracebackhide__ = True - stdout, stderr, exitcode = api.run([ - "--config-file", - MYPY_INI, - "--cache-dir", - CACHE_DIR, - path, - ]) - with open(path) as fin: lines = _parse_reveals(fin) - stdout_list = stdout.replace('*', '').split("\n") - for error_line in stdout_list: - error_line = error_line.strip() - if not error_line: - continue - + output_mypy = OUTPUT_MYPY + assert path in output_mypy + for error_line in output_mypy[path]: match = re.match( r"^.+\.py:(?P<lineno>\d+): note: .+$", error_line, |
