8000 ENH: add type stubs from numpy-stubs by person142 · Pull Request #16515 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: add type stubs from numpy-stubs #16515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
ENH: add type stubs from numpy-stubs
Add the type stubs and tests from numpy-stubs. Things this entails:

- Copy over the stubs (numpy/__init__.pyi and
  numpy/core/_internal.pyi)
  - The only modification made was removing `ndarray.tostring` since
    it is deprecated
- Update some setup.py files to include pyi files
- Move the tests from numpy-stubs/tests into numpy/tests
  - Skip them if mypy is not installed (planning on setting up CI in a
    future PR)
  - Add a mypy.ini; use it to configure mypy in the tests
    - It tells mypy where to find NumPy in the test env
    - It ignores internal NumPy type errors (since we only want to
      consider errors from the tests cases)
  - Some small edits were made to fix test cases that were emitting
    deprecation warnings
 - Add numpy/py.typed so that the types are picked up in an
   installed version of NumPy
  • Loading branch information
person142 committed Jun 6, 2020
commit 11b95d15f10c2bc652ed19d5e27efa0384396cb8
1,077 changes: 1,077 additions & 0 deletions numpy/__init__.pyi

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions numpy/core/_internal.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Any
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


# TODO: add better annotations when ctypes is stubbed out

class _ctypes:
@property
def data(self) -> int: ...
@property
def shape(self) -> Any: ...
@property
def strides(self) -> Any: ...
def data_as(self, obj: Any) -> Any: ...
def shape_as(self, obj: Any) -> Any: ...
def strides_as(self, obj: Any) -> Any: ...
def get_data(self) -> int: ...
def get_shape(self) -> Any: ...
def get_strides(self) -> Any: ...
def get_as_parameter(self) -> Any: ...
1 change: 1 addition & 0 deletions numpy/core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,7 @@ def generate_umath_c(ext, build_dir):
config.add_subpackage('tests')
config.add_data_dir('tests/data')
config.add_data_dir('tests/examples')
config.add_data_files('*.pyi')

config.make_svn_version_py()

Expand Down
Empty file added numpy/py.typed
Empty file.
2 changes: 2 additions & 0 deletions numpy/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def configuration(parent_package='',top_path=None):
config.add_subpackage('random')
config.add_subpackage('testing')
config.add_data_dir('doc')
config.add_data_files('py.typed')
config.add_data_files('*.pyi')
config.add_subpackage('tests')
config.make_config_py() # installs __config__.py
return config
Expand Down
22 changes: 22 additions & 0 deletions numpy/tests/fail/array_like.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Any, TYPE_CHECKING
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


import numpy as np

if TYPE_CHECKING:
from numpy.typing import ArrayLike
else:
ArrayLike = Any


class A:
pass


x1: ArrayLike = (i for i in range(10)) # E: Incompatible types in assignment
x2: ArrayLike = A() # E: Incompatible types in assignment
x3: ArrayLike = {1: "foo", 2: "bar"} # E: Incompatible types in assignment

