diff options
author | Ralf Gommers <ralf.gommers@gmail.com> | 2021-03-06 20:54:23 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-06 20:54:23 +0100 |
commit | eff28c4c903d39c9be373434e7e5ef1fdf194a77 (patch) | |
tree | f15e3982c1dc508aa63e9efcfb76648d69f4038e | |
parent | dcf580482569352275acff282fa0548fbc12042e (diff) | |
parent | c6bdbad5458c3b48ee92350fa0b723ee3b98743f (diff) | |
download | numpy-eff28c4c903d39c9be373434e7e5ef1fdf194a77.tar.gz |
Merge pull request #18417 from BvB93/comparison5
ENH: Add dtype-support to the ufunc-based `ndarray` magic methods 4/4
-rw-r--r-- | numpy/__init__.pyi | 204 | ||||
-rw-r--r-- | numpy/typing/tests/data/fail/arithmetic.py | 49 | ||||
-rw-r--r-- | numpy/typing/tests/data/pass/arithmetic.py | 73 | ||||
-rw-r--r-- | numpy/typing/tests/test_typing.py | 29 |
4 files changed, 326 insertions, 29 deletions
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index dba4176f2..9cdc4f2e1 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -15,6 +15,7 @@ from numpy.typing import ( _SupportsArray, _NestedSequence, _RecursiveSequence, + _SupportsArray, _ArrayLikeBool_co, _ArrayLikeUInt_co, _ArrayLikeInt_co, @@ -1640,7 +1641,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): @overload def __mod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] @overload - def __mod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... + def __mod__(self: _ArrayTD64_co, other: _NestedSequence[_SupportsArray[dtype[timedelta64]]]) -> _ArrayOrScalar[timedelta64]: ... @overload def __mod__(self: _ArrayND[object_], other: Any) -> Any: ... @overload @@ -1662,7 +1663,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): @overload def __rmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _ArrayOrScalar[floating[Any]]: ... # type: ignore[misc] @overload - def __rmod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> _ArrayOrScalar[timedelta64]: ... + def __rmod__(self: _ArrayTD64_co, other: _NestedSequence[_SupportsArray[dtype[timedelta64]]]) -> _ArrayOrScalar[timedelta64]: ... @overload def __rmod__(self: _ArrayND[object_], other: Any) -> Any: ... @overload @@ -1684,7 +1685,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): @overload def __divmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _2Tuple[_ArrayOrScalar[floating[Any]]]: ... # type: ignore[misc] @overload - def __divmod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> Union[Tuple[int64, timedelta64], Tuple[_ArrayND[int64], _ArrayND[timedelta64]]]: ... + def __divmod__(self: _ArrayTD64_co, other: _NestedSequence[_SupportsArray[dtype[timedelta64]]]) -> Union[Tuple[int64, timedelta64], Tuple[_ArrayND[int64], _ArrayND[timedelta64]]]: ... @overload def __divmod__( self: _ArrayND[Union[bool_, integer[Any], floating[Any], timedelta64]], @@ -1702,7 +1703,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): @overload def __rdivmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _2Tuple[_ArrayOrScalar[floating[Any]]]: ... # type: ignore[misc] @overload - def __rdivmod__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> Union[Tuple[int64, timedelta64], Tuple[_ArrayND[int64], _ArrayND[timedelta64]]]: ... + def __rdivmod__(self: _ArrayTD64_co, other: _NestedSequence[_SupportsArray[dtype[timedelta64]]]) -> Union[Tuple[int64, timedelta64], Tuple[_ArrayND[int64], _ArrayND[timedelta64]]]: ... @overload def __rdivmod__( self: _ArrayND[Union[bool_, integer[Any], floating[Any], timedelta64]], @@ -2202,18 +2203,189 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]): ) -> Any: ... # `np.generic` does not support inplace operations - def __iadd__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __isub__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __imul__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __itruediv__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __ifloordiv__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __ipow__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __imod__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __ilshift__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __irshift__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __iand__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __ixor__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... - def __ior__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ... + @overload # type: ignore[misc] + def __iadd__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __iadd__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayND[bool_]: ... + @overload + def __iadd__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __iadd__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __iadd__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __iadd__(self: _ArrayND[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> _ArrayND[complexfloating[_NBit1, _NBit1]]: ... + @overload + def __iadd__(self: _ArrayND[timedelta64], other: _ArrayLikeTD64_co) -> _ArrayND[timedelta64]: ... + @overload + def __iadd__(self: _ArrayND[datetime64], other: _ArrayLikeTD64_co) -> _ArrayND[datetime64]: ... + @overload + def __iadd__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __iadd__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __isub__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __isub__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __isub__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __isub__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __isub__(self: _ArrayND[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> _ArrayND[complexfloating[_NBit1, _NBit1]]: ... + @overload + def __isub__(self: _ArrayND[timedelta64], other: _ArrayLikeTD64_co) -> _ArrayND[timedelta64]: ... + @overload + def __isub__(self: _ArrayND[datetime64], other: _ArrayLikeTD64_co) -> _ArrayND[datetime64]: ... + @overload + def __isub__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __isub__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __imul__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __imul__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayND[bool_]: ... + @overload + def __imul__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __imul__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __imul__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __imul__(self: _ArrayND[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> _ArrayND[complexfloating[_NBit1, _NBit1]]: ... + @overload + def __imul__(self: _ArrayND[timedelta64], other: _ArrayLikeFloat_co) -> _ArrayND[timedelta64]: ... + @overload + def __imul__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __imul__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __itruediv__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __itruediv__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __itruediv__(self: _ArrayND[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> _ArrayND[complexfloating[_NBit1, _NBit1]]: ... + @overload + def __itruediv__(self: _ArrayND[timedelta64], other: _ArrayLikeBool_co) -> NoReturn: ... + @overload + def __itruediv__(self: _ArrayND[timedelta64], other: _ArrayLikeInt_co) -> _ArrayND[timedelta64]: ... + @overload + def __itruediv__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __itruediv__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __ifloordiv__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __ifloordiv__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __ifloordiv__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __ifloordiv__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __ifloordiv__(self: _ArrayND[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> _ArrayND[complexfloating[_NBit1, _NBit1]]: ... + @overload + def __ifloordiv__(self: _ArrayND[timedelta64], other: _ArrayLikeBool_co) -> NoReturn: ... + @overload + def __ifloordiv__(self: _ArrayND[timedelta64], other: _ArrayLikeInt_co) -> _ArrayND[timedelta64]: ... + @overload + def __ifloordiv__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __ifloordiv__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __ipow__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __ipow__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __ipow__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __ipow__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __ipow__(self: _ArrayND[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> _ArrayND[complexfloating[_NBit1, _NBit1]]: ... + @overload + def __ipow__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __ipow__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __imod__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __imod__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __imod__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __imod__(self: _ArrayND[floating[_NBit1]], other: _ArrayLikeFloat_co) -> _ArrayND[floating[_NBit1]]: ... + @overload + def __imod__(self: _ArrayND[timedelta64], other: _NestedSequence[_SupportsArray[dtype[timedelta64]]]) -> _ArrayND[timedelta64]: ... + @overload + def __imod__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __imod__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __ilshift__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __ilshift__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __ilshift__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __ilshift__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __ilshift__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __irshift__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __irshift__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __irshift__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __irshift__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __irshift__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __iand__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __iand__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayND[bool_]: ... + @overload + def __iand__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __iand__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __iand__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __iand__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __ixor__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __ixor__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayND[bool_]: ... + @overload + def __ixor__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __ixor__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __ixor__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __ixor__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... + + @overload # type: ignore[misc] + def __ior__(self: _ArrayND[Any], other: _NestedSequence[str | bytes]) -> NoReturn: ... + @overload + def __ior__(self: _ArrayND[bool_], other: _ArrayLikeBool_co) -> _ArrayND[bool_]: ... + @overload + def __ior__(self: _ArrayND[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> _ArrayND[unsignedinteger[_NBit1]]: ... + @overload + def __ior__(self: _ArrayND[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> _ArrayND[signedinteger[_NBit1]]: ... + @overload + def __ior__(self: _ArrayND[object_], other: Any) -> _ArrayND[object_]: ... + @overload + def __ior__(self: _ArrayND[_ScalarType], other: _RecursiveSequence) -> _ArrayND[_ScalarType]: ... # Keep `dtype` at the bottom to avoid name conflicts with `np.dtype` @property diff --git a/numpy/typing/tests/data/fail/arithmetic.py b/numpy/typing/tests/data/fail/arithmetic.py index 1ca8a7b70..02bbffa53 100644 --- a/numpy/typing/tests/data/fail/arithmetic.py +++ b/numpy/typing/tests/data/fail/arithmetic.py @@ -61,13 +61,50 @@ AR_m // AR_LIKE_M # E: Unsupported operand types AR_M // AR_LIKE_M # E: Unsupported operand types _3 = AR_m // AR_LIKE_b # E: Need type annotation -AR_m // AR_LIKE_c # E: Unsupported operand types +AR_m // AR_LIKE_c # E: Unsupported operand types -AR_b // AR_LIKE_m # E: Unsupported operand types -AR_u // AR_LIKE_m # E: Unsupported operand types -AR_i // AR_LIKE_m # E: Unsupported operand types -AR_f // AR_LIKE_m # E: Unsupported operand types -AR_c // AR_LIKE_m # E: Unsupported operand types +AR_b // AR_LIKE_m # E: Unsupported operand types +AR_u // AR_LIKE_m # E: Unsupported operand types +AR_i // AR_LIKE_m # E: Unsupported operand types +AR_f // AR_LIKE_m # E: Unsupported operand types +AR_c // AR_LIKE_m # E: Unsupported operand types + +# Array multiplication + +AR_b *= AR_LIKE_u # E: incompatible type +AR_b *= AR_LIKE_i # E: incompatible type +AR_b *= AR_LIKE_f # E: incompatible type +AR_b *= AR_LIKE_c # E: incompatible type +AR_b *= AR_LIKE_m # E: incompatible type + +AR_u *= AR_LIKE_i # E: incompatible type +AR_u *= AR_LIKE_f # E: incompatible type +AR_u *= AR_LIKE_c # E: incompatible type +AR_u *= AR_LIKE_m # E: incompatible type + +AR_i *= AR_LIKE_f # E: incompatible type +AR_i *= AR_LIKE_c # E: incompatible type +AR_i *= AR_LIKE_m # E: incompatible type + +AR_f *= AR_LIKE_c # E: incompatible type +AR_f *= AR_LIKE_m # E: incompatible type + +# Array power + +AR_b **= AR_LIKE_b # E: incompatible type +AR_b **= AR_LIKE_u # E: incompatible type +AR_b **= AR_LIKE_i # E: incompatible type +AR_b **= AR_LIKE_f # E: incompatible type +AR_b **= AR_LIKE_c # E: incompatible type + +AR_u **= AR_LIKE_i # E: incompatible type +AR_u **= AR_LIKE_f # E: incompatible type +AR_u **= AR_LIKE_c # E: incompatible type + +AR_i **= AR_LIKE_f # E: incompatible type +AR_i **= AR_LIKE_c # E: incompatible type + +AR_f **= AR_LIKE_c # E: incompatible type # Scalars diff --git a/numpy/typing/tests/data/pass/arithmetic.py b/numpy/typing/tests/data/pass/arithmetic.py index 86e7a92a8..7a297cfc5 100644 --- a/numpy/typing/tests/data/pass/arithmetic.py +++ b/numpy/typing/tests/data/pass/arithmetic.py @@ -42,6 +42,18 @@ class Object: def __rfloordiv__(self, value: Any) -> Object: return self + def __mul__(self, value: Any) -> Object: + return self + + def __rmul__(self, value: Any) -> Object: + return self + + def __pow__(self, value: Any) -> Object: + return self + + def __rpow__(self, value: Any) -> Object: + return self + AR_b: np.ndarray[Any, np.dtype[np.bool_]] = np.array([True]) AR_u: np.ndarray[Any, np.dtype[np.uint32]] = np.array([1], dtype=np.uint32) @@ -267,6 +279,67 @@ AR_LIKE_i // AR_O AR_LIKE_f // AR_O AR_LIKE_O // AR_O +# Inplace multiplication + +AR_b *= AR_LIKE_b + +AR_u *= AR_LIKE_b +AR_u *= AR_LIKE_u + +AR_i *= AR_LIKE_b +AR_i *= AR_LIKE_u +AR_i *= AR_LIKE_i + +AR_f *= AR_LIKE_b +AR_f *= AR_LIKE_u +AR_f *= AR_LIKE_i +AR_f *= AR_LIKE_f + +AR_c *= AR_LIKE_b +AR_c *= AR_LIKE_u +AR_c *= AR_LIKE_i +AR_c *= AR_LIKE_f +AR_c *= AR_LIKE_c + +AR_m *= AR_LIKE_b +AR_m *= AR_LIKE_u +AR_m *= AR_LIKE_i +AR_m *= AR_LIKE_f + +AR_O *= AR_LIKE_b +AR_O *= AR_LIKE_u +AR_O *= AR_LIKE_i +AR_O *= AR_LIKE_f +AR_O *= AR_LIKE_c +AR_O *= AR_LIKE_O + +# Inplace power + +AR_u **= AR_LIKE_b +AR_u **= AR_LIKE_u + +AR_i **= AR_LIKE_b +AR_i **= AR_LIKE_u +AR_i **= AR_LIKE_i + +AR_f **= AR_LIKE_b +AR_f **= AR_LIKE_u +AR_f **= AR_LIKE_i +AR_f **= AR_LIKE_f + +AR_c **= AR_LIKE_b +AR_c **= AR_LIKE_u +AR_c **= AR_LIKE_i +AR_c **= AR_LIKE_f +AR_c **= AR_LIKE_c + +AR_O **= AR_LIKE_b +AR_O **= AR_LIKE_u +AR_O **= AR_LIKE_i +AR_O **= AR_LIKE_f +AR_O **= AR_LIKE_c +AR_O **= AR_LIKE_O + # unary ops -c16 diff --git a/numpy/typing/tests/test_typing.py b/numpy/typing/tests/test_typing.py index 70355dcd9..be08c1359 100644 --- a/numpy/typing/tests/test_typing.py +++ b/numpy/typing/tests/test_typing.py @@ -40,6 +40,12 @@ def _key_func(key: str) -> str: return os.path.join(drive, tail.split(":", 1)[0]) +def _strip_filename(msg: str) -> str: + """Strip the filename from a mypy message.""" + _, tail = os.path.splitdrive(msg) + return tail.split(":", 1)[-1] + + @pytest.mark.slow @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed") @pytest.fixture(scope="module", autouse=True) @@ -57,14 +63,17 @@ def run_mypy() -> None: for directory in (PASS_DIR, REVEAL_DIR, FAIL_DIR, MISC_DIR): # Run mypy - stdout, stderr, _ = api.run([ + stdout, stderr, exit_code = api.run([ "--config-file", MYPY_INI, "--cache-dir", CACHE_DIR, directory, ]) - assert not stderr, directory + if stderr: + pytest.fail(f"Unexpected mypy standard error\n\n{stderr}") + elif exit_code not in {0, 1}: + pytest.fail(f"Unexpected mypy exit code: {exit_code}\n\n{stdout}") stdout = stdout.replace('*', '') # Parse the output @@ -94,7 +103,9 @@ def test_success(path): # Alias `OUTPUT_MYPY` so that it appears in the local namespace output_mypy = OUTPUT_MYPY if path in output_mypy: - raise AssertionError("\n".join(v for v in output_mypy[path])) + msg = "Unexpected mypy output\n\n" + msg += "\n".join(_strip_filename(v) for v in output_mypy[path]) + raise AssertionError(msg) @pytest.mark.slow @@ -111,14 +122,15 @@ def test_fail(path): output_mypy = OUTPUT_MYPY assert path in output_mypy for error_line in output_mypy[path]: + error_line = _strip_filename(error_line) match = re.match( - r"^.+\.py:(?P<lineno>\d+): (error|note): .+$", + r"(?P<lineno>\d+): (error|note): .+$", error_line, ) if match is None: raise ValueError(f"Unexpected error line format: {error_line}") lineno = int(match.group('lineno')) - errors[lineno] += error_line + errors[lineno] += f'{error_line}\n' for i, line in enumerate(lines): lineno = i + 1 @@ -131,7 +143,7 @@ def test_fail(path): expected_error = errors.get(lineno) _test_fail(path, marker, expected_error, lineno) else: - pytest.fail(f"Error {repr(errors[lineno])} not found") + pytest.fail(f"Unexpected mypy output\n\n{errors[lineno]}") _FAIL_MSG1 = """Extra error at line {} @@ -250,8 +262,9 @@ def test_reveal(path): output_mypy = OUTPUT_MYPY assert path in output_mypy for error_line in output_mypy[path]: + error_line = _strip_filename(error_line) match = re.match( - r"^.+\.py:(?P<lineno>\d+): note: .+$", + r"(?P<lineno>\d+): note: .+$", error_line, ) if match is None: @@ -311,6 +324,8 @@ def test_extended_precision() -> None: for _msg in output_mypy[path]: *_, _lineno, msg_typ, msg = _msg.split(":") + + msg = _strip_filename(msg) lineno = int(_lineno) msg_typ = msg_typ.strip() assert msg_typ in {"error", "note"} |