-
-
Notifications
You must be signed in to change notification settings - Fork 31
ENH: Add type annotations for the np.core.fromnumeric module: part 1/4 #67
Changes from 5 commits
dd7a601
36581cb
c2eeada
37cbded
36efcf3
837eec6
11dd7e4
35e1cda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,6 @@ venv | |
.idea | ||
*~ | ||
**~ | ||
|
||
# MacOS | ||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
||
# TODO: remove when the full numpy namespace is defined | ||
def __getattr__(name: str) -> Any: ... | ||
|
||
|
@@ -792,3 +797,131 @@ class AxisError(ValueError, IndexError): | |
def __init__( | ||
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"] | ||
|
||
# Various annotations for scalars | ||
_ScalarGeneric = TypeVar("_ScalarGeneric", bound=generic) | ||
_ScalarBuiltin = Union[str, bytes, dt.date, dt.timedelta, bool, int, float, complex] | ||
_Scalar = Union[_ScalarBuiltin, generic] | ||
|
||
# An array-like object consisting of integers | ||
# TODO: If possible, figure out a better way to deal with nested sequences | ||
_Int = Union[int, integer] | ||
_ArrayLikeInt = Union[ | ||
_Int, | ||
ndarray, # TODO: ndarray[int] | ||
Sequence[_Int], | ||
Sequence[Sequence[_Int]], | ||
Sequence[Sequence[Sequence[_Int]]], | ||
Sequence[Sequence[Sequence[Sequence[_Int]]]], | ||
Sequence[Sequence[Sequence[Sequence[Sequence[_Int]]]]], | ||
Sequence[Sequence[Sequence[Sequence[Sequence[Sequence[_Int]]]]]], | ||
] | ||
|
||
# An array-like object consisting of strings | ||
_ArrayLikeStr = Union[ | ||
str, str_, Sequence[Union[str, str_]], ndarray | ||
] # TODO: ndarray[str] | ||
|
||
# The signature of take() follows a common theme with its overloads: | ||
# 1. A generic comes in; the same generic comes out | ||
# 2. A scalar comes in; a generic comes out | ||
# 3. An array-like object comes in; some keyword ensures that a generic comes out | ||
# 4. An array-like object comes in; an ndarray or generic comes out | ||
@overload | ||
def take( | ||
a: _ScalarGeneric, | ||
indices: int, | ||
axis: Optional[int] = ..., | ||
out: Optional[ndarray] = ..., | ||
mode: _Mode = ..., | ||
) -> _ScalarGeneric: ... | ||
@overload | ||
def take( | ||
a: _Scalar, | ||
indices: int, | ||
axis: Optional[int] = ..., | ||
out: Optional[ndarray] = ..., | ||
mode: _Mode = ..., | ||
) -> generic: ... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't always true I don't think: >>> type(np.take(datetime.timedelta(days=1), 0))
<class 'datetime.timedelta'>
>>> type(np.take(datetime.date.today(), 0))
<class 'datetime.date'> Works for the others though. There might be diminishing returns getting this to work until such a time as we have a templating system in place; then it can generate specific overloads like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If thus is only exception to the rule, then I feel it might be worthwhile to swap |
||
@overload | ||
def take( | ||
a: _ArrayLike, | ||
indices: int, | ||
axis: Optional[int] = ..., | ||
out: Optional[ndarray] = ..., | ||
mode: _Mode = ..., | ||
) -> generic: ... | ||
@overload | ||
def take( | ||
a: _ArrayLike, | ||
indices: _ArrayLikeInt, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think >>> x = np.arange(9).reshape(3, 3)
>>> np.take(x, [[0, 1], [1, 2]], axis=1)
array([[[0, 1],
[1, 2]],
[[3, 4],
[4, 5]],
[[6, 7],
[7, 8]]]) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's true, I forgot the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So far we've just been doing It's not the best, but I think it's what we have right now. (Though I have also considered the
It felt too gross to do, but maybe there's more discussion to be had on it in an issue.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Gross it most definetly is; I've changed it to |
||
axis: Optional[int] = ..., | ||
out: Optional[ndarray] = ..., | ||
mode: _Mode = ..., | ||
) -> Union[generic, ndarray]: ... | ||
def reshape(a: _ArrayLike, newshape: _ShapeLike, order: _Order = ...) -> ndarray: ... | ||
@overload | ||
def choose( | ||
a: _ScalarGeneric, | ||
choices: Union[Sequence[_ArrayLike], ndarray], # TODO: ndarray[_ArrayLike] | ||
out: Optional[ndarray] = ..., | ||
mode: _Mode = ..., | ||
) -> _ScalarGeneric: ... | ||
@overload | ||
def choose( | ||
a: _Scalar, | ||
choices: Union[Sequence[_ArrayLike], ndarray], # TODO: ndarray[_ArrayLike] | ||
out: Optional[ndarray] = ..., | ||
mode: _Mode = ..., | ||
) -> generic: ... | ||
@overload | ||
def choose( | ||
a: _ArrayLike, | ||
choices: Union[Sequence[_ArrayLike], ndarray], # TODO: ndarray[_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: ... | ||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def swapaxes( | ||
a: Union[Sequence[_ArrayLike], ndarray], # TODO: ndarray[_ArrayLike] | ||
axis1: int, | ||
axis2: int, | ||
) -> ndarray: ... | ||
def transpose( | ||
a: _ArrayLike, axes: Union[None, Sequence[int], ndarray] = ... # TODO: ndarray[int] | ||
) -> ndarray: ... | ||
def partition( | ||
a: _ArrayLike, | ||
kth: _ArrayLikeInt, | ||
axis: Optional[int] = ..., | ||
kind: _PartitionKind = ..., | ||
order: Optional[_ArrayLikeStr] = ..., | ||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) -> ndarray: ... | ||
def argpartition( | ||
a: _ArrayLike, | ||
kth: _ArrayLikeInt, | ||
axis: Optional[int] = ..., | ||
kind: _PartitionKind = ..., | ||
order: Optional[_ArrayLikeStr] = ..., | ||
) -> ndarray: ... | ||
def sort( | ||
a: Union[Sequence[_ArrayLike], ndarray], | ||
axis: Optional[int] = ..., | ||
kind: Optional[_SortKind] = ..., | ||
order: Optional[_ArrayLikeStr] = ..., | ||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) -> ndarray: ... | ||
def argsort( | ||
a: Union[Sequence[_ArrayLike], ndarray], | ||
axis: Optional[int] = ..., | ||
kind: Optional[_SortKind] = ..., | ||
order: Optional[_ArrayLikeStr] = ..., | ||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) -> ndarray: ... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
"""Tests for :mod:`numpy.core.fromnumeric`.""" | ||
|
||
import numpy as np | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe there's a better name than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently it's named after the corresponding module in NumPy ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Im any case, I've added a module-level docstring to the tests for now to clarify that the relevant functions are from |
||
|
||
A = np.array(True, ndmin=2, dtype=bool) | ||
A.setflags(write=False) | ||
|
||
a = np.bool_(True) | ||
|
||
np.take(a, None) # E: No overload variant of "take" matches argument types | ||
np.take(a, axis=1.0) # E: No overload variant of "take" matches argument types | ||
np.take(A, out=1) # E: No overload variant of "take" matches argument types | ||
np.take(A, mode="bob") # E: No overload variant of "take" matches argument types | ||
|
||
np.reshape(a, None) # E: Argument 2 to "reshape" has incompatible type | ||
np.reshape(A, 1, order="bob") # E: Argument "order" to "reshape" has incompatible type | ||
|
||
np.choose(a, None) # E: No overload variant of "choose" matches argument types | ||
np.choose(a, out=1.0) # E: No overload variant of "choose" matches argument types | ||
np.choose(A, mode="bob") # E: No overload variant of "choose" matches argument types | ||
|
||
np.repeat(a, None) # E: Argument 2 to "repeat" has incompatible type | ||
np.repeat(A, 1, axis=1.0) # E: Argument "axis" to "repeat" has incompatible type | ||
|
||
np.swapaxes(a, 0, 0) # E: Argument 1 to "swapaxes" has incompatible type | ||
np.swapaxes(A, None, 1) # E: Argument 2 to "swapaxes" has incompatible type | ||
np.swapaxes(A, 1, [0]) # E: Argument 3 to "swapaxes" has incompatible type | ||
|
||
np.transpose(a, axes=1) # E: Argument "axes" to "transpose" has incompatible type | ||
np.transpose(A, axes=1.0) # E: Argument "axes" to "transpose" has incompatible type | ||
|
||
np.partition(a, None) # E: Argument 2 to "partition" has incompatible type | ||
np.partition( | ||
a, 0, axis="bob" # E: Argument "axis" to "partition" has incompatible type | ||
) | ||
np.partition( | ||
A, 0, kind="bob" # E: Argument "kind" to "partition" has incompatible type | ||
) | ||
np.partition( | ||
A, 0, order=range(5) # E: Argument "order" to "partition" has incompatible type | ||
) | ||
|
||
np.argpartition(a, None) # E: Argument 2 to "argpartition" has incompatible type | ||
np.argpartition( | ||
a, 0, axis="bob" # E: Argument "axis" to "argpartition" has incompatible type | ||
) | ||
np.argpartition( | ||
A, 0, kind="bob" # E: Argument "kind" to "argpartition" has incompatible type | ||
) | ||
np.argpartition( | ||
A, 0, order=range(5) # E: Argument "order" to "argpartition" has incompatible type | ||
) | ||
|
||
np.sort(a) # E: Argument 1 to "sort" has incompatible type | ||
np.sort(A, axis="bob") # E: Argument "axis" to "sort" has incompatible type | ||
np.sort(A, kind="bob") # E: Argument "kind" to "sort" has incompatible type | ||
np.sort(A, order=range(5)) # E: Argument "order" to "sort" has incompatible type | ||
|
||
np.argsort(a) # E: Argument 1 to "argsort" has incompatible type | ||
np.argsort(A, axis="bob") # E: Argument "axis" to "argsort" has incompatible type | ||
np.argsort(A, kind="bob") # E: Argument "kind" to "argsort" has incompatible type | ||
np.argsort(A, order=range(5)) # E: Argument "order" to "argsort" has incompatible type |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
"""Tests for :mod:`numpy.core.fromnumeric`.""" | ||
|
||
import numpy as np | ||
|
||
A = np.array(True, ndmin=2, dtype=bool) | ||
B = np.array(1.0, ndmin=2, dtype=np.float32) | ||
A.setflags(write=False) | ||
B.setflags(write=False) | ||
|
||
a = np.bool_(True) | ||
b = np.float32(1.0) | ||
c = 1.0 | ||
|
||
np.take(a, 0) | ||
np.take(b, 0) | ||
np.take(c, 0) | ||
np.take(A, 0) | ||
np.take(B, 0) | ||
np.take(A, [0]) | ||
np.take(B, [0]) | ||
|
||
np.reshape(a, 1) | ||
np.reshape(b, 1) | ||
np.reshape(c, 1) | ||
np.reshape(A, 1) | ||
np.reshape(B, 1) | ||
|
||
np.choose(a, [True]) | ||
np.choose(b, [1.0]) | ||
np.choose(c, [1.0]) | ||
np.choose(A, [True]) | ||
np.choose(B, [1.0]) | ||
|
||
np.repeat(a, 1) | ||
np.repeat(b, 1) | ||
np.repeat(c, 1) | ||
np.repeat(A, 1) | ||
np.repeat(B, 1) | ||
|
||
np.swapaxes(A, 0, 0) | ||
np.swapaxes(B, 0, 0) | ||
|
||
np.transpose(a) | ||
np.transpose(b) | ||
np.transpose(c) | ||
np.transpose(A) | ||
np.transpose(B) | ||
|
||
np.partition(a, 0) | ||
np.partition(b, 0) | ||
np.partition(c, 0) | ||
np.partition(A, 0) | ||
np.partition(B, 0) | ||
|
||
np.argpartition(a, 0) | ||
np.argpartition(b, 0) | ||
np.argpartition(c, 0) | ||
np.argpartition(A, 0) | ||
np.argpartition(B, 0) | ||
|
||
np.sort(A, 0) | ||
np.sort(B, 0) | ||
|
||
np.argsort(A, 0) | ||
np.argsort(B, 0) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"""Tests for :mod:`numpy.core.fromnumeric`.""" | ||
|
||
import numpy as np | ||
|
||
A = np.array(True, ndmin=2, dtype=bool) | ||
B = np.array(1.0, ndmin=2, dtype=np.float32) | ||
A.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 |
Uh oh!
There was an error while loading. Please reload this page.