scalar = np.int64(1)
scalar.__array__(dtype=np.float64) # E: Unexpected keyword argument
array = np.array([1])
array.__array__(dtype=np.float64) # E: Unexpected keyword argument
101 changes: 101 additions & 0 deletions numpy/tests/fail/fromnumeric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""Tests for :mod:`numpy.core.fromnumeric`."""

import numpy as np

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 type
np.take(a, axis=1.0) # E: No overload variant of "take" matches argument type
np.take(A, out=1) # E: No overload variant of "take" matches argument type
np.take(A, mode="bob") # E: No overload variant of "take" matches argument type

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 type
np.choose(a, out=1.0) # E: No overload variant of "choose" matches argument type
np.choose(A, mode="bob") # E: No overload variant of "choose" matches argument type

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( # E: No overload variant of "argpartition" matches argument type
a, None
)
np.argpartition( # E: No overload variant of "argpartition" matches argument type
a, 0, axis="bob"
)
np.argpartition( # E: No overload variant of "argpartition" matches argument type
A, 0, kind="bob"
)
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

np.argmax(a) # E: No overload variant of "argmax" matches argument type
np.argmax(A, axis="bob") # E: No overload variant of "argmax" matches argument type
np.argmax(A, kind="bob") # E: No overload variant of "argmax" matches argument type

np.argmin(a) # E: No overload variant of "argmin" matches argument type
np.argmin(A, axis="bob") # E: No overload variant of "argmin" matches argument type
np.argmin(A, kind="bob") # E: No overload variant of "argmin" matches argument type

np.searchsorted(a, 0) # E: No overload variant of "searchsorted" matches argument type
np.searchsorted( # E: No overload variant of "searchsorted" matches argument type
A[0], 0, side="bob"
)
np.searchsorted( # E: No overload variant of "searchsorted" matches argument type
A[0], 0, sorter=1.0
)

np.resize(A, 1.0) # E: Argument 2 to "resize" has incompatible type

np.squeeze(A, 1.0) # E: No overload variant of "squeeze" matches argument type

np.diagonal(a) # E: Argument 1 to "diagonal" has incompatible type
np.diagonal(A, offset=None) # E: Argument "offset" to "diagonal" has incompatible type
np.diagonal(A, axis1="bob") # E: Argument "axis1" to "diagonal" has incompatible type
np.diagonal(A, axis2=[]) # E: Argument "axis2" to "diagonal" has incompatible type

np.trace(a) # E: Argument 1 to "trace" has incompatible type
np.trace(A, offset=None) # E: Argument "offset" to "trace" has incompatible type
np.trace(A, axis1="bob") # E: Argument "axis1" to "trace" has incompatible type
np.trace(A, axis2=[]) # E: Argument "axis2" to "trace" has incompatible type

np.ravel(a, order="bob") # E: Argument "order" to "ravel" has incompatible type

np.compress(True, A) # E: Argument 1 to "compress" has incompatible type
np.compress(
[True], A, axis=1.0 # E: Argument "axis" to "compress" has incompatible type
)
11 changes: 11 additions & 0 deletions numpy/tests/fail/ndarray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import numpy as np

# Ban setting dtype since mutating the type of the array in place
# makes having ndarray be generic over dtype impossible. Generally
# users should use `ndarray.view` in this situation anyway. See
#
# https://github.com/numpy/numpy-stubs/issues/7
#
# for more context.
float_array = np.array([1.0])
float_array.dtype = np.bool_ # E: Property "dtype" defined in "ndarray" is read-only
13 changes: 13 additions & 0 deletions numpy/tests/fail/numerictypes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import numpy as np

# Techincally this works, but probably shouldn't. See
#
# https://github.com/numpy/numpy/issues/16366
#
np.maximum_sctype(1) # E: incompatible type "int"

np.issubsctype(1, np.int64) # E: incompatible type "int"

np.issubdtype(1, np.int64) # E: incompatible type "int"

np.find_common_type(np.int64, np.int64) # E: incompatible type "Type[int64]"
67 changes: 67 additions & 0 deletions numpy/tests/fail/scalars.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import numpy as np

# Construction

np.float32(3j) # E: incompatible type

# Technically the following examples are valid NumPy code. But they
# are not considered a best practice, and people who wish to use the
# stubs should instead do
#
# np.array([1.0, 0.0, 0.0], dtype=np.float32)
# np.array([], dtype=np.complex64)
#
# See e.g. the discussion on the mailing list
#
# https://mail.python.org/pipermail/numpy-discussion/2020-April/080566.html
#
# and the issue
#
# https://github.com/numpy/numpy-stubs/issues/41
#
# for more context.
np.float32([1.0, 0.0, 0.0]) # E: incompatible type
np.complex64([]) # E: incompatible type

np.complex64(1, 2) # E: Too many arguments
# TODO: protocols (can't check for non-existent protocols w/ __getattr__)

np.datetime64(0) # E: non-matching overload

dt_64 = np.datetime64(0, "D")
td_64 = np.timedelta64(1, "h")

dt_64 + dt_64 # E: Unsupported operand types

td_64 - dt_64 # E: Unsupported operand types
td_64 / dt_64 # E: No overload
td_64 % 1 # E: Unsupported operand types
td_64 % dt_64 # E: Unsupported operand types


class A:
def __float__(self):
return 1.0


np.int8(A()) # E: incompatible type
np.int16(A()) # E: incompatible type
np.int32(A()) # E: incompatible type
np.int64(A()) # E: incompatible type
np.uint8(A()) # E: incompatible type
np.uint16(A()) # E: incompatible type
np.uint32(A()) # E: incompatible type
np.uint64(A()) # E: incompatible type

np.void("test") # E: incompatible type

np.generic(1) # E: Cannot instantiate abstract class
np.number(1) # E: Cannot instantiate abstract class
np.integer(1) # E: Cannot instantiate abstract class
np.signedinteger(1) # E: Cannot instantiate abstract class
np.unsignedinteger(1) # E: Cannot instantiate abstract class
np.inexact(1) # E: Cannot instantiate abstract class
np.floating(1) # E: Cannot instantiate abstract class
np.complexfloating(1) # E: Cannot instantiate abstract class
np.character("test") # E: Cannot instantiate abstract class
np.flexible(b"test") # E: Cannot instantiate abstract class
10 changes: 10 additions & 0 deletions numpy/tests/fail/simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Simple expression that should fail with mypy."""

