From 2a1c59cd0cddee45a0746e77a28b38e76dd6838d Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sat, 18 Apr 2020 16:13:15 +0200 Subject: [PATCH 1/9] Implemented Warning and Exception annotations See https://github.com/numpy/numpy-stubs/issues/54. Added annotations and tests for: * np.warnings * np.ModuleDeprecationWarning * np.VisibleDeprecationWarning * np.ComplexWarning * np.RankWarning * np.TooHardError * np.AxisError --- numpy-stubs/__init__.pyi | 15 +++++++++++++++ tests/pass/warnings_and_errors.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/pass/warnings_and_errors.py diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 960e6e5..5bc41b9 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -1,6 +1,7 @@ import builtins import sys import datetime as dt +import warnings as _warnings from numpy.core._internal import _ctypes from typing import ( @@ -778,3 +779,17 @@ trunc: ufunc # TODO(shoyer): remove when the full numpy namespace is defined def __getattr__(name: str) -> Any: ... + +# Warnings +warnings = _warnings +class ModuleDeprecationWarning(DeprecationWarning): ... +class VisibleDeprecationWarning(UserWarning): ... +class ComplexWarning(RuntimeWarning): ... +class RankWarning(UserWarning): ... + +# Errors +class TooHardError(RuntimeError): ... +class AxisError(ValueError, IndexError): + # Note that all parameters for __init__ (except self) can technically be Any. + # So it's a question here whether or not we should allow what's possible or what's intended + def __init__(self, axis: int, ndim: Optional[int] = ..., msg_prefix: Optional[str] = ...) -> None: ... diff --git a/tests/pass/warnings_and_errors.py b/tests/pass/warnings_and_errors.py new file mode 100644 index 0000000..dfc7617 --- /dev/null +++ b/tests/pass/warnings_and_errors.py @@ -0,0 +1,18 @@ +import types +from typing import Type + +import numpy as np + +warnings: types.ModuleType = np.warnings +ModuleDeprecationWarning: Type[DeprecationWarning] = np.ModuleDeprecationWarning +VisibleDeprecationWarning: Type[UserWarning] = np.VisibleDeprecationWarning +ComplexWarning: Type[RuntimeWarning] = np.ComplexWarning +RankWarning: Type[UserWarning] = np.RankWarning + +TooHardError: Type[RuntimeError] = np.TooHardError +AxisError1: Type[ValueError] = np.AxisError +AxisError2: Type[IndexError] = np.AxisError + +np.AxisError(1) +np.AxisError(1, ndim=2) +np.AxisError(1, ndim=2, msg_prefix='error') From ba767a03c8ed4532d2f80cc1997c0a33576272e4 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sat, 18 Apr 2020 16:22:08 +0200 Subject: [PATCH 2/9] Annotate using Python 2 compatible type comments --- tests/pass/warnings_and_errors.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/pass/warnings_and_errors.py b/tests/pass/warnings_and_errors.py index dfc7617..2774f5f 100644 --- a/tests/pass/warnings_and_errors.py +++ b/tests/pass/warnings_and_errors.py @@ -3,15 +3,15 @@ import numpy as np -warnings: types.ModuleType = np.warnings -ModuleDeprecationWarning: Type[DeprecationWarning] = np.ModuleDeprecationWarning -VisibleDeprecationWarning: Type[UserWarning] = np.VisibleDeprecationWarning -ComplexWarning: Type[RuntimeWarning] = np.ComplexWarning -RankWarning: Type[UserWarning] = np.RankWarning +warnings = np.warnings # type: types.ModuleType +ModuleDeprecationWarning = np.ModuleDeprecationWarning # type: Type[DeprecationWarning] +VisibleDeprecationWarning = np.VisibleDeprecationWarning # type: Type[UserWarning] +ComplexWarning = np.ComplexWarning # type: Type[RuntimeWarning] +RankWarning = np.RankWarning # type: Type[UserWarning] -TooHardError: Type[RuntimeError] = np.TooHardError -AxisError1: Type[ValueError] = np.AxisError -AxisError2: Type[IndexError] = np.AxisError +TooHardError = np.TooHardError # type: Type[RuntimeError] +AxisError1 = np.AxisError # type: Type[ValueError] +AxisError2 = np.AxisError # type: Type[IndexError] np.AxisError(1) np.AxisError(1, ndim=2) From ac0ce25616ee4e41dd71cab959f1f67f94af5ead Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sat, 18 Apr 2020 21:44:34 +0200 Subject: [PATCH 3/9] Addressed comments from https://github.com/numpy/numpy-stubs/pull/57 * Removed ``warnings`` (https://github.com/numpy/numpy-stubs/pull/57#discussion_r410731135) * Deleted a now redundant comment (https://github.com/numpy/numpy-stubs/pull/57#discussion_r410732818) * Created and/or moved a number of tests to fail/ and reveal/ (https://github.com/numpy/numpy-stubs/pull/57#discussion_r410731679 and https://github.com/numpy/numpy-stubs/pull/57#discussion_r410731884) * Formatted the main __init__.pyi file with black (https://github.com/numpy/numpy-stubs/pull/57#pullrequestreview-395937631) --- numpy-stubs/__init__.pyi | 11 +++++------ tests/fail/warnings_and_errors.py | 5 +++++ tests/pass/warnings_and_errors.py | 15 ++------------- tests/reveal/warnings_and_errors.py | 10 ++++++++++ 4 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 tests/fail/warnings_and_errors.py create mode 100644 tests/reveal/warnings_and_errors.py diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 5bc41b9..9151ad1 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -1,7 +1,6 @@ import builtins import sys import datetime as dt -import warnings as _warnings from numpy.core._internal import _ctypes from typing import ( @@ -104,7 +103,7 @@ class dtype: def descr(self) -> List[Union[Tuple[str, str], Tuple[str, str, _Shape]]]: ... @property def fields( - self + self, ) -> Optional[Mapping[str, Union[Tuple[dtype, int], Tuple[dtype, int, Any]]]]: ... @property def flags(self) -> int: ... @@ -781,7 +780,6 @@ trunc: ufunc def __getattr__(name: str) -> Any: ... # Warnings -warnings = _warnings class ModuleDeprecationWarning(DeprecationWarning): ... class VisibleDeprecationWarning(UserWarning): ... class ComplexWarning(RuntimeWarning): ... @@ -789,7 +787,8 @@ class RankWarning(UserWarning): ... # Errors class TooHardError(RuntimeError): ... + class AxisError(ValueError, IndexError): - # Note that all parameters for __init__ (except self) can technically be Any. - # So it's a question here whether or not we should allow what's possible or what's intended - def __init__(self, axis: int, ndim: Optional[int] = ..., msg_prefix: Optional[str] = ...) -> None: ... + def __init__( + self, axis: int, ndim: Optional[int] = ..., msg_prefix: Optional[str] = ... + ) -> None: ... diff --git a/tests/fail/warnings_and_errors.py b/tests/fail/warnings_and_errors.py new file mode 100644 index 0000000..9f8b1db --- /dev/null +++ b/tests/fail/warnings_and_errors.py @@ -0,0 +1,5 @@ +import numpy as np + +np.AxisError(1.0) # E: Argument 1 to "AxisError" has incompatible type +np.AxisError(1, ndim=2.0) # E: Argument "ndim" to "AxisError" has incompatible type +np.AxisError(2, msg_prefix=404) # E: Argument "msg_prefix" to "AxisError" has incompatible type diff --git a/tests/pass/warnings_and_errors.py b/tests/pass/warnings_and_errors.py index 2774f5f..e69e1f1 100644 --- a/tests/pass/warnings_and_errors.py +++ b/tests/pass/warnings_and_errors.py @@ -1,18 +1,7 @@ -import types -from typing import Type - import numpy as np -warnings = np.warnings # type: types.ModuleType -ModuleDeprecationWarning = np.ModuleDeprecationWarning # type: Type[DeprecationWarning] -VisibleDeprecationWarning = np.VisibleDeprecationWarning # type: Type[UserWarning] -ComplexWarning = np.ComplexWarning # type: Type[RuntimeWarning] -RankWarning = np.RankWarning # type: Type[UserWarning] - -TooHardError = np.TooHardError # type: Type[RuntimeError] -AxisError1 = np.AxisError # type: Type[ValueError] -AxisError2 = np.AxisError # type: Type[IndexError] - np.AxisError(1) np.AxisError(1, ndim=2) +np.AxisError(1, ndim=None) np.AxisError(1, ndim=2, msg_prefix='error') +np.AxisError(1, ndim=2, msg_prefix=None) diff --git a/tests/reveal/warnings_and_errors.py b/tests/reveal/warnings_and_errors.py new file mode 100644 index 0000000..c428deb --- /dev/null +++ b/tests/reveal/warnings_and_errors.py @@ -0,0 +1,10 @@ +from typing import Type + +import numpy as np + +reveal_type(np.ModuleDeprecationWarning()) # E: numpy.ModuleDeprecationWarning +reveal_type(np.VisibleDeprecationWarning()) # E: numpy.VisibleDeprecationWarning +reveal_type(np.ComplexWarning()) # E: numpy.ComplexWarning +reveal_type(np.RankWarning()) # E: numpy.RankWarning +reveal_type(np.TooHardError()) # E: numpy.TooHardError +reveal_type(np.AxisError(1)) # E: numpy.AxisError From 80e3976fc0c1ebe2fe3bc1357633deb406168712 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sun, 19 Apr 2020 01:07:50 +0200 Subject: [PATCH 4/9] Added np.all() and np.any() --- numpy-stubs/__init__.pyi | 34 ++++++++++++++++++++++++++++++++++ tests/reveal/any_all.py | 22 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/reveal/any_all.py diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 9151ad1..661b9cf 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -35,6 +35,11 @@ if sys.version_info[0] < 3: else: from typing import SupportsBytes +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + _Shape = Tuple[int, ...] # Anything that can be coerced to a shape tuple @@ -792,3 +797,32 @@ class AxisError(ValueError, IndexError): def __init__( self, axis: int, ndim: Optional[int] = ..., msg_prefix: Optional[str] = ... ) -> None: ... + +@overload +def all( + a: _ArrayLike, + axis: None = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., +) -> bool: ... +@overload +def all( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> Union[bool, ndarray]: ... +@overload +def any( + a: _ArrayLike, + axis: None = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., +) -> bool: ... +@overload +def any( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> Union[bool, ndarray]: ... diff --git a/tests/reveal/any_all.py b/tests/reveal/any_all.py new file mode 100644 index 0000000..16e946c --- /dev/null +++ b/tests/reveal/any_all.py @@ -0,0 +1,22 @@ +import numpy as np + +A = np.array([True]) +A.setflags(write=False) + +reveal_type(np.all(A)) # E: builtins.bool +reveal_type(np.all(A, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.all(A, keepdims=False)) # E: builtins.bool +reveal_type(np.all(A, axis=0, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.all(A, axis=0, keepdims=False)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.all(A, keepdims=True, axis=0)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.all(A, keepdims=False, axis=0)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.all(A, axis=0)) # E: Union[builtins.bool, numpy.ndarray] + +reveal_type(np.any(A)) # E: builtins.bool +reveal_type(np.any(A, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.any(A, keepdims=False)) # E: builtins.bool +reveal_type(np.any(A, axis=0, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.any(A, axis=0, keepdims=False)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.any(A, keepdims=True, axis=0)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.any(A, keepdims=False, axis=0)) # E: Union[builtins.bool, numpy.ndarray] +reveal_type(np.any(A, axis=0)) # E: Union[builtins.bool, numpy.ndarray] From 7404d1a3e7f2250993053a7823ec4ca2b6dc4ebe Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sun, 19 Apr 2020 16:57:46 +0200 Subject: [PATCH 5/9] Implemented type annotations for the np.core.fromnumeric module --- numpy-stubs/__init__.pyi | 279 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 275 insertions(+), 4 deletions(-) diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 661b9cf..c4c6a3c 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -798,31 +798,302 @@ class AxisError(ValueError, IndexError): self, axis: int, ndim: Optional[int] = ..., msg_prefix: Optional[str] = ... ) -> None: ... +# Functions from np.core.fromnumeric +_Mode = Literal["raise", "wrap", "clip"] +_Order = Literal["C", "F", "A"] +_PartitionKind = Literal["introselect"] +_SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"] +_Side = Literal["left", "right"] + +# A placeholder (?) for numerical scalars +_Scalar = TypeVar('_Scalar', bound=Union[int, float, complex, bool, bool_, number]) +_ArrayLikeInt = Union[SupportsInt, Sequence[SupportsInt]] +_ArrayLikeBool = _ArrayLike # TODO: Should be an array-like object consisting of booleans + +def take( + a: _ArrayLike, + indices: _ArrayLikeInt, + axis: Optional[int] = ..., + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> ndarray: ... +def reshape(a: _ArrayLike, newshape: _ShapeLike, order: _Order = ...) -> ndarray: ... +def choose( + a: _ArrayLike, + choices: Sequence[_ArrayLike], + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> ndarray: ... +def repeat( + a: _ArrayLike, repeats: _ArrayLikeInt, axis: Optional[int] = ... +) -> ndarray: ... +def put(a: ndarray, ind: _ArrayLikeInt, v: _ArrayLike, mode: _Mode = ...) -> None: ... +def swapaxes(a: _ArrayLike, axis1: int, axis2: int) -> ndarray: ... +def transpose(a: _ArrayLike, axes: Optional[Sequence[int]] = ...) -> ndarray: ... +def partition( + a: _ArrayLike, + kth: _ArrayLikeInt, + axis: Optional[int] = ..., + kind: _PartitionKind = ..., + order: Union[None, str, Sequence[str]] = ..., +) -> ndarray: ... +def argpartition( + a: _ArrayLike, + kth: _ArrayLikeInt, + axis: Optional[int], + kind: _PartitionKind = ..., + order: Union[None, str, Sequence[str]] = ..., +) -> ndarray: ... +def sort( + a: _ArrayLike, + axis: Optional[int] = ..., + kind: Optional[_SortKind] = ..., + order: Union[None, str, Sequence[str]] = ..., +) -> ndarray: ... +def argsort( + a: _ArrayLike, + axis: Optional[int] = ..., + kind: Optional[_SortKind] = ..., + order: Union[None, str, Sequence[str]] = ..., +) -> ndarray: ... +@overload +def argmax(a, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ... +@overload +def argmax( + a, axis: int = ..., out: Optional[ndarray] = ... +) -> Union[integer, ndarray]: ... +@overload +def argmin(a, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ... +@overload +def argmin( + a, axis: int = ..., out: Optional[ndarray] = ... +) -> Union[integer, ndarray]: ... +def searchsorted( + a: _ArrayLike, + v: _ArrayLike, + side: _Side = ..., + sorter: Optional[_ArrayLikeInt] = ..., +) -> ndarray: ... +def resize(a: _ArrayLike, new_shape: _ShapeLike) -> ndarray: ... +def squeeze(a: _ArrayLike, axis: Optional[_ShapeLike] = ...) -> ndarray: ... +def diagonal( + a: _ArrayLike, offset: int = ..., axis1: int = ..., axis2: int = ... +) -> ndarray: ... +def trace( + a: _ArrayLike, + offset: int = ..., + axis1: int = ..., + axis2: int = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., +) -> Union[number, ndarray]: ... +def ravel(a: _ArrayLike, order: _Order = ...) -> ndarray: ... +def nonzero(a: _ArrayLike) -> Tuple[ndarray, ...]: ... +def shape(a: _ArrayLike) -> _Shape: ... +def compress( + condition: _ArrayLikeBool, + a: _ArrayLike, + axis: Optional[int] = ..., + out: Optional[ndarray] = ..., +) -> ndarray: ... +def clip( + a: _ArrayLike, + a_min: _ArrayLike, + a_max: _ArrayLike, + out: Optional[ndarray] = ..., + **kwargs: Any, +) -> Union[number, ndarray]: ... +@overload +def sum( + a: _ArrayLike, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _Scalar = ..., # TODO: The type should be compatible with *a* + where: _ArrayLikeBool = ..., +) -> number: ... +@overload +def sum( + a: _ArrayLike, + axis: _ShapeLike = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _Scalar = ..., # TODO: The type should be compatible with *a* + where: _ArrayLikeBool = ..., +) -> Union[number, ndarray]: ... @overload def all( a: _ArrayLike, axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., -) -> bool: ... +) -> bool_: ... @overload def all( a: _ArrayLike, axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., -) -> Union[bool, ndarray]: ... +) -> Union[bool_, ndarray]: ... @overload def any( a: _ArrayLike, axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., -) -> bool: ... +) -> bool_: ... @overload def any( a: _ArrayLike, axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., -) -> Union[bool, ndarray]: ... +) -> Union[bool_, ndarray]: ... +@overload +def cumsum( + a: _ArrayLike, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., +) -> number: ... +@overload +def cumsum( + a: _ArrayLike, + axis: int = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., +) -> Union[number, ndarray]: ... +def ptp( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> Union[number, ndarray]: ... +@overload +def amax( + a: _ArrayLike, + axis: None = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., + initial: _Scalar = ..., + where: _ArrayLikeBool = ..., +) -> number: ... +@overload +def amax( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _Scalar = ..., + where: _ArrayLikeBool = ..., +) -> Union[number, ndarray]: ... +@overload +def amin( + a: _ArrayLike, + axis: None = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., + initial: _Scalar = ..., + where: _ArrayLikeBool = ..., +) -> number: ... +@overload +def amin( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _Scalar = ..., + where: _ArrayLikeBool = ..., +) -> Union[number, ndarray]: ... +def alen(a: _ArrayLike) -> int: ... +@overload +def prod( + a: _ArrayLike, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., + initial: _Scalar = ..., + where: _ArrayLikeBool = ..., +) -> number: ... +@overload +def prod( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _Scalar = ..., + where: _ArrayLikeBool = ..., +) -> Union[number, ndarray]: ... +def cumprod( + a: _ArrayLike, + axis: Optional[int] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., +) -> ndarray: ... +def ndim(a: _ArrayLike) -> int: ... +def size(a: _ArrayLike, axis: Optional[int] = ...) -> int: ... +def around( + a: _ArrayLike, decimals: int = ..., out: Optional[ndarray] = ... +) -> ndarray: ... +@overload +def mean( + a: _ArrayLike, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., +) -> number: ... +@overload +def mean( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> Union[number, ndarray]: ... +@overload +def std( + a: _ArrayLike, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + ddof: int = ..., + keepdims: Literal[False] = ..., +) -> number: ... +@overload +def std( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + ddof: int = ..., + keepdims: bool = ..., +) -> Union[number, ndarray]: ... +@overload +def var( + a: _ArrayLike, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + ddof: int = ..., + keepdims: Literal[False] = ..., +) -> number: ... +@overload +def var( + a: _ArrayLike, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + ddof: int = ..., + keepdims: bool = ..., +) -> Union[number, ndarray]: ... + +round_ = around +product = prod +cumproduct = cumprod +sometrue = any +alltrue = all From 8e4ce4ea123b9569014f5bd94ef879511125013f Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sun, 19 Apr 2020 17:10:20 +0200 Subject: [PATCH 6/9] Added typing_extensions as a requirement for python < 3.8 --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 235683e..7f0b346 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,10 @@ def find_stubs(package): version="0.0.1", packages=['numpy-stubs'], # PEP 561 requires these - install_requires=['numpy>=1.14.0'], + install_requires=[ + 'numpy>=1.14.0', + 'typing_extensions; python_version<"3.8"' + ], package_data=find_stubs('numpy-stubs'), zip_safe=False, ) From 7ae41fcc85bf2b245a7cfd0454ba77586fc7416e Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sun, 19 Apr 2020 17:10:37 +0200 Subject: [PATCH 7/9] Renamed the any_all.py to fromnumeric.py --- tests/reveal/any_all.py | 22 ---------------------- tests/reveal/fromnumeric.py | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 tests/reveal/any_all.py create mode 100644 tests/reveal/fromnumeric.py diff --git a/tests/reveal/any_all.py b/tests/reveal/any_all.py deleted file mode 100644 index 16e946c..0000000 --- a/tests/reveal/any_all.py +++ /dev/null @@ -1,22 +0,0 @@ -import numpy as np - -A = np.array([True]) -A.setflags(write=False) - -reveal_type(np.all(A)) # E: builtins.bool -reveal_type(np.all(A, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.all(A, keepdims=False)) # E: builtins.bool -reveal_type(np.all(A, axis=0, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.all(A, axis=0, keepdims=False)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.all(A, keepdims=True, axis=0)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.all(A, keepdims=False, axis=0)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.all(A, axis=0)) # E: Union[builtins.bool, numpy.ndarray] - -reveal_type(np.any(A)) # E: builtins.bool -reveal_type(np.any(A, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.any(A, keepdims=False)) # E: builtins.bool -reveal_type(np.any(A, axis=0, keepdims=True)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.any(A, axis=0, keepdims=False)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.any(A, keepdims=True, axis=0)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.any(A, keepdims=False, axis=0)) # E: Union[builtins.bool, numpy.ndarray] -reveal_type(np.any(A, axis=0)) # E: Union[builtins.bool, numpy.ndarray] diff --git a/tests/reveal/fromnumeric.py b/tests/reveal/fromnumeric.py new file mode 100644 index 0000000..08fb259 --- /dev/null +++ b/tests/reveal/fromnumeric.py @@ -0,0 +1,22 @@ +import numpy as np + +A = np.array([True]) +A.setflags(write=False) + +reveal_type(np.all(A)) # E: numpy.bool_ +reveal_type(np.all(A, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.all(A, keepdims=False)) # E: numpy.bool_ +reveal_type(np.all(A, axis=0, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.all(A, axis=0, keepdims=False)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.all(A, keepdims=True, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.all(A, keepdims=False, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.all(A, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] + +reveal_type(np.any(A)) # E: numpy.bool_ +reveal_type(np.any(A, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.any(A, keepdims=False)) # E: numpy.bool_ +reveal_type(np.any(A, axis=0, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.any(A, axis=0, keepdims=False)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.any(A, keepdims=True, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.any(A, keepdims=False, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] +reveal_type(np.any(A, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] From 6f802db88de558366f7bc1a5fe4ac6bb4acc43cc Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sun, 19 Apr 2020 17:13:51 +0200 Subject: [PATCH 8/9] Run black one more time --- numpy-stubs/__init__.pyi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index c4c6a3c..16bfea0 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -806,9 +806,11 @@ _SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"] _Side = Literal["left", "right"] # A placeholder (?) for numerical scalars -_Scalar = TypeVar('_Scalar', bound=Union[int, float, complex, bool, bool_, number]) +_Scalar = TypeVar("_Scalar", bound=Union[int, float, complex, bool, bool_, number]) _ArrayLikeInt = Union[SupportsInt, Sequence[SupportsInt]] -_ArrayLikeBool = _ArrayLike # TODO: Should be an array-like object consisting of booleans +_ArrayLikeBool = ( + _ArrayLike # TODO: Should be an array-like object consisting of booleans +) def take( a: _ArrayLike, From ea31239f1c523111d39946d6cef834f6898e4333 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Mon, 20 Apr 2020 18:59:00 +0200 Subject: [PATCH 9/9] Added new overloads; wrapped up the reveal tests * Added new overloads to the ``np.core.fromnumeric`` functions. * Added the ``_ArrayOrScalarCommon.__array__()`` method. * Added the ``_ArrayLikeSeq`` Protocol. * Renamed ``_Scalar`` to ``_ScalarNumeric``. * Wrapped up the reveal tests. * Removed ``typing_extenions`` from the dependencies; see https://github.com/numpy/numpy-stubs/pull/63 --- numpy-stubs/__init__.pyi | 324 ++++++++++++++++++++++++++++++------ setup.py | 5 +- tests/reveal/fromnumeric.py | 247 ++++++++++++++++++++++++++- 3 files changed, 514 insertions(+), 62 deletions(-) diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index 16bfea0..5449ff1 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -36,9 +36,9 @@ else: from typing import SupportsBytes if sys.version_info >= (3, 8): - from typing import Literal + from typing import Literal, Protocol else: - from typing_extensions import Literal + from typing_extensions import Literal, Protocol _Shape = Tuple[int, ...] @@ -87,10 +87,39 @@ _DtypeLike = Union[ Tuple[_DtypeLikeNested, _DtypeLikeNested], ] +# Can be used as such `Union[Sequence[T], _ArrayLikeSeq]` as ndarray +# is not a proper Sequence +# TODO: Specify the to-be returned array type once ndarray is a Generic +class _ArrayLikeSeq(Protocol): + shape: Tuple[int, ...] + def __array__(self, dtype: _DtypeLike = ...) -> ndarray: ... + _NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray) _ArrayLike = TypeVar("_ArrayLike") +_Generic = TypeVar("_Generic", bound=generic) +_Number = TypeVar("_Number", bound=number) + +# In principle the SupportsInt, SupportsFloat, etc. protocols +# would be more suited here but they have one significant disadvatange: +# all these methods are also defined available in ndarray, +# which has no guarantee of being scalar-esque (i.e. a 0D array) +_ScalarNumeric = Union[int, float, complex, bool, bool_, number] + +# Any scalar besides object, as the latter may or may not be a scalar +_ScalarAny = Union[_ScalarNumeric, str, bytes, dt.datetime, flexible, datetime64] + +# TODO: Refine the _ArrayLikeSeq type once ndarray is a Generic +_ArrayLikeInt = TypeVar( + "_ArrayLikeInt", + bound=Union[int, integer, Sequence[Union[int, integer]], _ArrayLikeSeq], +) +_ArrayLikeBool = TypeVar( + "_ArrayLikeBool", + bound=Union[bool, bool_, Sequence[Union[bool, bool_]], _ArrayLikeSeq], +) + class dtype: names: Optional[Tuple[str, ...]] def __init__( @@ -214,6 +243,7 @@ class _ArrayOrScalarCommon( def shape(self) -> _Shape: ... @property def strides(self) -> _Shape: ... + def __array__(self, dtype: _DtypeLike = ...) -> ndarray: ... def __int__(self) -> int: ... def __float__(self) -> float: ... def __complex__(self) -> complex: ... @@ -805,24 +835,58 @@ _PartitionKind = Literal["introselect"] _SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"] _Side = Literal["left", "right"] -# A placeholder (?) for numerical scalars -_Scalar = TypeVar("_Scalar", bound=Union[int, float, complex, bool, bool_, number]) -_ArrayLikeInt = Union[SupportsInt, Sequence[SupportsInt]] -_ArrayLikeBool = ( - _ArrayLike # TODO: Should be an array-like object consisting of booleans -) - +# The actual functions +@overload +def take( + a: _Generic, + indices: int, + axis: Optional[int] = ..., + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> _Generic: ... +@overload +def take( + a: _ScalarAny, + indices: int, + axis: Optional[int] = ..., + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> generic: ... +@overload +def take( + a: _ArrayLike, + indices: int, + axis: Optional[int] = ..., + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> generic: ... +@overload def take( a: _ArrayLike, indices: _ArrayLikeInt, axis: Optional[int] = ..., out: Optional[ndarray] = ..., mode: _Mode = ..., -) -> ndarray: ... +) -> Union[generic, ndarray]: ... def reshape(a: _ArrayLike, newshape: _ShapeLike, order: _Order = ...) -> ndarray: ... +@overload +def choose( + a: _Generic, + choices: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> _Generic: ... +@overload +def choose( + a: _ScalarAny, + choices: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + out: Optional[ndarray] = ..., + mode: _Mode = ..., +) -> generic: ... +@overload def choose( a: _ArrayLike, - choices: Sequence[_ArrayLike], + choices: Union[Sequence[_ArrayLike], _ArrayLikeSeq], out: Optional[ndarray] = ..., mode: _Mode = ..., ) -> ndarray: ... @@ -830,48 +894,72 @@ def repeat( a: _ArrayLike, repeats: _ArrayLikeInt, axis: Optional[int] = ... ) -> ndarray: ... def put(a: ndarray, ind: _ArrayLikeInt, v: _ArrayLike, mode: _Mode = ...) -> None: ... -def swapaxes(a: _ArrayLike, axis1: int, axis2: int) -> ndarray: ... -def transpose(a: _ArrayLike, axes: Optional[Sequence[int]] = ...) -> ndarray: ... +def swapaxes( + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], axis1: int, axis2: int +) -> ndarray: ... +def transpose( + a: _ArrayLike, axes: Union[None, Sequence[int], _ArrayLikeSeq] = ..., +) -> ndarray: ... def partition( a: _ArrayLike, kth: _ArrayLikeInt, axis: Optional[int] = ..., kind: _PartitionKind = ..., - order: Union[None, str, Sequence[str]] = ..., + order: Union[None, str, Sequence[str], _ArrayLikeSeq] = ..., ) -> ndarray: ... def argpartition( a: _ArrayLike, kth: _ArrayLikeInt, - axis: Optional[int], + axis: Optional[int] = ..., kind: _PartitionKind = ..., - order: Union[None, str, Sequence[str]] = ..., + order: Union[None, str, Sequence[str], _ArrayLikeSeq] = ..., ) -> ndarray: ... def sort( - a: _ArrayLike, + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], axis: Optional[int] = ..., kind: Optional[_SortKind] = ..., - order: Union[None, str, Sequence[str]] = ..., + order: Union[None, str, Sequence[str], _ArrayLikeSeq] = ..., ) -> ndarray: ... def argsort( - a: _ArrayLike, + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], axis: Optional[int] = ..., kind: Optional[_SortKind] = ..., - order: Union[None, str, Sequence[str]] = ..., + order: Union[None, str, Sequence[str], _ArrayLikeSeq] = ..., ) -> ndarray: ... @overload -def argmax(a, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ... +def argmax( + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + axis: None = ..., + out: Optional[ndarray] = ..., +) -> integer: ... @overload def argmax( - a, axis: int = ..., out: Optional[ndarray] = ... + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + axis: int = ..., + out: Optional[ndarray] = ..., ) -> Union[integer, ndarray]: ... @overload -def argmin(a, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ... +def argmin( + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + axis: None = ..., + out: Optional[ndarray] = ..., +) -> integer: ... @overload def argmin( - a, axis: int = ..., out: Optional[ndarray] = ... + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + axis: int = ..., + out: Optional[ndarray] = ..., ) -> Union[integer, ndarray]: ... +@overload def searchsorted( - a: _ArrayLike, + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], + v: _ScalarAny, + side: _Side = ..., + sorter: Optional[_ArrayLikeInt] = ..., +) -> integer: ... +@overload +def searchsorted( + a: Union[Sequence[_ArrayLike], _ArrayLikeSeq], v: _ArrayLike, side: _Side = ..., sorter: Optional[_ArrayLikeInt] = ..., @@ -879,10 +967,17 @@ def searchsorted( def resize(a: _ArrayLike, new_shape: _ShapeLike) -> ndarray: ... def squeeze(a: _ArrayLike, axis: Optional[_ShapeLike] = ...) -> ndarray: ... def diagonal( - a: _ArrayLike, offset: int = ..., axis1: int = ..., axis2: int = ... + a: Union[ + Sequence[Sequence[_ArrayLike]], _ArrayLikeSeq + ], # TODO: requires a >= 2D array + offset: int = ..., + axis1: int = ..., + axis2: int = ..., ) -> ndarray: ... def trace( - a: _ArrayLike, + a: Union[ + Sequence[Sequence[_ArrayLike]], _ArrayLikeSeq + ], # TODO: requires a >= 2D array offset: int = ..., axis1: int = ..., axis2: int = ..., @@ -893,11 +988,28 @@ def ravel(a: _ArrayLike, order: _Order = ...) -> ndarray: ... def nonzero(a: _ArrayLike) -> Tuple[ndarray, ...]: ... def shape(a: _ArrayLike) -> _Shape: ... def compress( - condition: _ArrayLikeBool, + condition: Union[Sequence[_ArrayLikeBool], _ArrayLikeSeq], a: _ArrayLike, axis: Optional[int] = ..., out: Optional[ndarray] = ..., ) -> ndarray: ... +@overload +def clip( + a: _Number, + a_min: _ScalarNumeric, + a_max: _ScalarNumeric, + out: Optional[ndarray] = ..., + **kwargs: Any, +) -> _Number: ... +@overload +def clip( + a: _ScalarNumeric, + a_min: _ScalarNumeric, + a_max: _ScalarNumeric, + out: Optional[ndarray] = ..., + **kwargs: Any, +) -> number: ... +@overload def clip( a: _ArrayLike, a_min: _ArrayLike, @@ -906,13 +1018,33 @@ def clip( **kwargs: Any, ) -> Union[number, ndarray]: ... @overload +def sum( + a: _Number, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _ScalarNumeric = ..., + where: _ArrayLikeBool = ..., +) -> _Number: ... +@overload +def sum( + a: _ScalarNumeric, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _ScalarNumeric = ..., + where: _ArrayLikeBool = ..., +) -> number: ... +@overload def sum( a: _ArrayLike, axis: None = ..., dtype: _DtypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _Scalar = ..., # TODO: The type should be compatible with *a* + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -922,10 +1054,17 @@ def sum( dtype: _DtypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _Scalar = ..., # TODO: The type should be compatible with *a* + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload +def all( + a: _ScalarNumeric, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> bool_: ... +@overload def all( a: _ArrayLike, axis: None = ..., @@ -940,6 +1079,13 @@ def all( keepdims: bool = ..., ) -> Union[bool_, ndarray]: ... @overload +def any( + a: _ScalarNumeric, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> bool_: ... +@overload def any( a: _ArrayLike, axis: None = ..., @@ -953,20 +1099,27 @@ def any( out: Optional[ndarray] = ..., keepdims: bool = ..., ) -> Union[bool_, ndarray]: ... -@overload def cumsum( a: _ArrayLike, - axis: None = ..., + axis: Optional[int] = ..., dtype: _DtypeLike = ..., out: Optional[ndarray] = ..., -) -> number: ... +) -> ndarray: ... @overload -def cumsum( - a: _ArrayLike, - axis: int = ..., - dtype: _DtypeLike = ..., +def ptp( + a: _Number, + axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., -) -> Union[number, ndarray]: ... + keepdims: bool = ..., +) -> _Number: ... +@overload +def ptp( + a: _ScalarNumeric, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., +) -> number: ... +@overload def ptp( a: _ArrayLike, axis: Optional[_ShapeLike] = ..., @@ -974,50 +1127,88 @@ def ptp( keepdims: bool = ..., ) -> Union[number, ndarray]: ... @overload +def amax( + a: _ScalarNumeric, + axis: Optional[int] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _ScalarNumeric = ..., + where: _ArrayLikeBool = ..., +) -> integer: ... +@overload def amax( a: _ArrayLike, axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _Scalar = ..., + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., -) -> number: ... +) -> integer: ... @overload def amax( a: _ArrayLike, axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _Scalar = ..., + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., -) -> Union[number, ndarray]: ... +) -> Union[integer, ndarray]: ... +@overload +def amin( + a: _ScalarNumeric, + axis: Optional[_ShapeLike] = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _ScalarNumeric = ..., + where: _ArrayLikeBool = ..., +) -> integer: ... @overload def amin( a: _ArrayLike, axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _Scalar = ..., + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., -) -> number: ... +) -> integer: ... @overload def amin( a: _ArrayLike, axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _Scalar = ..., + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., -) -> Union[number, ndarray]: ... +) -> Union[integer, ndarray]: ... def alen(a: _ArrayLike) -> int: ... @overload +def prod( + a: _Number, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _ScalarNumeric = ..., + where: _ArrayLikeBool = ..., +) -> _Number: ... +@overload +def prod( + a: _ScalarNumeric, + axis: Optional[_ShapeLike] = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: bool = ..., + initial: _ScalarNumeric = ..., + where: _ArrayLikeBool = ..., +) -> number: ... +@overload def prod( a: _ArrayLike, axis: None = ..., dtype: _DtypeLike = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _Scalar = ..., + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1027,7 +1218,7 @@ def prod( dtype: _DtypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _Scalar = ..., + initial: _ScalarNumeric = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... def cumprod( @@ -1038,10 +1229,27 @@ def cumprod( ) -> ndarray: ... def ndim(a: _ArrayLike) -> int: ... def size(a: _ArrayLike, axis: Optional[int] = ...) -> int: ... +@overload +def around( + a: _Number, decimals: int = ..., out: Optional[ndarray] = ... +) -> _Number: ... +@overload +def around( + a: _ScalarNumeric, decimals: int = ..., out: Optional[ndarray] = ... +) -> number: ... +@overload def around( a: _ArrayLike, decimals: int = ..., out: Optional[ndarray] = ... ) -> ndarray: ... @overload +def mean( + a: _ScalarNumeric, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + keepdims: Literal[False] = ..., +) -> number: ... # TODO: The type of the output is determined by *dtype* +@overload def mean( a: _ArrayLike, axis: None = ..., @@ -1058,6 +1266,15 @@ def mean( keepdims: bool = ..., ) -> Union[number, ndarray]: ... @overload +def std( + a: _ScalarNumeric, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + ddof: int = ..., + keepdims: Literal[False] = ..., +) -> number: ... # TODO: The type of the output is determined by *dtype* +@overload def std( a: _ArrayLike, axis: None = ..., @@ -1076,6 +1293,15 @@ def std( keepdims: bool = ..., ) -> Union[number, ndarray]: ... @overload +def var( + a: _ScalarNumeric, + axis: None = ..., + dtype: _DtypeLike = ..., + out: Optional[ndarray] = ..., + ddof: int = ..., + keepdims: bool = ..., +) -> number: ... +@overload def var( a: _ArrayLike, axis: None = ..., @@ -1083,7 +1309,7 @@ def var( out: Optional[ndarray] = ..., ddof: int = ..., keepdims: Literal[False] = ..., -) -> number: ... +) -> number: ... # TODO: The type of the output is determined by *dtype* @overload def var( a: _ArrayLike, diff --git a/setup.py b/setup.py index 7f0b346..235683e 100644 --- a/setup.py +++ b/setup.py @@ -21,10 +21,7 @@ def find_stubs(package): version="0.0.1", packages=['numpy-stubs'], # PEP 561 requires these - install_requires=[ - 'numpy>=1.14.0', - 'typing_extensions; python_version<"3.8"' - ], + install_requires=['numpy>=1.14.0'], package_data=find_stubs('numpy-stubs'), zip_safe=False, ) diff --git a/tests/reveal/fromnumeric.py b/tests/reveal/fromnumeric.py index 08fb259..0c00888 100644 --- a/tests/reveal/fromnumeric.py +++ b/tests/reveal/fromnumeric.py @@ -1,22 +1,251 @@ import numpy as np -A = np.array([True]) +A = np.array([True], dtype=bool) +A_ = np.array([[True]], dtype=bool) +B = np.array([1.0], dtype='float32') +B_ = np.array([[1.0]], dtype='float32') + A.setflags(write=False) +A_.setflags(write=False) +B.setflags(write=False) +B_.setflags(write=False) + +a = np.bool_(True) +b = np.float32(1.0) +c = 1.0 + +reveal_type(np.take(a, 0)) # E: numpy.bool_ +reveal_type(np.take(b, 0)) # E: numpy.float32 +reveal_type(np.take(c, 0)) # E: numpy.generic +reveal_type(np.take(A, 0)) # E: numpy.generic +reveal_type(np.take(B, 0)) # E: numpy.generic +reveal_type(np.take(A, [0])) # E: Union[numpy.generic, numpy.ndarray] +reveal_type(np.take(B, [0])) # E: Union[numpy.generic, numpy.ndarray] + +reveal_type(np.reshape(a, 1)) # E: numpy.ndarray +reveal_type(np.reshape(b, 1)) # E: numpy.ndarray +reveal_type(np.reshape(c, 1)) # E: numpy.ndarray +reveal_type(np.reshape(A, 1)) # E: numpy.ndarray +reveal_type(np.reshape(B, 1)) # E: numpy.ndarray + +reveal_type(np.choose(a, [True])) # E: numpy.bool_ +reveal_type(np.choose(b, [1.0])) # E: numpy.float32 +reveal_type(np.choose(c, [1.0])) # E: numpy.generic +reveal_type(np.choose(A, [True])) # E: numpy.ndarray +reveal_type(np.choose(B, [1.0])) # E: numpy.ndarray + +reveal_type(np.repeat(a, 1)) # E: numpy.ndarray +reveal_type(np.repeat(b, 1)) # E: numpy.ndarray +reveal_type(np.repeat(c, 1)) # E: numpy.ndarray +reveal_type(np.repeat(A, 1)) # E: numpy.ndarray +reveal_type(np.repeat(B, 1)) # E: numpy.ndarray + +# TODO: Add tests for np.put() + +reveal_type(np.swapaxes(A, 0, 0)) # E: numpy.ndarray +reveal_type(np.swapaxes(B, 0, 0)) # E: numpy.ndarray + +reveal_type(np.transpose(a)) # E: numpy.ndarray +reveal_type(np.transpose(b)) # E: numpy.ndarray +reveal_type(np.transpose(c)) # E: numpy.ndarray +reveal_type(np.transpose(A)) # E: numpy.ndarray +reveal_type(np.transpose(B)) # E: numpy.ndarray + +reveal_type(np.partition(a, 0)) # E: numpy.ndarray +reveal_type(np.partition(b, 0)) # E: numpy.ndarray +reveal_type(np.partition(c, 0)) # E: numpy.ndarray +reveal_type(np.partition(A, 0)) # E: numpy.ndarray +reveal_type(np.partition(B, 0)) # E: numpy.ndarray + +reveal_type(np.argpartition(a, 0)) # E: numpy.ndarray +reveal_type(np.argpartition(b, 0)) # E: numpy.ndarray +reveal_type(np.argpartition(c, 0)) # E: numpy.ndarray +reveal_type(np.argpartition(A, 0)) # E: numpy.ndarray +reveal_type(np.argpartition(B, 0)) # E: numpy.ndarray + +reveal_type(np.sort(A, 0)) # E: numpy.ndarray +reveal_type(np.sort(B, 0)) # E: numpy.ndarray + +reveal_type(np.argsort(A, 0)) # E: numpy.ndarray +reveal_type(np.argsort(B, 0)) # E: numpy.ndarray + +reveal_type(np.argmin(A)) # E: numpy.integer +reveal_type(np.argmin(B)) # E: numpy.integer +reveal_type(np.argmin(A, axis=0)) # E: Union[numpy.integer, numpy.ndarray] +reveal_type(np.argmin(B, axis=0)) # E: Union[numpy.integer, numpy.ndarray] + +reveal_type(np.argmax(A)) # E: numpy.integer +reveal_type(np.argmax(B)) # E: numpy.integer +reveal_type(np.argmax(A, axis=0)) # E: Union[numpy.integer, numpy.ndarray] +reveal_type(np.argmax(B, axis=0)) # E: Union[numpy.integer, numpy.ndarray] + +reveal_type(np.searchsorted(A, 0)) # E: numpy.integer +reveal_type(np.searchsorted(B, 0)) # E: numpy.integer +reveal_type(np.searchsorted(A, [0])) # E: numpy.ndarray +reveal_type(np.searchsorted(B, [0])) # E: numpy.ndarray + +reveal_type(np.resize(a, (1,))) # E: numpy.ndarray +reveal_type(np.resize(b, (1,))) # E: numpy.ndarray +reveal_type(np.resize(c, (1,))) # E: numpy.ndarray +reveal_type(np.resize(A, (1,))) # E: numpy.ndarray +reveal_type(np.resize(B, (1,))) # E: numpy.ndarray + +reveal_type(np.squeeze(a)) # E: numpy.ndarray +reveal_type(np.squeeze(b)) # E: numpy.ndarray +reveal_type(np.squeeze(c)) # E: numpy.ndarray +reveal_type(np.squeeze(A)) # E: numpy.ndarray +reveal_type(np.squeeze(B)) # E: numpy.ndarray + +reveal_type(np.diagonal(A_)) # E: numpy.ndarray +reveal_type(np.diagonal(B_)) # E: numpy.ndarray + +reveal_type(np.trace(A_)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.trace(B_)) # E: Union[numpy.number, numpy.ndarray] + +reveal_type(np.ravel(a)) # E: numpy.ndarray +reveal_type(np.ravel(b)) # E: numpy.ndarray +reveal_type(np.ravel(c)) # E: numpy.ndarray +reveal_type(np.ravel(A)) # E: numpy.ndarray +reveal_type(np.ravel(B)) # E: numpy.ndarray + +reveal_type(np.nonzero(a)) # E: builtins.tuple[numpy.ndarray] +reveal_type(np.nonzero(b)) # E: builtins.tuple[numpy.ndarray] +reveal_type(np.nonzero(c)) # E: builtins.tuple[numpy.ndarray] +reveal_type(np.nonzero(A)) # E: builtins.tuple[numpy.ndarray] +reveal_type(np.nonzero(B)) # E: builtins.tuple[numpy.ndarray] + +reveal_type(np.shape(a)) # E: builtins.tuple[builtins.int] +reveal_type(np.shape(b)) # E: builtins.tuple[builtins.int] +reveal_type(np.shape(c)) # E: builtins.tuple[builtins.int] +reveal_type(np.shape(A)) # E: builtins.tuple[builtins.int] +reveal_type(np.shape(B)) # E: builtins.tuple[builtins.int] + +reveal_type(np.compress([True], a)) # E: numpy.ndarray +reveal_type(np.compress([True], b)) # E: numpy.ndarray +reveal_type(np.compress([True], c)) # E: numpy.ndarray +reveal_type(np.compress([True], A)) # E: numpy.ndarray +reveal_type(np.compress([True], B)) # E: numpy.ndarray + +reveal_type(np.clip(a, 0, 2)) # E: numpy.number +reveal_type(np.clip(b, 0, 2)) # E: numpy.float32 +reveal_type(np.clip(c, 0, 2)) # E: numpy.number +reveal_type(np.clip(A, 0, 2)) # E: numpy.ndarray +reveal_type(np.clip(B, 0, 2)) # E: numpy.ndarray + +reveal_type(np.sum(a)) # E: numpy.number +reveal_type(np.sum(b)) # E: numpy.float32 +reveal_type(np.sum(c)) # E: numpy.number +reveal_type(np.sum(A)) # E: numpy.number +reveal_type(np.sum(B)) # E: numpy.number +reveal_type(np.sum(A, axis=0)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.sum(B, axis=0)) # E: Union[numpy.number, numpy.ndarray] reveal_type(np.all(A)) # E: numpy.bool_ +reveal_type(np.all(B)) # E: numpy.bool_ +reveal_type(np.all(a)) # E: numpy.bool_ +reveal_type(np.all(b)) # E: numpy.bool_ +reveal_type(np.all(c)) # E: numpy.bool_ reveal_type(np.all(A, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] reveal_type(np.all(A, keepdims=False)) # E: numpy.bool_ -reveal_type(np.all(A, axis=0, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] -reveal_type(np.all(A, axis=0, keepdims=False)) # E: Union[numpy.bool_, numpy.ndarray] -reveal_type(np.all(A, keepdims=True, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] -reveal_type(np.all(A, keepdims=False, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] reveal_type(np.all(A, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] reveal_type(np.any(A)) # E: numpy.bool_ +reveal_type(np.any(B)) # E: numpy.bool_ +reveal_type(np.any(a)) # E: numpy.bool_ +reveal_type(np.any(b)) # E: numpy.bool_ +reveal_type(np.any(c)) # E: numpy.bool_ reveal_type(np.any(A, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] reveal_type(np.any(A, keepdims=False)) # E: numpy.bool_ -reveal_type(np.any(A, axis=0, keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray] -reveal_type(np.any(A, axis=0, keepdims=False)) # E: Union[numpy.bool_, numpy.ndarray] -reveal_type(np.any(A, keepdims=True, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] -reveal_type(np.any(A, keepdims=False, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] reveal_type(np.any(A, axis=0)) # E: Union[numpy.bool_, numpy.ndarray] + +reveal_type(np.cumsum(a)) # E: numpy.ndarray +reveal_type(np.cumsum(b)) # E: numpy.ndarray +reveal_type(np.cumsum(c)) # E: numpy.ndarray +reveal_type(np.cumsum(A)) # E: numpy.ndarray +reveal_type(np.cumsum(B)) # E: numpy.ndarray + +reveal_type(np.ptp(a)) # E: numpy.number +reveal_type(np.ptp(b)) # E: numpy.float32 +reveal_type(np.ptp(c)) # E: numpy.number +reveal_type(np.ptp(A)) # E: numpy.number +reveal_type(np.ptp(B)) # E: numpy.number +reveal_type(np.ptp(A, axis=0)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.ptp(B, axis=0)) # E: Union[numpy.number, numpy.ndarray] + +reveal_type(np.amax(a)) # E: numpy.integer +reveal_type(np.amax(b)) # E: numpy.integer +reveal_type(np.amax(c)) # E: numpy.integer +reveal_type(np.amax(A)) # E: numpy.integer +reveal_type(np.amax(B)) # E: numpy.integer +reveal_type(np.amax(A, axis=0)) # E: Union[numpy.integer, numpy.ndarray] +reveal_type(np.amax(B, axis=0)) # E: Union[numpy.integer, numpy.ndarray] + +reveal_type(np.amin(a)) # E: numpy.integer +reveal_type(np.amin(b)) # E: numpy.integer +reveal_type(np.amin(c)) # E: numpy.integer +reveal_type(np.amin(A)) # E: numpy.integer +reveal_type(np.amin(B)) # E: numpy.integer +reveal_type(np.amin(A, axis=0)) # E: Union[numpy.integer, numpy.ndarray] +reveal_type(np.amin(B, axis=0)) # E: Union[numpy.integer, numpy.ndarray] + +reveal_type(np.alen(a)) # E: builtins.int +reveal_type(np.alen(b)) # E: builtins.int +reveal_type(np.alen(c)) # E: builtins.int +reveal_type(np.alen(A)) # E: builtins.int +reveal_type(np.alen(B)) # E: builtins.int + +reveal_type(np.prod(a)) # E: numpy.number +reveal_type(np.prod(b)) # E: numpy.float32 +reveal_type(np.prod(c)) # E: numpy.number +reveal_type(np.prod(A)) # E: numpy.number +reveal_type(np.prod(B)) # E: numpy.number +reveal_type(np.prod(A, axis=0)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.prod(B, axis=0)) # E: Union[numpy.number, numpy.ndarray] + +reveal_type(np.cumprod(a)) # E: numpy.ndarray +reveal_type(np.cumprod(b)) # E: numpy.ndarray +reveal_type(np.cumprod(c)) # E: numpy.ndarray +reveal_type(np.cumprod(A)) # E: numpy.ndarray +reveal_type(np.cumprod(B)) # E: numpy.ndarray + +reveal_type(np.ndim(a)) # E: builtins.int +reveal_type(np.ndim(b)) # E: builtins.int +reveal_type(np.ndim(c)) # E: builtins.int +reveal_type(np.ndim(A)) # E: builtins.int +reveal_type(np.ndim(B)) # E: builtins.int + +reveal_type(np.size(a)) # E: builtins.int +reveal_type(np.size(b)) # E: builtins.int +reveal_type(np.size(c)) # E: builtins.int +reveal_type(np.size(A)) # E: builtins.int +reveal_type(np.size(B)) # E: builtins.int + +reveal_type(np.around(a)) # E: numpy.number +reveal_type(np.around(b)) # E: numpy.float32 +reveal_type(np.around(c)) # E: numpy.number +reveal_type(np.around(A)) # E: numpy.ndarray +reveal_type(np.around(B)) # E: numpy.ndarray + +reveal_type(np.mean(a)) # E: numpy.number +reveal_type(np.mean(b)) # E: numpy.number +reveal_type(np.mean(c)) # E: numpy.number +reveal_type(np.mean(A)) # E: numpy.number +reveal_type(np.mean(B)) # E: numpy.number +reveal_type(np.mean(A, axis=0)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.mean(B, axis=0)) # E: Union[numpy.number, numpy.ndarray] + +reveal_type(np.std(a)) # E: numpy.number +reveal_type(np.std(b)) # E: numpy.number +reveal_type(np.std(c)) # E: numpy.number +reveal_type(np.std(A)) # E: numpy.number +reveal_type(np.std(B)) # E: numpy.number +reveal_type(np.std(A, axis=0)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.std(B, axis=0)) # E: Union[numpy.number, numpy.ndarray] + +reveal_type(np.var(a)) # E: numpy.number +reveal_type(np.var(b)) # E: numpy.number +reveal_type(np.var(c)) # E: numpy.number +reveal_type(np.var(A)) # E: numpy.number +reveal_type(np.var(B)) # E: numpy.number +reveal_type(np.var(A, axis=0)) # E: Union[numpy.number, numpy.ndarray] +reveal_type(np.var(B, axis=0)) # E: Union[numpy.number, numpy.ndarray]