summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPamphile ROY <roy.pamphile@gmail.com>2021-04-16 18:40:33 +0200
committerGitHub <noreply@github.com>2021-04-16 18:40:33 +0200
commit2ba1cdedf8a8ee68cf6c0273e98c7fc2ed7f47cf (patch)
tree2c282c939d25d0a5991ca32085161e90fb33f023
parentf47f64e319faca16519fb2a229b4ebb5c0271850 (diff)
parenta6cd7b4f56c9fbffb9e72e8ffc5a0b9e70d1b06d (diff)
downloadnumpy-2ba1cdedf8a8ee68cf6c0273e98c7fc2ed7f47cf.tar.gz
Merge branch 'main' into test_guidelines_random_asserts
-rw-r--r--doc/TESTS.rst.txt18
-rw-r--r--doc/source/conf.py1
-rw-r--r--numpy/__init__.pyi156
-rw-r--r--numpy/fft/__init__.py4
-rw-r--r--numpy/fft/__init__.pyi4
-rw-r--r--numpy/linalg/__init__.py3
-rw-r--r--numpy/linalg/__init__.pyi4
-rw-r--r--numpy/polynomial/__init__.py16
-rw-r--r--numpy/polynomial/__init__.pyi4
-rw-r--r--numpy/random/_generator.pyx2
-rw-r--r--numpy/typing/_shape.py11
-rw-r--r--numpy/typing/tests/data/pass/array_constructors.py16
12 files changed, 177 insertions, 62 deletions
diff --git a/doc/TESTS.rst.txt b/doc/TESTS.rst.txt
index fd8845291..ba09aa800 100644
--- a/doc/TESTS.rst.txt
+++ b/doc/TESTS.rst.txt
@@ -106,6 +106,8 @@ module called ``test_yyy.py``. If you only need to test one aspect of
More often, we need to group a number of tests together, so we create
a test class::
+ import pytest
+
# import xxx symbols
from numpy.xxx.yyy import zzz
import pytest
@@ -115,11 +117,23 @@ a test class::
assert zzz() == 'Hello from zzz'
def test_invalid_parameter(self):
- with pytest.raises(xxxError, match='expected error message'):
+ with pytest.raises(ValueError, match='.*some matching regex.*'):
...
Within these test methods, ``assert`` and related functions are used to test
whether a certain assumption is valid. If the assertion fails, the test fails.
+``pytest`` internally rewrites the ``assert`` statement to give informative
+output when it fails, so should be preferred over the legacy variant
+``numpy.testing.assert_``. Whereas plain ``assert`` statements are ignored
+when running Python in optimized mode with ``-O``, this is not an issue when
+running tests with pytest.
+
+Similarly, the pytest functions :func:`pytest.raises` and :func:`pytest.warns`
+should be preferred over their legacy counterparts
+:func:`numpy.testing.assert_raises` and :func:`numpy.testing.assert_warns`,
+since the pytest variants are more broadly used and allow more explicit
+targeting of warnings and errors when used with the ``match`` regex.
+
Note that ``test_`` functions or methods should not have a docstring, because
that makes it hard to identify the test from the output of running the test
@@ -185,7 +199,7 @@ Parametric tests
One very nice feature of testing is allowing easy testing across a range
of parameters - a nasty problem for standard unit tests. Use the
-``dec.paramaterize`` decorator.
+``pytest.mark.parametrize`` decorator.
Doctests
--------
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 95865c024..fdb9f926d 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -292,6 +292,7 @@ intersphinx_mapping = {
'skimage': ('https://scikit-image.org/docs/stable', None),
'pandas': ('https://pandas.pydata.org/pandas-docs/stable', None),
'scipy-lecture-notes': ('https://scipy-lectures.org', None),
+ 'pytest': ('https://docs.pytest.org/en/stable', None),
}
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi
index 8565d4b40..f3b331d50 100644
--- a/numpy/__init__.pyi
+++ b/numpy/__init__.pyi
@@ -368,26 +368,58 @@ __git_version__: str
# TODO: Move placeholders to their respective module once
# their annotations are properly implemented
#
-# Placeholders for non-functions (types and other objects)
-DataSource: Type[Any]
-MachAr: Type[Any]
+# Placeholders for classes
+# TODO: Remove the `__getattr__` methods once the classes are stubbed out
+class DataSource:
+ def __getattr__(self, key: str) -> Any: ...
+
+class MachAr:
+ def __getattr__(self, key: str) -> Any: ...
+
+class broadcast:
+ def __getattr__(self, key: str) -> Any: ...
+
+class busdaycalendar:
+ def __getattr__(self, key: str) -> Any: ...
+
+class chararray(ndarray[_ShapeType, _DType_co]):
+ def __getattr__(self, key: str) -> Any: ...
+
+class finfo:
+ def __getattr__(self, key: str) -> Any: ...
+
+class format_parser:
+ def __getattr__(self, key: str) -> Any: ...
+
+class iinfo:
+ def __getattr__(self, key: str) -> Any: ...
+
+class matrix(ndarray[_ShapeType, _DType_co]):
+ def __getattr__(self, key: str) -> Any: ...
+
+class memmap(ndarray[_ShapeType, _DType_co]):
+ def __getattr__(self, key: str) -> Any: ...
+
+class nditer:
+ def __getattr__(self, key: str) -> Any: ...
+
+class poly1d:
+ def __getattr__(self, key: str) -> Any: ...
+
+class recarray(ndarray[_ShapeType, _DType_co]):
+ def __getattr__(self, key: str) -> Any: ...
+
+class record(void):
+ def __getattr__(self, key: str) -> Any: ...
+
+class vectorize:
+ def __getattr__(self, key: str) -> Any: ...
+
+# Placeholders for miscellaneous objects
ScalarType: Tuple[Type[Any], ...]
-broadcast: Type[Any]
-busdaycalendar: Type[Any]
cast: Dict[generic, Callable[..., ndarray[Any, dtype[Any]]]]
-chararray: Type[Any]
-finfo: Type[Any]
-format_parser: Type[Any]
-iinfo: Type[Any]
-matrix: Type[Any]
-memmap: Type[Any]
nbytes: Dict[generic, int]
-nditer: Type[Any]
-poly1d: Type[Any]
-recarray: Type[Any]
-record: Type[Any]
typecodes: Dict[str, str]
-vectorize: Type[Any]
# Placeholders for Python-based functions
def angle(z, deg=...): ...
@@ -540,38 +572,64 @@ def vsplit(ary, indices_or_sections): ...
def who(vardict=...): ...
# Placeholders for C-based functions
-arange: Callable[..., Any]
-bincount: Callable[..., Any]
-busday_count: Callable[..., Any]
-busday_offset: Callable[..., Any]
-can_cast: Callable[..., Any]
-compare_chararrays: Callable[..., Any]
-concatenate: Callable[..., Any]
-copyto: Callable[..., Any]
-datetime_as_string: Callable[..., Any]
-datetime_data: Callable[..., Any]
-dot: Callable[..., Any]
-frombuffer: Callable[..., Any]
-fromfile: Callable[..., Any]
-fromiter: Callable[..., Any]
-frompyfunc: Callable[..., Any]
-fromstring: Callable[..., Any]
-geterrobj: Callable[..., Any]
-inner: Callable[..., Any]
-is_busday: Callable[..., Any]
-lexsort: Callable[..., Any]
-may_share_memory: Callable[..., Any]
-min_scalar_type: Callable[..., Any]
-nested_iters: Callable[..., Any]
-packbits: Callable[..., Any]
-promote_types: Callable[..., Any]
-putmask: Callable[..., Any]
-result_type: Callable[..., Any]
-seterrobj: Callable[..., Any]
-shares_memory: Callable[..., Any]
-unpackbits: Callable[..., Any]
-vdot: Callable[..., Any]
-where: Callable[..., Any]
+# TODO: Sort out which parameters are positional-only
+@overload
+def arange(stop, dtype=..., *, like=...): ...
+@overload
+def arange(start, stop, step, dtype=..., *, like=...): ...
+def bincount(x, weights=..., minlength=...): ...
+def busday_count(
+ begindates,
+ enddates,
+ weekmask=...,
+ holidays=...,
+ busdaycal=...,
+ out=...,
+): ...
+def busday_offset(
+ dates,
+ offsets,
+ roll=...,
+ weekmask=...,
+ holidays=...,
+ busdaycal=...,
+ out=...,
+): ...
+def can_cast(from_, to, casting=...): ...
+def compare_chararrays(a, b, cmp_op, rstrip): ...
+def concatenate(__a, axis=..., out=..., dtype=..., casting=...): ...
+def copyto(dst, src, casting=..., where=...): ...
+def datetime_as_string(arr, unit=..., timezone=..., casting=...): ...
+def datetime_data(__dtype): ...
+def dot(a, b, out=...): ...
+def frombuffer(buffer, dtype=..., count=..., offset=..., *, like=...): ...
+def fromfile(
+ file, dtype=..., count=..., sep=..., offset=..., *, like=...
+): ...
+def fromiter(iter, dtype, count=..., *, like=...): ...
+def frompyfunc(func, nin, nout, * identity): ...
+def fromstring(string, dtype=..., count=..., sep=..., *, like=...): ...
+def geterrobj(): ...
+def inner(a, b): ...
+def is_busday(
+ dates, weekmask=..., holidays=..., busdaycal=..., out=...
+): ...
+def lexsort(keys, axis=...): ...
+def may_share_memory(a, b, max_work=...): ...
+def min_scalar_type(a): ...
+def nested_iters(*args, **kwargs): ... # TODO: Sort out parameters
+def packbits(a, axis=..., bitorder=...): ...
+def promote_types(type1, type2): ...
+def putmask(a, mask, values): ...
+def result_type(*arrays_and_dtypes): ...
+def seterrobj(errobj): ...
+def shares_memory(a, b, max_work=...): ...
+def unpackbits(a, axis=..., count=..., bitorder=...): ...
+def vdot(a, b): ...
+@overload
+def where(__condition): ...
+@overload
+def where(__condition, __x, __y): ...
_NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray)
_DTypeScalar_co = TypeVar("_DTypeScalar_co", covariant=True, bound=generic)
@@ -1375,7 +1433,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]):
def imag(self, value: ArrayLike) -> None: ...
def __new__(
cls: Type[_ArraySelf],
- shape: Sequence[int],
+ shape: _ShapeLike,
dtype: DTypeLike = ...,
buffer: _BufferType = ...,
offset: int = ...,
diff --git a/numpy/fft/__init__.py b/numpy/fft/__init__.py
index a86bb3ac0..fd5e47580 100644
--- a/numpy/fft/__init__.py
+++ b/numpy/fft/__init__.py
@@ -200,9 +200,13 @@ For examples, see the various functions.
"""
+from . import _pocketfft, helper
from ._pocketfft import *
from .helper import *
+__all__ = _pocketfft.__all__.copy()
+__all__ += helper.__all__
+
from numpy._pytesttester import PytestTester
test = PytestTester(__name__)
del PytestTester
diff --git a/numpy/fft/__init__.pyi b/numpy/fft/__init__.pyi
index 45190517f..bb4fae903 100644
--- a/numpy/fft/__init__.pyi
+++ b/numpy/fft/__init__.pyi
@@ -1,4 +1,6 @@
-from typing import Any
+from typing import Any, List
+
+__all__: List[str]
fft: Any
ifft: Any
diff --git a/numpy/linalg/__init__.py b/numpy/linalg/__init__.py
index 3a53ac6ec..93943de38 100644
--- a/numpy/linalg/__init__.py
+++ b/numpy/linalg/__init__.py
@@ -70,8 +70,11 @@ Exceptions
"""
# To get sub-modules
+from . import linalg
from .linalg import *
+__all__ = linalg.__all__.copy()
+
from numpy._pytesttester import PytestTester
test = PytestTester(__name__)
del PytestTester
diff --git a/numpy/linalg/__init__.pyi b/numpy/linalg/__init__.pyi
index ffb05bb81..39b061969 100644
--- a/numpy/linalg/__init__.pyi
+++ b/numpy/linalg/__init__.pyi
@@ -1,4 +1,6 @@
-from typing import Any
+from typing import Any, List
+
+__all__: List[str]
matrix_power: Any
solve: Any
diff --git a/numpy/polynomial/__init__.py b/numpy/polynomial/__init__.py
index d629df29f..4b4361163 100644
--- a/numpy/polynomial/__init__.py
+++ b/numpy/polynomial/__init__.py
@@ -37,13 +37,13 @@ This eliminates the need to navigate to the corresponding submodules, e.g.
The classes provide a more consistent and concise interface than the
type-specific functions defined in the submodules for each type of polynomial.
For example, to fit a Chebyshev polynomial with degree ``1`` to data given
-by arrays ``xdata`` and ``ydata``, the
+by arrays ``xdata`` and ``ydata``, the
`~chebyshev.Chebyshev.fit` class method::
>>> from numpy.polynomial import Chebyshev
>>> c = Chebyshev.fit(xdata, ydata, deg=1)
-is preferred over the `chebyshev.chebfit` function from the
+is preferred over the `chebyshev.chebfit` function from the
``np.polynomial.chebyshev`` module::
>>> from numpy.polynomial.chebyshev import chebfit
@@ -76,7 +76,7 @@ Methods for creating polynomial instances.
- ``Poly.basis(degree)`` -- Basis polynomial of given degree
- ``Poly.identity()`` -- ``p`` where ``p(x) = x`` for all ``x``
-- ``Poly.fit(x, y, deg)`` -- ``p`` of degree ``deg`` with coefficients
+- ``Poly.fit(x, y, deg)`` -- ``p`` of degree ``deg`` with coefficients
determined by the least-squares fit to the data ``x``, ``y``
- ``Poly.fromroots(roots)`` -- ``p`` with specified roots
- ``p.copy()`` -- Create a copy of ``p``
@@ -120,6 +120,16 @@ from .hermite import Hermite
from .hermite_e import HermiteE
from .laguerre import Laguerre
+__all__ = [
+ "set_default_printstyle",
+ "polynomial", "Polynomial",
+ "chebyshev", "Chebyshev",
+ "legendre", "Legendre",
+ "hermite", "Hermite",
+ "hermite_e", "HermiteE",
+ "laguerre", "Laguerre",
+]
+
def set_default_printstyle(style):
"""
diff --git a/numpy/polynomial/__init__.pyi b/numpy/polynomial/__init__.pyi
index 755f7521b..6a7406041 100644
--- a/numpy/polynomial/__init__.pyi
+++ b/numpy/polynomial/__init__.pyi
@@ -1,4 +1,4 @@
-from typing import Any
+from typing import Any, List
from numpy.polynomial import (
chebyshev as chebyshev,
@@ -9,6 +9,8 @@ from numpy.polynomial import (
polynomial as polynomial,
)
+__all__: List[str]
+
Polynomial: Any
Chebyshev: Any
Legendre: Any
diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx
index 17a52a8d5..a68303501 100644
--- a/numpy/random/_generator.pyx
+++ b/numpy/random/_generator.pyx
@@ -4592,7 +4592,7 @@ def default_rng(seed=None):
Examples
--------
- ``default_rng`` is the reccomended constructor for the random number class
+ ``default_rng`` is the recommended constructor for the random number class
``Generator``. Here are several ways we can construct a random
number generator using ``default_rng`` and the ``Generator`` class.
diff --git a/numpy/typing/_shape.py b/numpy/typing/_shape.py
index 4629046ea..b720c3ffc 100644
--- a/numpy/typing/_shape.py
+++ b/numpy/typing/_shape.py
@@ -1,6 +1,15 @@
+import sys
from typing import Sequence, Tuple, Union
+if sys.version_info >= (3, 8):
+ from typing import SupportsIndex
+else:
+ try:
+ from typing_extensions import SupportsIndex
+ except ImportError:
+ SupportsIndex = NotImplemented
+
_Shape = Tuple[int, ...]
# Anything that can be coerced to a shape tuple
-_ShapeLike = Union[int, Sequence[int]]
+_ShapeLike = Union[SupportsIndex, Sequence[SupportsIndex]]
diff --git a/numpy/typing/tests/data/pass/array_constructors.py b/numpy/typing/tests/data/pass/array_constructors.py
index 63208f139..206f70a15 100644
--- a/numpy/typing/tests/data/pass/array_constructors.py
+++ b/numpy/typing/tests/data/pass/array_constructors.py
@@ -1,11 +1,20 @@
+import sys
from typing import List, Any
import numpy as np
+
class Index:
def __index__(self) -> int:
return 0
-class SubClass(np.ndarray): ...
+
+class SubClass(np.ndarray):
+ pass
+
+
+def func(i: int, j: int, **kwargs: Any) -> SubClass:
+ return B
+
i8 = np.int64(1)
@@ -14,8 +23,9 @@ B = A.view(SubClass).copy()
B_stack = np.array([[1], [1]]).view(SubClass)
C = [1]
-def func(i: int, j: int, **kwargs: Any) -> SubClass:
- return B
+if sys.version_info >= (3, 8):
+ np.ndarray(Index())
+ np.ndarray([Index()])
np.array(1, dtype=float)
np.array(1, copy=False)