import numpy as np

# Array creation routines checks
np.zeros("test") # E: incompatible type
np.zeros() # E: Too few arguments

np.ones("test") # E: incompatible type
np.ones() # E: Too few arguments
5 changes: 5 additions & 0 deletions numpy/tests/fail/ufuncs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import numpy as np

np.sin.nin + "foo" # E: Unsupported operand types
np.sin(1, foo="bar") # E: Unexpected keyword argument
np.sin(1, extobj=["foo", "foo", "foo"]) # E: incompatible type
7 changes: 7 additions & 0 deletions numpy/tests/fail/warnings_and_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
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
)
8 changes: 8 additions & 0 deletions numpy/tests/mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[mypy]
mypy_path = ../..

[mypy-numpy]
ignore_errors = True

[mypy-numpy.*]
ignore_errors = True
44 changes: 44 additions & 0 deletions numpy/tests/pass/array_like.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import Any, List, Optional, TYPE_CHECKING

import numpy as np

if TYPE_CHECKING:
from numpy.typing import ArrayLike, DtypeLike, _SupportsArray
else:
ArrayLike = Any
DtypeLike = Any
_SupportsArray = Any

x1: ArrayLike = True
x2: ArrayLike = 5
x3: ArrayLike = 1.0
x4: ArrayLike = 1 + 1j
x5: ArrayLike = np.int8(1)
x6: ArrayLike = np.float64(1)
x7: ArrayLike = np.complex128(1)
x8: ArrayLike = np.array([1, 2, 3])
x9: ArrayLike = [1, 2, 3]
x10: ArrayLike = (1, 2, 3)
x11: ArrayLike = "foo"


class A:
def __array__(self, dtype: DtypeLike = None) -> np.ndarray:
return np.array([1, 2, 3])


x12: ArrayLike = A()

scalar: _SupportsArray = np.int64(1)
scalar.__array__(np.float64)
array: _SupportsArray = np.array(1)
array.__array__(np.float64)

a: _SupportsArray = A()
a.__array__(np.int64)
a.__array__(dtype=np.int64)

# Escape hatch for when you mean to make something like an object
# array.
object_array_scalar: Any = (i for i in range(10))
np.array(object_array_scalar)
Loading
0