Skip to content

Commit

Permalink
TST: Make pass <3.11
Browse files Browse the repository at this point in the history
On older snakes, was previously assigning Array = NDArray.  However,
that was causing unexpected errors in testing the shape311.py files.
Had to extend numpy.typing.Array to <3.11 using typing_extensions, as
well as quoting some type hints in the test files for delayed
evaluation.

Alternatively, I could have found a way to limit the parameterization
of test_fail and test_runs for just >= 3.11.  However, IDK how to do
that in pytest.
  • Loading branch information
Jacob-Stevens-Haas committed May 7, 2024
1 parent 8f8a973 commit 742153f
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 32 deletions.
4 changes: 2 additions & 2 deletions doc/release/upcoming_changes/26081.improvement.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ This PR also provides the ``np.typing.Array`` type alias in the style of

.. code::
from typing import Literal, TypeVar, TypeVarTuple
from typing import Literal, TypeVar
import numpy as np
import numpy.typing as npt
Expand All @@ -51,14 +51,14 @@ This PR also provides the ``np.typing.Array`` type alias in the style of
arr = np.arange(12, dtype=np.uint16)
stacked = stack_1Ds(arr, arr, arr)
reveal_type(stacked) #
Note that, if shape is unknown or arbitrary, it is still recommended to use
``NDArray``. Because ``TypeVarTuple`` cannot be bound, not all type checkers
allow arbitrarily shape arrays. e.g.:

.. code::
from typing import TypeVarTuple
Shapes = TypeVarTuple("Shapes")
Expand Down
6 changes: 3 additions & 3 deletions numpy/_typing/_add_docstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ def _parse_docstrings() -> str:
Can be used during runtime for typing arrays with a given dtype
and specified shape. Particularly useful for functions which modify number
of axes. If it is important to enforce integer axis sizes, use np.ndarray
for typing. If axes dimensions are variable, it is best to use
`npt.NDArray <numpy.typing.NDArray>`.
of axes. If it is important to enforce integer axis sizes, use
`np.ndarray <numpy.ndarray>` for typing. If axes dimensions are
variable, it is best to use `npt.NDArray <numpy.typing.NDArray>`.
.. versionadded:: 2.1
Expand Down
6 changes: 3 additions & 3 deletions numpy/_typing/_array_like.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
)
if sys.version_info >= (3, 11):
from typing import TypeVarTuple, Unpack
else:
from typing_extensions import TypeVarTuple, Unpack

import numpy as np
from numpy import (
Expand Down Expand Up @@ -39,11 +41,9 @@
_DType_co = TypeVar("_DType_co", covariant=True, bound=dtype[Any])

NDArray = ndarray[Any, dtype[_ScalarType_co]]
if TYPE_CHECKING or sys.version_info >= (3, 11):
if TYPE_CHECKING:
_ShapeTypeTuple = TypeVarTuple("_ShapeTypeTuple")
Array = ndarray[tuple[Unpack[_ShapeTypeTuple]], dtype[_ScalarType_co]]
else:
Array = NDArray

# The `_SupportsArray` protocol only cares about the default dtype
# (i.e. `dtype=None` or no `dtype` parameter at all) of the to-be returned
Expand Down
6 changes: 4 additions & 2 deletions numpy/typing/tests/data/fail/shape311.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
import numpy as np
import numpy.typing as npt

if sys.version_info >= (3, 11):
npt.Array[str, str, np.float64] # E: Value of type variable
from typing_extensions import assert_type

# Fails for different reason with same syntax < 3.11
npt.Array[str, str, np.float64] # E: Value of type variable
44 changes: 22 additions & 22 deletions numpy/typing/tests/data/pass/shape311.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import sys
from typing import Literal, NewType, TypeVar, TypeVarTuple
from typing import NewType, TypeVar

import numpy as np
import numpy.typing as npt
from typing_extensions import assert_type, cast, reveal_type
from typing_extensions import assert_type

if sys.version_info >= (3, 11):
DType = TypeVar("DType", bound=np.generic)
# if sys.version_info >= (3, 11):
DType = TypeVar("DType", bound=np.generic)

# Check that typevartuple in alias is packed correctly
Length = NewType("Length", int)
Width = NewType("Width", int)
arr: npt.Array[Length, Width, np.int8] = np.array([[0]])
assert_type(arr, np.ndarray[tuple[Length, Width], np.dtype[np.int8]])
# Check that typevartuple in alias is packed correctly
Length = NewType("Length", int)
Width = NewType("Width", int)
arr: "npt.Array[Length, Width, np.int8]" = np.array([[0]])
assert_type(arr, np.ndarray[tuple[Length, Width], np.dtype[np.int8]])

# Check that typevartuple in alias is unpacked correctly
M = TypeVar("M", bound=int)
N = TypeVar("N", bound=int)
T = TypeVar("T", bound=np.generic)
# Check that typevartuple in alias is unpacked correctly
M = TypeVar("M", bound=int)
N = TypeVar("N", bound=int)
T = TypeVar("T", bound=np.generic)


def mult(vec: npt.Array[N, T], mat: npt.Array[M, N, T]) -> npt.Array[M, T]:
return mat @ vec # type: ignore
def mult(vec: "npt.Array[N, T]", mat: "npt.Array[M, N, T]") -> "npt.Array[M, T]":
return mat @ vec # type: ignore


arr2: np.ndarray[tuple[Width], np.dtype[np.int8]] = np.array([0])
assert_type(mult(arr2, arr), np.ndarray[tuple[Length], np.dtype[np.int8]])
arr2: np.ndarray[tuple[Width], np.dtype[np.int8]] = np.array([0])
assert_type(mult(arr2, arr), np.ndarray[tuple[Length], np.dtype[np.int8]])


# Check that shape works
def return_shp(a: npt.Array[M, N, DType]) -> tuple[M, N]:
return a.shape
# Check that shape works
def return_shp(a: "npt.Array[M, N, DType]") -> tuple[M, N]:
return a.shape

shp = return_shp(arr)
assert_type(shp, tuple[Length, Width])
shp = return_shp(arr)
assert_type(shp, tuple[Length, Width])

0 comments on commit 742153f

Please sign in to comment.