summaryrefslogtreecommitdiff
path: root/numpy/_typing
diff options
context:
space:
mode:
authorBas van Beek <43369155+BvB93@users.noreply.github.com>2022-03-18 17:09:56 +0100
committerBas van Beek <43369155+BvB93@users.noreply.github.com>2022-03-18 18:29:54 +0100
commit7739583f5fb39c31e83010a3153fa078004e55eb (patch)
tree23435d5de3f1870bc664354d50524b7166c2587a /numpy/_typing
parenta8f9711493adee93fa3d61e7ef1bee11d7055a85 (diff)
downloadnumpy-7739583f5fb39c31e83010a3153fa078004e55eb.tar.gz
MAINT: Split `numpy.typing` into a public and private component
i.e. `numpy.typing` and `numpy._typing`
Diffstat (limited to 'numpy/_typing')
-rw-r--r--numpy/_typing/__init__.py218
-rw-r--r--numpy/_typing/_add_docstring.py152
-rw-r--r--numpy/_typing/_array_like.py143
-rw-r--r--numpy/_typing/_callable.pyi325
-rw-r--r--numpy/_typing/_char_codes.py111
-rw-r--r--numpy/_typing/_dtype_like.py247
-rw-r--r--numpy/_typing/_extended_precision.py43
-rw-r--r--numpy/_typing/_generic_alias.py209
-rw-r--r--numpy/_typing/_nbit.py16
-rw-r--r--numpy/_typing/_nested_sequence.py90
-rw-r--r--numpy/_typing/_scalars.py30
-rw-r--r--numpy/_typing/_shape.py6
-rw-r--r--numpy/_typing/_ufunc.pyi403
-rw-r--r--numpy/_typing/setup.py10
14 files changed, 2003 insertions, 0 deletions
diff --git a/numpy/_typing/__init__.py b/numpy/_typing/__init__.py
new file mode 100644
index 000000000..950905e52
--- /dev/null
+++ b/numpy/_typing/__init__.py
@@ -0,0 +1,218 @@
+"""Private counterpart of ``numpy.typing``."""
+
+from __future__ import annotations
+
+from numpy import ufunc
+from numpy.core.overrides import set_module
+from typing import TYPE_CHECKING, final
+
+
+@final # Disallow the creation of arbitrary `NBitBase` subclasses
+@set_module("numpy.typing")
+class NBitBase:
+ """
+ A type representing `numpy.number` precision during static type checking.
+
+ Used exclusively for the purpose static type checking, `NBitBase`
+ represents the base of a hierarchical set of subclasses.
+ Each subsequent subclass is herein used for representing a lower level
+ of precision, *e.g.* ``64Bit > 32Bit > 16Bit``.
+
+ .. versionadded:: 1.20
+
+ Examples
+ --------
+ Below is a typical usage example: `NBitBase` is herein used for annotating
+ a function that takes a float and integer of arbitrary precision
+ as arguments and returns a new float of whichever precision is largest
+ (*e.g.* ``np.float16 + np.int64 -> np.float64``).
+
+ .. code-block:: python
+
+ >>> from __future__ import annotations
+ >>> from typing import TypeVar, TYPE_CHECKING
+ >>> import numpy as np
+ >>> import numpy.typing as npt
+
+ >>> T1 = TypeVar("T1", bound=npt.NBitBase)
+ >>> T2 = TypeVar("T2", bound=npt.NBitBase)
+
+ >>> def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[T1 | T2]:
+ ... return a + b
+
+ >>> a = np.float16()
+ >>> b = np.int64()
+ >>> out = add(a, b)
+
+ >>> if TYPE_CHECKING:
+ ... reveal_locals()
+ ... # note: Revealed local types are:
+ ... # note: a: numpy.floating[numpy.typing._16Bit*]
+ ... # note: b: numpy.signedinteger[numpy.typing._64Bit*]
+ ... # note: out: numpy.floating[numpy.typing._64Bit*]
+
+ """
+
+ def __init_subclass__(cls) -> None:
+ allowed_names = {
+ "NBitBase", "_256Bit", "_128Bit", "_96Bit", "_80Bit",
+ "_64Bit", "_32Bit", "_16Bit", "_8Bit",
+ }
+ if cls.__name__ not in allowed_names:
+ raise TypeError('cannot inherit from final class "NBitBase"')
+ super().__init_subclass__()
+
+
+# Silence errors about subclassing a `@final`-decorated class
+class _256Bit(NBitBase): # type: ignore[misc]
+ pass
+
+class _128Bit(_256Bit): # type: ignore[misc]
+ pass
+
+class _96Bit(_128Bit): # type: ignore[misc]
+ pass
+
+class _80Bit(_96Bit): # type: ignore[misc]
+ pass
+
+class _64Bit(_80Bit): # type: ignore[misc]
+ pass
+
+class _32Bit(_64Bit): # type: ignore[misc]
+ pass
+
+class _16Bit(_32Bit): # type: ignore[misc]
+ pass
+
+class _8Bit(_16Bit): # type: ignore[misc]
+ pass
+
+
+from ._nested_sequence import _NestedSequence
+from ._nbit import (
+ _NBitByte,
+ _NBitShort,
+ _NBitIntC,
+ _NBitIntP,
+ _NBitInt,
+ _NBitLongLong,
+ _NBitHalf,
+ _NBitSingle,
+ _NBitDouble,
+ _NBitLongDouble,
+)
+from ._char_codes import (
+ _BoolCodes,
+ _UInt8Codes,
+ _UInt16Codes,
+ _UInt32Codes,
+ _UInt64Codes,
+ _Int8Codes,
+ _Int16Codes,
+ _Int32Codes,
+ _Int64Codes,
+ _Float16Codes,
+ _Float32Codes,
+ _Float64Codes,
+ _Complex64Codes,
+ _Complex128Codes,
+ _ByteCodes,
+ _ShortCodes,
+ _IntCCodes,
+ _IntPCodes,
+ _IntCodes,
+ _LongLongCodes,
+ _UByteCodes,
+ _UShortCodes,
+ _UIntCCodes,
+ _UIntPCodes,
+ _UIntCodes,
+ _ULongLongCodes,
+ _HalfCodes,
+ _SingleCodes,
+ _DoubleCodes,
+ _LongDoubleCodes,
+ _CSingleCodes,
+ _CDoubleCodes,
+ _CLongDoubleCodes,
+ _DT64Codes,
+ _TD64Codes,
+ _StrCodes,
+ _BytesCodes,
+ _VoidCodes,
+ _ObjectCodes,
+)
+from ._scalars import (
+ _CharLike_co,
+ _BoolLike_co,
+ _UIntLike_co,
+ _IntLike_co,
+ _FloatLike_co,
+ _ComplexLike_co,
+ _TD64Like_co,
+ _NumberLike_co,
+ _ScalarLike_co,
+ _VoidLike_co,
+)
+from ._shape import _Shape, _ShapeLike
+from ._dtype_like import (
+ DTypeLike as DTypeLike,
+ _DTypeLike,
+ _SupportsDType,
+ _VoidDTypeLike,
+ _DTypeLikeBool,
+ _DTypeLikeUInt,
+ _DTypeLikeInt,
+ _DTypeLikeFloat,
+ _DTypeLikeComplex,
+ _DTypeLikeTD64,
+ _DTypeLikeDT64,
+ _DTypeLikeObject,
+ _DTypeLikeVoid,
+ _DTypeLikeStr,
+ _DTypeLikeBytes,
+ _DTypeLikeComplex_co,
+)
+from ._array_like import (
+ ArrayLike as ArrayLike,
+ _ArrayLike,
+ _FiniteNestedSequence,
+ _SupportsArray,
+ _SupportsArrayFunc,
+ _ArrayLikeInt,
+ _ArrayLikeBool_co,
+ _ArrayLikeUInt_co,
+ _ArrayLikeInt_co,
+ _ArrayLikeFloat_co,
+ _ArrayLikeComplex_co,
+ _ArrayLikeNumber_co,
+ _ArrayLikeTD64_co,
+ _ArrayLikeDT64_co,
+ _ArrayLikeObject_co,
+ _ArrayLikeVoid_co,
+ _ArrayLikeStr_co,
+ _ArrayLikeBytes_co,
+)
+from ._generic_alias import (
+ NDArray as NDArray,
+ _DType,
+ _GenericAlias,
+)
+
+if TYPE_CHECKING:
+ from ._ufunc import (
+ _UFunc_Nin1_Nout1,
+ _UFunc_Nin2_Nout1,
+ _UFunc_Nin1_Nout2,
+ _UFunc_Nin2_Nout2,
+ _GUFunc_Nin2_Nout1,
+ )
+else:
+ # Declare the (type-check-only) ufunc subclasses as ufunc aliases during
+ # runtime; this helps autocompletion tools such as Jedi (numpy/numpy#19834)
+ _UFunc_Nin1_Nout1 = ufunc
+ _UFunc_Nin2_Nout1 = ufunc
+ _UFunc_Nin1_Nout2 = ufunc
+ _UFunc_Nin2_Nout2 = ufunc
+ _GUFunc_Nin2_Nout1 = ufunc
diff --git a/numpy/_typing/_add_docstring.py b/numpy/_typing/_add_docstring.py
new file mode 100644
index 000000000..10d77f516
--- /dev/null
+++ b/numpy/_typing/_add_docstring.py
@@ -0,0 +1,152 @@
+"""A module for creating docstrings for sphinx ``data`` domains."""
+
+import re
+import textwrap
+
+from ._generic_alias import NDArray
+
+_docstrings_list = []
+
+
+def add_newdoc(name: str, value: str, doc: str) -> None:
+ """Append ``_docstrings_list`` with a docstring for `name`.
+
+ Parameters
+ ----------
+ name : str
+ The name of the object.
+ value : str
+ A string-representation of the object.
+ doc : str
+ The docstring of the object.
+
+ """
+ _docstrings_list.append((name, value, doc))
+
+
+def _parse_docstrings() -> str:
+ """Convert all docstrings in ``_docstrings_list`` into a single
+ sphinx-legible text block.
+
+ """
+ type_list_ret = []
+ for name, value, doc in _docstrings_list:
+ s = textwrap.dedent(doc).replace("\n", "\n ")
+
+ # Replace sections by rubrics
+ lines = s.split("\n")
+ new_lines = []
+ indent = ""
+ for line in lines:
+ m = re.match(r'^(\s+)[-=]+\s*$', line)
+ if m and new_lines:
+ prev = textwrap.dedent(new_lines.pop())
+ if prev == "Examples":
+ indent = ""
+ new_lines.append(f'{m.group(1)}.. rubric:: {prev}')
+ else:
+ indent = 4 * " "
+ new_lines.append(f'{m.group(1)}.. admonition:: {prev}')
+ new_lines.append("")
+ else:
+ new_lines.append(f"{indent}{line}")
+
+ s = "\n".join(new_lines)
+ s_block = f""".. data:: {name}\n :value: {value}\n {s}"""
+ type_list_ret.append(s_block)
+ return "\n".join(type_list_ret)
+
+
+add_newdoc('ArrayLike', 'typing.Union[...]',
+ """
+ A `~typing.Union` representing objects that can be coerced
+ into an `~numpy.ndarray`.
+
+ Among others this includes the likes of:
+
+ * Scalars.
+ * (Nested) sequences.
+ * Objects implementing the `~class.__array__` protocol.
+
+ .. versionadded:: 1.20
+
+ See Also
+ --------
+ :term:`array_like`:
+ Any scalar or sequence that can be interpreted as an ndarray.
+
+ Examples
+ --------
+ .. code-block:: python
+
+ >>> import numpy as np
+ >>> import numpy.typing as npt
+
+ >>> def as_array(a: npt.ArrayLike) -> np.ndarray:
+ ... return np.array(a)
+
+ """)
+
+add_newdoc('DTypeLike', 'typing.Union[...]',
+ """
+ A `~typing.Union` representing objects that can be coerced
+ into a `~numpy.dtype`.
+
+ Among others this includes the likes of:
+
+ * :class:`type` objects.
+ * Character codes or the names of :class:`type` objects.
+ * Objects with the ``.dtype`` attribute.
+
+ .. versionadded:: 1.20
+
+ See Also
+ --------
+ :ref:`Specifying and constructing data types <arrays.dtypes.constructing>`
+ A comprehensive overview of all objects that can be coerced
+ into data types.
+
+ Examples
+ --------
+ .. code-block:: python
+
+ >>> import numpy as np
+ >>> import numpy.typing as npt
+
+ >>> def as_dtype(d: npt.DTypeLike) -> np.dtype:
+ ... return np.dtype(d)
+
+ """)
+
+add_newdoc('NDArray', repr(NDArray),
+ """
+ A :term:`generic <generic type>` version of
+ `np.ndarray[Any, np.dtype[+ScalarType]] <numpy.ndarray>`.
+
+ Can be used during runtime for typing arrays with a given dtype
+ and unspecified shape.
+
+ .. versionadded:: 1.21
+
+ Examples
+ --------
+ .. code-block:: python
+
+ >>> import numpy as np
+ >>> import numpy.typing as npt
+
+ >>> print(npt.NDArray)
+ numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]
+
+ >>> print(npt.NDArray[np.float64])
+ numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]
+
+ >>> NDArrayInt = npt.NDArray[np.int_]
+ >>> a: NDArrayInt = np.arange(10)
+
+ >>> def func(a: npt.ArrayLike) -> npt.NDArray[Any]:
+ ... return np.array(a)
+
+ """)
+
+_docstrings = _parse_docstrings()
diff --git a/numpy/_typing/_array_like.py b/numpy/_typing/_array_like.py
new file mode 100644
index 000000000..02f264222
--- /dev/null
+++ b/numpy/_typing/_array_like.py
@@ -0,0 +1,143 @@
+from __future__ import annotations
+
+# NOTE: Import `Sequence` from `typing` as we it is needed for a type-alias,
+# not an annotation
+from collections.abc import Collection, Callable
+from typing import Any, Sequence, Protocol, Union, TypeVar
+from numpy import (
+ ndarray,
+ dtype,
+ generic,
+ bool_,
+ unsignedinteger,
+ integer,
+ floating,
+ complexfloating,
+ number,
+ timedelta64,
+ datetime64,
+ object_,
+ void,
+ str_,
+ bytes_,
+)
+from ._nested_sequence import _NestedSequence
+
+_T = TypeVar("_T")
+_ScalarType = TypeVar("_ScalarType", bound=generic)
+_DType = TypeVar("_DType", bound="dtype[Any]")
+_DType_co = TypeVar("_DType_co", covariant=True, bound="dtype[Any]")
+
+# The `_SupportsArray` protocol only cares about the default dtype
+# (i.e. `dtype=None` or no `dtype` parameter at all) of the to-be returned
+# array.
+# Concrete implementations of the protocol are responsible for adding
+# any and all remaining overloads
+class _SupportsArray(Protocol[_DType_co]):
+ def __array__(self) -> ndarray[Any, _DType_co]: ...
+
+
+class _SupportsArrayFunc(Protocol):
+ """A protocol class representing `~class.__array_function__`."""
+ def __array_function__(
+ self,
+ func: Callable[..., Any],
+ types: Collection[type[Any]],
+ args: tuple[Any, ...],
+ kwargs: dict[str, Any],
+ ) -> object: ...
+
+
+# TODO: Wait until mypy supports recursive objects in combination with typevars
+_FiniteNestedSequence = Union[
+ _T,
+ Sequence[_T],
+ Sequence[Sequence[_T]],
+ Sequence[Sequence[Sequence[_T]]],
+ Sequence[Sequence[Sequence[Sequence[_T]]]],
+]
+
+# A subset of `npt.ArrayLike` that can be parametrized w.r.t. `np.generic`
+_ArrayLike = Union[
+ _SupportsArray["dtype[_ScalarType]"],
+ _NestedSequence[_SupportsArray["dtype[_ScalarType]"]],
+]
+
+# A union representing array-like objects; consists of two typevars:
+# One representing types that can be parametrized w.r.t. `np.dtype`
+# and another one for the rest
+_DualArrayLike = Union[
+ _SupportsArray[_DType],
+ _NestedSequence[_SupportsArray[_DType]],
+ _T,
+ _NestedSequence[_T],
+]
+
+# TODO: support buffer protocols once
+#
+# https://bugs.python.org/issue27501
+#
+# is resolved. See also the mypy issue:
+#
+# https://github.com/python/typing/issues/593
+ArrayLike = _DualArrayLike[
+ dtype,
+ Union[bool, int, float, complex, str, bytes],
+]
+
+# `ArrayLike<X>_co`: array-like objects that can be coerced into `X`
+# given the casting rules `same_kind`
+_ArrayLikeBool_co = _DualArrayLike[
+ "dtype[bool_]",
+ bool,
+]
+_ArrayLikeUInt_co = _DualArrayLike[
+ "dtype[Union[bool_, unsignedinteger[Any]]]",
+ bool,
+]
+_ArrayLikeInt_co = _DualArrayLike[
+ "dtype[Union[bool_, integer[Any]]]",
+ Union[bool, int],
+]
+_ArrayLikeFloat_co = _DualArrayLike[
+ "dtype[Union[bool_, integer[Any], floating[Any]]]",
+ Union[bool, int, float],
+]
+_ArrayLikeComplex_co = _DualArrayLike[
+ "dtype[Union[bool_, integer[Any], floating[Any], complexfloating[Any, Any]]]",
+ Union[bool, int, float, complex],
+]
+_ArrayLikeNumber_co = _DualArrayLike[
+ "dtype[Union[bool_, number[Any]]]",
+ Union[bool, int, float, complex],
+]
+_ArrayLikeTD64_co = _DualArrayLike[
+ "dtype[Union[bool_, integer[Any], timedelta64]]",
+ Union[bool, int],
+]
+_ArrayLikeDT64_co = Union[
+ _SupportsArray["dtype[datetime64]"],
+ _NestedSequence[_SupportsArray["dtype[datetime64]"]],
+]
+_ArrayLikeObject_co = Union[
+ _SupportsArray["dtype[object_]"],
+ _NestedSequence[_SupportsArray["dtype[object_]"]],
+]
+
+_ArrayLikeVoid_co = Union[
+ _SupportsArray["dtype[void]"],
+ _NestedSequence[_SupportsArray["dtype[void]"]],
+]
+_ArrayLikeStr_co = _DualArrayLike[
+ "dtype[str_]",
+ str,
+]
+_ArrayLikeBytes_co = _DualArrayLike[
+ "dtype[bytes_]",
+ bytes,
+]
+
+_ArrayLikeInt = _DualArrayLike[
+ "dtype[integer[Any]]",
+ int,
+]
diff --git a/numpy/_typing/_callable.pyi b/numpy/_typing/_callable.pyi
new file mode 100644
index 000000000..6d7136592
--- /dev/null
+++ b/numpy/_typing/_callable.pyi
@@ -0,0 +1,325 @@
+"""
+A module with various ``typing.Protocol`` subclasses that implement
+the ``__call__`` magic method.
+
+See the `Mypy documentation`_ on protocols for more details.
+
+.. _`Mypy documentation`: https://mypy.readthedocs.io/en/stable/protocols.html#callback-protocols
+
+"""
+
+from __future__ import annotations
+
+from typing import (
+ TypeVar,
+ overload,
+ Any,
+ NoReturn,
+ Protocol,
+)
+
+from numpy import (
+ ndarray,
+ dtype,
+ generic,
+ bool_,
+ timedelta64,
+ number,
+ integer,
+ unsignedinteger,
+ signedinteger,
+ int8,
+ int_,
+ floating,
+ float64,
+ complexfloating,
+ complex128,
+)
+from ._nbit import _NBitInt, _NBitDouble
+from ._scalars import (
+ _BoolLike_co,
+ _IntLike_co,
+ _FloatLike_co,
+ _NumberLike_co,
+)
+from . import NBitBase
+from ._generic_alias import NDArray
+
+_T1 = TypeVar("_T1")
+_T2 = TypeVar("_T2")
+_T1_contra = TypeVar("_T1_contra", contravariant=True)
+_T2_contra = TypeVar("_T2_contra", contravariant=True)
+_2Tuple = tuple[_T1, _T1]
+
+_NBit1 = TypeVar("_NBit1", bound=NBitBase)
+_NBit2 = TypeVar("_NBit2", bound=NBitBase)
+
+_IntType = TypeVar("_IntType", bound=integer)
+_FloatType = TypeVar("_FloatType", bound=floating)
+_NumberType = TypeVar("_NumberType", bound=number)
+_NumberType_co = TypeVar("_NumberType_co", covariant=True, bound=number)
+_GenericType_co = TypeVar("_GenericType_co", covariant=True, bound=generic)
+
+class _BoolOp(Protocol[_GenericType_co]):
+ @overload
+ def __call__(self, other: _BoolLike_co, /) -> _GenericType_co: ...
+ @overload # platform dependent
+ def __call__(self, other: int, /) -> int_: ...
+ @overload
+ def __call__(self, other: float, /) -> float64: ...
+ @overload
+ def __call__(self, other: complex, /) -> complex128: ...
+ @overload
+ def __call__(self, other: _NumberType, /) -> _NumberType: ...
+
+class _BoolBitOp(Protocol[_GenericType_co]):
+ @overload
+ def __call__(self, other: _BoolLike_co, /) -> _GenericType_co: ...
+ @overload # platform dependent
+ def __call__(self, other: int, /) -> int_: ...
+ @overload
+ def __call__(self, other: _IntType, /) -> _IntType: ...
+
+class _BoolSub(Protocol):
+ # Note that `other: bool_` is absent here
+ @overload
+ def __call__(self, other: bool, /) -> NoReturn: ...
+ @overload # platform dependent
+ def __call__(self, other: int, /) -> int_: ...
+ @overload
+ def __call__(self, other: float, /) -> float64: ...
+ @overload
+ def __call__(self, other: complex, /) -> complex128: ...
+ @overload
+ def __call__(self, other: _NumberType, /) -> _NumberType: ...
+
+class _BoolTrueDiv(Protocol):
+ @overload
+ def __call__(self, other: float | _IntLike_co, /) -> float64: ...
+ @overload
+ def __call__(self, other: complex, /) -> complex128: ...
+ @overload
+ def __call__(self, other: _NumberType, /) -> _NumberType: ...
+
+class _BoolMod(Protocol):
+ @overload
+ def __call__(self, other: _BoolLike_co, /) -> int8: ...
+ @overload # platform dependent
+ def __call__(self, other: int, /) -> int_: ...
+ @overload
+ def __call__(self, other: float, /) -> float64: ...
+ @overload
+ def __call__(self, other: _IntType, /) -> _IntType: ...
+ @overload
+ def __call__(self, other: _FloatType, /) -> _FloatType: ...
+
+class _BoolDivMod(Protocol):
+ @overload
+ def __call__(self, other: _BoolLike_co, /) -> _2Tuple[int8]: ...
+ @overload # platform dependent
+ def __call__(self, other: int, /) -> _2Tuple[int_]: ...
+ @overload
+ def __call__(self, other: float, /) -> _2Tuple[floating[_NBit1 | _NBitDouble]]: ...
+ @overload
+ def __call__(self, other: _IntType, /) -> _2Tuple[_IntType]: ...
+ @overload
+ def __call__(self, other: _FloatType, /) -> _2Tuple[_FloatType]: ...
+
+class _TD64Div(Protocol[_NumberType_co]):
+ @overload
+ def __call__(self, other: timedelta64, /) -> _NumberType_co: ...
+ @overload
+ def __call__(self, other: _BoolLike_co, /) -> NoReturn: ...
+ @overload
+ def __call__(self, other: _FloatLike_co, /) -> timedelta64: ...
+
+class _IntTrueDiv(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> floating[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> floating[_NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: complex, /,
+ ) -> complexfloating[_NBit1 | _NBitDouble, _NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(self, other: integer[_NBit2], /) -> floating[_NBit1 | _NBit2]: ...
+
+class _UnsignedIntOp(Protocol[_NBit1]):
+ # NOTE: `uint64 + signedinteger -> float64`
+ @overload
+ def __call__(self, other: bool, /) -> unsignedinteger[_NBit1]: ...
+ @overload
+ def __call__(
+ self, other: int | signedinteger[Any], /
+ ) -> Any: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: complex, /,
+ ) -> complexfloating[_NBit1 | _NBitDouble, _NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: unsignedinteger[_NBit2], /
+ ) -> unsignedinteger[_NBit1 | _NBit2]: ...
+
+class _UnsignedIntBitOp(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> unsignedinteger[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> signedinteger[Any]: ...
+ @overload
+ def __call__(self, other: signedinteger[Any], /) -> signedinteger[Any]: ...
+ @overload
+ def __call__(
+ self, other: unsignedinteger[_NBit2], /
+ ) -> unsignedinteger[_NBit1 | _NBit2]: ...
+
+class _UnsignedIntMod(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> unsignedinteger[_NBit1]: ...
+ @overload
+ def __call__(
+ self, other: int | signedinteger[Any], /
+ ) -> Any: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: unsignedinteger[_NBit2], /
+ ) -> unsignedinteger[_NBit1 | _NBit2]: ...
+
+class _UnsignedIntDivMod(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> _2Tuple[signedinteger[_NBit1]]: ...
+ @overload
+ def __call__(
+ self, other: int | signedinteger[Any], /
+ ) -> _2Tuple[Any]: ...
+ @overload
+ def __call__(self, other: float, /) -> _2Tuple[floating[_NBit1 | _NBitDouble]]: ...
+ @overload
+ def __call__(
+ self, other: unsignedinteger[_NBit2], /
+ ) -> _2Tuple[unsignedinteger[_NBit1 | _NBit2]]: ...
+
+class _SignedIntOp(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> signedinteger[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> signedinteger[_NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: complex, /,
+ ) -> complexfloating[_NBit1 | _NBitDouble, _NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: signedinteger[_NBit2], /,
+ ) -> signedinteger[_NBit1 | _NBit2]: ...
+
+class _SignedIntBitOp(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> signedinteger[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> signedinteger[_NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(
+ self, other: signedinteger[_NBit2], /,
+ ) -> signedinteger[_NBit1 | _NBit2]: ...
+
+class _SignedIntMod(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> signedinteger[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> signedinteger[_NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: signedinteger[_NBit2], /,
+ ) -> signedinteger[_NBit1 | _NBit2]: ...
+
+class _SignedIntDivMod(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> _2Tuple[signedinteger[_NBit1]]: ...
+ @overload
+ def __call__(self, other: int, /) -> _2Tuple[signedinteger[_NBit1 | _NBitInt]]: ...
+ @overload
+ def __call__(self, other: float, /) -> _2Tuple[floating[_NBit1 | _NBitDouble]]: ...
+ @overload
+ def __call__(
+ self, other: signedinteger[_NBit2], /,
+ ) -> _2Tuple[signedinteger[_NBit1 | _NBit2]]: ...
+
+class _FloatOp(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> floating[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> floating[_NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: complex, /,
+ ) -> complexfloating[_NBit1 | _NBitDouble, _NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: integer[_NBit2] | floating[_NBit2], /
+ ) -> floating[_NBit1 | _NBit2]: ...
+
+class _FloatMod(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> floating[_NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> floating[_NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(self, other: float, /) -> floating[_NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self, other: integer[_NBit2] | floating[_NBit2], /
+ ) -> floating[_NBit1 | _NBit2]: ...
+
+class _FloatDivMod(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> _2Tuple[floating[_NBit1]]: ...
+ @overload
+ def __call__(self, other: int, /) -> _2Tuple[floating[_NBit1 | _NBitInt]]: ...
+ @overload
+ def __call__(self, other: float, /) -> _2Tuple[floating[_NBit1 | _NBitDouble]]: ...
+ @overload
+ def __call__(
+ self, other: integer[_NBit2] | floating[_NBit2], /
+ ) -> _2Tuple[floating[_NBit1 | _NBit2]]: ...
+
+class _ComplexOp(Protocol[_NBit1]):
+ @overload
+ def __call__(self, other: bool, /) -> complexfloating[_NBit1, _NBit1]: ...
+ @overload
+ def __call__(self, other: int, /) -> complexfloating[_NBit1 | _NBitInt, _NBit1 | _NBitInt]: ...
+ @overload
+ def __call__(
+ self, other: complex, /,
+ ) -> complexfloating[_NBit1 | _NBitDouble, _NBit1 | _NBitDouble]: ...
+ @overload
+ def __call__(
+ self,
+ other: (
+ integer[_NBit2]
+ | floating[_NBit2]
+ | complexfloating[_NBit2, _NBit2]
+ ), /,
+ ) -> complexfloating[_NBit1 | _NBit2, _NBit1 | _NBit2]: ...
+
+class _NumberOp(Protocol):
+ def __call__(self, other: _NumberLike_co, /) -> Any: ...
+
+class _ComparisonOp(Protocol[_T1_contra, _T2_contra]):
+ @overload
+ def __call__(self, other: _T1_contra, /) -> bool_: ...
+ @overload
+ def __call__(self, other: _T2_contra, /) -> NDArray[bool_]: ...
diff --git a/numpy/_typing/_char_codes.py b/numpy/_typing/_char_codes.py
new file mode 100644
index 000000000..f840d17bb
--- /dev/null
+++ b/numpy/_typing/_char_codes.py
@@ -0,0 +1,111 @@
+from typing import Literal
+
+_BoolCodes = Literal["?", "=?", "<?", ">?", "bool", "bool_", "bool8"]
+
+_UInt8Codes = Literal["uint8", "u1", "=u1", "<u1", ">u1"]
+_UInt16Codes = Literal["uint16", "u2", "=u2", "<u2", ">u2"]
+_UInt32Codes = Literal["uint32", "u4", "=u4", "<u4", ">u4"]
+_UInt64Codes = Literal["uint64", "u8", "=u8", "<u8", ">u8"]
+
+_Int8Codes = Literal["int8", "i1", "=i1", "<i1", ">i1"]
+_Int16Codes = Literal["int16", "i2", "=i2", "<i2", ">i2"]
+_Int32Codes = Literal["int32", "i4", "=i4", "<i4", ">i4"]
+_Int64Codes = Literal["int64", "i8", "=i8", "<i8", ">i8"]
+
+_Float16Codes = Literal["float16", "f2", "=f2", "<f2", ">f2"]
+_Float32Codes = Literal["float32", "f4", "=f4", "<f4", ">f4"]
+_Float64Codes = Literal["float64", "f8", "=f8", "<f8", ">f8"]
+
+_Complex64Codes = Literal["complex64", "c8", "=c8", "<c8", ">c8"]
+_Complex128Codes = Literal["complex128", "c16", "=c16", "<c16", ">c16"]
+
+_ByteCodes = Literal["byte", "b", "=b", "<b", ">b"]
+_ShortCodes = Literal["short", "h", "=h", "<h", ">h"]
+_IntCCodes = Literal["intc", "i", "=i", "<i", ">i"]
+_IntPCodes = Literal["intp", "int0", "p", "=p", "<p", ">p"]
+_IntCodes = Literal["long", "int", "int_", "l", "=l", "<l", ">l"]
+_LongLongCodes = Literal["longlong", "q", "=q", "<q", ">q"]
+
+_UByteCodes = Literal["ubyte", "B", "=B", "<B", ">B"]
+_UShortCodes = Literal["ushort", "H", "=H", "<H", ">H"]
+_UIntCCodes = Literal["uintc", "I", "=I", "<I", ">I"]
+_UIntPCodes = Literal["uintp", "uint0", "P", "=P", "<P", ">P"]
+_UIntCodes = Literal["ulong", "uint", "L", "=L", "<L", ">L"]
+_ULongLongCodes = Literal["ulonglong", "Q", "=Q", "<Q", ">Q"]
+
+_HalfCodes = Literal["half", "e", "=e", "<e", ">e"]
+_SingleCodes = Literal["single", "f", "=f", "<f", ">f"]
+_DoubleCodes = Literal["double", "float", "float_", "d", "=d", "<d", ">d"]
+_LongDoubleCodes = Literal["longdouble", "longfloat", "g", "=g", "<g", ">g"]
+
+_CSingleCodes = Literal["csingle", "singlecomplex", "F", "=F", "<F", ">F"]
+_CDoubleCodes = Literal["cdouble", "complex", "complex_", "cfloat", "D", "=D", "<D", ">D"]
+_CLongDoubleCodes = Literal["clongdouble", "clongfloat", "longcomplex", "G", "=G", "<G", ">G"]
+
+_StrCodes = Literal["str", "str_", "str0", "unicode", "unicode_", "U", "=U", "<U", ">U"]
+_BytesCodes = Literal["bytes", "bytes_", "bytes0", "S", "=S", "<S", ">S"]
+_VoidCodes = Literal["void", "void0", "V", "=V", "<V", ">V"]
+_ObjectCodes = Literal["object", "object_", "O", "=O", "<O", ">O"]
+
+_DT64Codes = Literal[
+ "datetime64", "=datetime64", "<datetime64", ">datetime64",
+ "datetime64[Y]", "=datetime64[Y]", "<datetime64[Y]", ">datetime64[Y]",
+ "datetime64[M]", "=datetime64[M]", "<datetime64[M]", ">datetime64[M]",
+ "datetime64[W]", "=datetime64[W]", "<datetime64[W]", ">datetime64[W]",
+ "datetime64[D]", "=datetime64[D]", "<datetime64[D]", ">datetime64[D]",
+ "datetime64[h]", "=datetime64[h]", "<datetime64[h]", ">datetime64[h]",
+ "datetime64[m]", "=datetime64[m]", "<datetime64[m]", ">datetime64[m]",
+ "datetime64[s]", "=datetime64[s]", "<datetime64[s]", ">datetime64[s]",
+ "datetime64[ms]", "=datetime64[ms]", "<datetime64[ms]", ">datetime64[ms]",
+ "datetime64[us]", "=datetime64[us]", "<datetime64[us]", ">datetime64[us]",
+ "datetime64[ns]", "=datetime64[ns]", "<datetime64[ns]", ">datetime64[ns]",
+ "datetime64[ps]", "=datetime64[ps]", "<datetime64[ps]", ">datetime64[ps]",
+ "datetime64[fs]", "=datetime64[fs]", "<datetime64[fs]", ">datetime64[fs]",
+ "datetime64[as]", "=datetime64[as]", "<datetime64[as]", ">datetime64[as]",
+ "M", "=M", "<M", ">M",
+ "M8", "=M8", "<M8", ">M8",
+ "M8[Y]", "=M8[Y]", "<M8[Y]", ">M8[Y]",
+ "M8[M]", "=M8[M]", "<M8[M]", ">M8[M]",
+ "M8[W]", "=M8[W]", "<M8[W]", ">M8[W]",
+ "M8[D]", "=M8[D]", "<M8[D]", ">M8[D]",
+ "M8[h]", "=M8[h]", "<M8[h]", ">M8[h]",
+ "M8[m]", "=M8[m]", "<M8[m]", ">M8[m]",
+ "M8[s]", "=M8[s]", "<M8[s]", ">M8[s]",
+ "M8[ms]", "=M8[ms]", "<M8[ms]", ">M8[ms]",
+ "M8[us]", "=M8[us]", "<M8[us]", ">M8[us]",
+ "M8[ns]", "=M8[ns]", "<M8[ns]", ">M8[ns]",
+ "M8[ps]", "=M8[ps]", "<M8[ps]", ">M8[ps]",
+ "M8[fs]", "=M8[fs]", "<M8[fs]", ">M8[fs]",
+ "M8[as]", "=M8[as]", "<M8[as]", ">M8[as]",
+]
+_TD64Codes = Literal[
+ "timedelta64", "=timedelta64", "<timedelta64", ">timedelta64",
+ "timedelta64[Y]", "=timedelta64[Y]", "<timedelta64[Y]", ">timedelta64[Y]",
+ "timedelta64[M]", "=timedelta64[M]", "<timedelta64[M]", ">timedelta64[M]",
+ "timedelta64[W]", "=timedelta64[W]", "<timedelta64[W]", ">timedelta64[W]",
+ "timedelta64[D]", "=timedelta64[D]", "<timedelta64[D]", ">timedelta64[D]",
+ "timedelta64[h]", "=timedelta64[h]", "<timedelta64[h]", ">timedelta64[h]",
+ "timedelta64[m]", "=timedelta64[m]", "<timedelta64[m]", ">timedelta64[m]",
+ "timedelta64[s]", "=timedelta64[s]", "<timedelta64[s]", ">timedelta64[s]",
+ "timedelta64[ms]", "=timedelta64[ms]", "<timedelta64[ms]", ">timedelta64[ms]",
+ "timedelta64[us]", "=timedelta64[us]", "<timedelta64[us]", ">timedelta64[us]",
+ "timedelta64[ns]", "=timedelta64[ns]", "<timedelta64[ns]", ">timedelta64[ns]",
+ "timedelta64[ps]", "=timedelta64[ps]", "<timedelta64[ps]", ">timedelta64[ps]",
+ "timedelta64[fs]", "=timedelta64[fs]", "<timedelta64[fs]", ">timedelta64[fs]",
+ "timedelta64[as]", "=timedelta64[as]", "<timedelta64[as]", ">timedelta64[as]",
+ "m", "=m", "<m", ">m",
+ "m8", "=m8", "<m8", ">m8",
+ "m8[Y]", "=m8[Y]", "<m8[Y]", ">m8[Y]",
+ "m8[M]", "=m8[M]", "<m8[M]", ">m8[M]",
+ "m8[W]", "=m8[W]", "<m8[W]", ">m8[W]",
+ "m8[D]", "=m8[D]", "<m8[D]", ">m8[D]",
+ "m8[h]", "=m8[h]", "<m8[h]", ">m8[h]",
+ "m8[m]", "=m8[m]", "<m8[m]", ">m8[m]",
+ "m8[s]", "=m8[s]", "<m8[s]", ">m8[s]",
+ "m8[ms]", "=m8[ms]", "<m8[ms]", ">m8[ms]",
+ "m8[us]", "=m8[us]", "<m8[us]", ">m8[us]",
+ "m8[ns]", "=m8[ns]", "<m8[ns]", ">m8[ns]",
+ "m8[ps]", "=m8[ps]", "<m8[ps]", ">m8[ps]",
+ "m8[fs]", "=m8[fs]", "<m8[fs]", ">m8[fs]",
+ "m8[as]", "=m8[as]", "<m8[as]", ">m8[as]",
+]
diff --git a/numpy/_typing/_dtype_like.py b/numpy/_typing/_dtype_like.py
new file mode 100644
index 000000000..b705d82fd
--- /dev/null
+++ b/numpy/_typing/_dtype_like.py
@@ -0,0 +1,247 @@
+from typing import (
+ Any,
+ List,
+ Sequence,
+ Tuple,
+ Union,
+ Type,
+ TypeVar,
+ Protocol,
+ TypedDict,
+)
+
+import numpy as np
+
+from ._shape import _ShapeLike
+from ._generic_alias import _DType as DType
+
+from ._char_codes import (
+ _BoolCodes,
+ _UInt8Codes,
+ _UInt16Codes,
+ _UInt32Codes,
+ _UInt64Codes,
+ _Int8Codes,
+ _Int16Codes,
+ _Int32Codes,
+ _Int64Codes,
+ _Float16Codes,
+ _Float32Codes,
+ _Float64Codes,
+ _Complex64Codes,
+ _Complex128Codes,
+ _ByteCodes,
+ _ShortCodes,
+ _IntCCodes,
+ _IntPCodes,
+ _IntCodes,
+ _LongLongCodes,
+ _UByteCodes,
+ _UShortCodes,
+ _UIntCCodes,
+ _UIntPCodes,
+ _UIntCodes,
+ _ULongLongCodes,
+ _HalfCodes,
+ _SingleCodes,
+ _DoubleCodes,
+ _LongDoubleCodes,
+ _CSingleCodes,
+ _CDoubleCodes,
+ _CLongDoubleCodes,
+ _DT64Codes,
+ _TD64Codes,
+ _StrCodes,
+ _BytesCodes,
+ _VoidCodes,
+ _ObjectCodes,
+)
+
+_SCT = TypeVar("_SCT", bound=np.generic)
+_DType_co = TypeVar("_DType_co", covariant=True, bound=DType[Any])
+
+_DTypeLikeNested = Any # TODO: wait for support for recursive types
+
+
+# Mandatory keys
+class _DTypeDictBase(TypedDict):
+ names: Sequence[str]
+ formats: Sequence[_DTypeLikeNested]
+
+
+# Mandatory + optional keys
+class _DTypeDict(_DTypeDictBase, total=False):
+ # Only `str` elements are usable as indexing aliases,
+ # but `titles` can in principle accept any object
+ offsets: Sequence[int]
+ titles: Sequence[Any]
+ itemsize: int
+ aligned: bool
+
+
+# A protocol for anything with the dtype attribute
+class _SupportsDType(Protocol[_DType_co]):
+ @property
+ def dtype(self) -> _DType_co: ...
+
+
+# A subset of `npt.DTypeLike` that can be parametrized w.r.t. `np.generic`
+_DTypeLike = Union[
+ "np.dtype[_SCT]",
+ Type[_SCT],
+ _SupportsDType["np.dtype[_SCT]"],
+]
+
+
+# Would create a dtype[np.void]
+_VoidDTypeLike = Union[
+ # (flexible_dtype, itemsize)
+ Tuple[_DTypeLikeNested, int],
+ # (fixed_dtype, shape)
+ Tuple[_DTypeLikeNested, _ShapeLike],
+ # [(field_name, field_dtype, field_shape), ...]
+ #
+ # The type here is quite broad because NumPy accepts quite a wide
+ # range of inputs inside the list; see the tests for some
+ # examples.
+ List[Any],
+ # {'names': ..., 'formats': ..., 'offsets': ..., 'titles': ...,
+ # 'itemsize': ...}
+ _DTypeDict,
+ # (base_dtype, new_dtype)
+ Tuple[_DTypeLikeNested, _DTypeLikeNested],
+]
+
+# Anything that can be coerced into numpy.dtype.
+# Reference: https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
+DTypeLike = Union[
+ DType[Any],
+ # default data type (float64)
+ None,
+ # array-scalar types and generic types
+ Type[Any], # NOTE: We're stuck with `Type[Any]` due to object dtypes
+ # anything with a dtype attribute
+ _SupportsDType[DType[Any]],
+ # character codes, type strings or comma-separated fields, e.g., 'float64'
+ str,
+ _VoidDTypeLike,
+]
+
+# NOTE: while it is possible to provide the dtype as a dict of
+# dtype-like objects (e.g. `{'field1': ..., 'field2': ..., ...}`),
+# this syntax is officially discourged and
+# therefore not included in the Union defining `DTypeLike`.
+#
+# See https://github.com/numpy/numpy/issues/16891 for more details.
+
+# Aliases for commonly used dtype-like objects.
+# Note that the precision of `np.number` subclasses is ignored herein.
+_DTypeLikeBool = Union[
+ Type[bool],
+ Type[np.bool_],
+ DType[np.bool_],
+ _SupportsDType[DType[np.bool_]],
+ _BoolCodes,
+]
+_DTypeLikeUInt = Union[
+ Type[np.unsignedinteger],
+ DType[np.unsignedinteger],
+ _SupportsDType[DType[np.unsignedinteger]],
+ _UInt8Codes,
+ _UInt16Codes,
+ _UInt32Codes,
+ _UInt64Codes,
+ _UByteCodes,
+ _UShortCodes,
+ _UIntCCodes,
+ _UIntPCodes,
+ _UIntCodes,
+ _ULongLongCodes,
+]
+_DTypeLikeInt = Union[
+ Type[int],
+ Type[np.signedinteger],
+ DType[np.signedinteger],
+ _SupportsDType[DType[np.signedinteger]],
+ _Int8Codes,
+ _Int16Codes,
+ _Int32Codes,
+ _Int64Codes,
+ _ByteCodes,
+ _ShortCodes,
+ _IntCCodes,
+ _IntPCodes,
+ _IntCodes,
+ _LongLongCodes,
+]
+_DTypeLikeFloat = Union[
+ Type[float],
+ Type[np.floating],
+ DType[np.floating],
+ _SupportsDType[DType[np.floating]],
+ _Float16Codes,
+ _Float32Codes,
+ _Float64Codes,
+ _HalfCodes,
+ _SingleCodes,
+ _DoubleCodes,
+ _LongDoubleCodes,
+]
+_DTypeLikeComplex = Union[
+ Type[complex],
+ Type[np.complexfloating],
+ DType[np.complexfloating],
+ _SupportsDType[DType[np.complexfloating]],
+ _Complex64Codes,
+ _Complex128Codes,
+ _CSingleCodes,
+ _CDoubleCodes,
+ _CLongDoubleCodes,
+]
+_DTypeLikeDT64 = Union[
+ Type[np.timedelta64],
+ DType[np.timedelta64],
+ _SupportsDType[DType[np.timedelta64]],
+ _TD64Codes,
+]
+_DTypeLikeTD64 = Union[
+ Type[np.datetime64],
+ DType[np.datetime64],
+ _SupportsDType[DType[np.datetime64]],
+ _DT64Codes,
+]
+_DTypeLikeStr = Union[
+ Type[str],
+ Type[np.str_],
+ DType[np.str_],
+ _SupportsDType[DType[np.str_]],
+ _StrCodes,
+]
+_DTypeLikeBytes = Union[
+ Type[bytes],
+ Type[np.bytes_],
+ DType[np.bytes_],
+ _SupportsDType[DType[np.bytes_]],
+ _BytesCodes,
+]
+_DTypeLikeVoid = Union[
+ Type[np.void],
+ DType[np.void],
+ _SupportsDType[DType[np.void]],
+ _VoidCodes,
+ _VoidDTypeLike,
+]
+_DTypeLikeObject = Union[
+ type,
+ DType[np.object_],
+ _SupportsDType[DType[np.object_]],
+ _ObjectCodes,
+]
+
+_DTypeLikeComplex_co = Union[
+ _DTypeLikeBool,
+ _DTypeLikeUInt,
+ _DTypeLikeInt,
+ _DTypeLikeFloat,
+ _DTypeLikeComplex,
+]
diff --git a/numpy/_typing/_extended_precision.py b/numpy/_typing/_extended_precision.py
new file mode 100644
index 000000000..edc1778ce
--- /dev/null
+++ b/numpy/_typing/_extended_precision.py
@@ -0,0 +1,43 @@
+"""A module with platform-specific extended precision
+`numpy.number` subclasses.
+
+The subclasses are defined here (instead of ``__init__.pyi``) such
+that they can be imported conditionally via the numpy's mypy plugin.
+"""
+
+from typing import TYPE_CHECKING
+
+import numpy as np
+from . import (
+ _80Bit,
+ _96Bit,
+ _128Bit,
+ _256Bit,
+)
+
+if TYPE_CHECKING:
+ uint128 = np.unsignedinteger[_128Bit]
+ uint256 = np.unsignedinteger[_256Bit]
+ int128 = np.signedinteger[_128Bit]
+ int256 = np.signedinteger[_256Bit]
+ float80 = np.floating[_80Bit]
+ float96 = np.floating[_96Bit]
+ float128 = np.floating[_128Bit]
+ float256 = np.floating[_256Bit]
+ complex160 = np.complexfloating[_80Bit, _80Bit]
+ complex192 = np.complexfloating[_96Bit, _96Bit]
+ complex256 = np.complexfloating[_128Bit, _128Bit]
+ complex512 = np.complexfloating[_256Bit, _256Bit]
+else:
+ uint128 = Any
+ uint256 = Any
+ int128 = Any
+ int256 = Any
+ float80 = Any
+ float96 = Any
+ float128 = Any
+ float256 = Any
+ complex160 = Any
+ complex192 = Any
+ complex256 = Any
+ complex512 = Any
diff --git a/numpy/_typing/_generic_alias.py b/numpy/_typing/_generic_alias.py
new file mode 100644
index 000000000..0541ad77f
--- /dev/null
+++ b/numpy/_typing/_generic_alias.py
@@ -0,0 +1,209 @@
+from __future__ import annotations
+
+import sys
+import types
+from collections.abc import Generator, Iterable, Iterator
+from typing import (
+ Any,
+ ClassVar,
+ NoReturn,
+ TypeVar,
+ TYPE_CHECKING,
+)
+
+import numpy as np
+
+__all__ = ["_GenericAlias", "NDArray"]
+
+_T = TypeVar("_T", bound="_GenericAlias")
+
+
+def _to_str(obj: object) -> str:
+ """Helper function for `_GenericAlias.__repr__`."""
+ if obj is Ellipsis:
+ return '...'
+ elif isinstance(obj, type) and not isinstance(obj, _GENERIC_ALIAS_TYPE):
+ if obj.__module__ == 'builtins':
+ return obj.__qualname__
+ else:
+ return f'{obj.__module__}.{obj.__qualname__}'
+ else:
+ return repr(obj)
+
+
+def _parse_parameters(args: Iterable[Any]) -> Generator[TypeVar, None, None]:
+ """Search for all typevars and typevar-containing objects in `args`.
+
+ Helper function for `_GenericAlias.__init__`.
+
+ """
+ for i in args:
+ if hasattr(i, "__parameters__"):
+ yield from i.__parameters__
+ elif isinstance(i, TypeVar):
+ yield i
+
+
+def _reconstruct_alias(alias: _T, parameters: Iterator[TypeVar]) -> _T:
+ """Recursively replace all typevars with those from `parameters`.
+
+ Helper function for `_GenericAlias.__getitem__`.
+
+ """
+ args = []
+ for i in alias.__args__:
+ if isinstance(i, TypeVar):
+ value: Any = next(parameters)
+ elif isinstance(i, _GenericAlias):
+ value = _reconstruct_alias(i, parameters)
+ elif hasattr(i, "__parameters__"):
+ prm_tup = tuple(next(parameters) for _ in i.__parameters__)
+ value = i[prm_tup]
+ else:
+ value = i
+ args.append(value)
+
+ cls = type(alias)
+ return cls(alias.__origin__, tuple(args))
+
+
+class _GenericAlias:
+ """A python-based backport of the `types.GenericAlias` class.
+
+ E.g. for ``t = list[int]``, ``t.__origin__`` is ``list`` and
+ ``t.__args__`` is ``(int,)``.
+
+ See Also
+ --------
+ :pep:`585`
+ The PEP responsible for introducing `types.GenericAlias`.
+
+ """
+
+ __slots__ = ("__weakref__", "_origin", "_args", "_parameters", "_hash")
+
+ @property
+ def __origin__(self) -> type:
+ return super().__getattribute__("_origin")
+
+ @property
+ def __args__(self) -> tuple[object, ...]:
+ return super().__getattribute__("_args")
+
+ @property
+ def __parameters__(self) -> tuple[TypeVar, ...]:
+ """Type variables in the ``GenericAlias``."""
+ return super().__getattribute__("_parameters")
+
+ def __init__(
+ self,
+ origin: type,
+ args: object | tuple[object, ...],
+ ) -> None:
+ self._origin = origin
+ self._args = args if isinstance(args, tuple) else (args,)
+ self._parameters = tuple(_parse_parameters(self.__args__))
+
+ @property
+ def __call__(self) -> type[Any]:
+ return self.__origin__
+
+ def __reduce__(self: _T) -> tuple[
+ type[_T],
+ tuple[type[Any], tuple[object, ...]],
+ ]:
+ cls = type(self)
+ return cls, (self.__origin__, self.__args__)
+
+ def __mro_entries__(self, bases: Iterable[object]) -> tuple[type[Any]]:
+ return (self.__origin__,)
+
+ def __dir__(self) -> list[str]:
+ """Implement ``dir(self)``."""
+ cls = type(self)
+ dir_origin = set(dir(self.__origin__))
+ return sorted(cls._ATTR_EXCEPTIONS | dir_origin)
+
+ def __hash__(self) -> int:
+ """Return ``hash(self)``."""
+ # Attempt to use the cached hash
+ try:
+ return super().__getattribute__("_hash")
+ except AttributeError:
+ self._hash: int = hash(self.__origin__) ^ hash(self.__args__)
+ return super().__getattribute__("_hash")
+
+ def __instancecheck__(self, obj: object) -> NoReturn:
+ """Check if an `obj` is an instance."""
+ raise TypeError("isinstance() argument 2 cannot be a "
+ "parameterized generic")
+
+ def __subclasscheck__(self, cls: type) -> NoReturn:
+ """Check if a `cls` is a subclass."""
+ raise TypeError("issubclass() argument 2 cannot be a "
+ "parameterized generic")
+
+ def __repr__(self) -> str:
+ """Return ``repr(self)``."""
+ args = ", ".join(_to_str(i) for i in self.__args__)
+ origin = _to_str(self.__origin__)
+ return f"{origin}[{args}]"
+
+ def __getitem__(self: _T, key: object | tuple[object, ...]) -> _T:
+ """Return ``self[key]``."""
+ key_tup = key if isinstance(key, tuple) else (key,)
+
+ if len(self.__parameters__) == 0:
+ raise TypeError(f"There are no type variables left in {self}")
+ elif len(key_tup) > len(self.__parameters__):
+ raise TypeError(f"Too many arguments for {self}")
+ elif len(key_tup) < len(self.__parameters__):
+ raise TypeError(f"Too few arguments for {self}")
+
+ key_iter = iter(key_tup)
+ return _reconstruct_alias(self, key_iter)
+
+ def __eq__(self, value: object) -> bool:
+ """Return ``self == value``."""
+ if not isinstance(value, _GENERIC_ALIAS_TYPE):
+ return NotImplemented
+ return (
+ self.__origin__ == value.__origin__ and
+ self.__args__ == value.__args__
+ )
+
+ _ATTR_EXCEPTIONS: ClassVar[frozenset[str]] = frozenset({
+ "__origin__",
+ "__args__",
+ "__parameters__",
+ "__mro_entries__",
+ "__reduce__",
+ "__reduce_ex__",
+ "__copy__",
+ "__deepcopy__",
+ })
+
+ def __getattribute__(self, name: str) -> Any:
+ """Return ``getattr(self, name)``."""
+ # Pull the attribute from `__origin__` unless its
+ # name is in `_ATTR_EXCEPTIONS`
+ cls = type(self)
+ if name in cls._ATTR_EXCEPTIONS:
+ return super().__getattribute__(name)
+ return getattr(self.__origin__, name)
+
+
+# See `_GenericAlias.__eq__`
+if sys.version_info >= (3, 9):
+ _GENERIC_ALIAS_TYPE = (_GenericAlias, types.GenericAlias)
+else:
+ _GENERIC_ALIAS_TYPE = (_GenericAlias,)
+
+ScalarType = TypeVar("ScalarType", bound=np.generic, covariant=True)
+
+if TYPE_CHECKING or sys.version_info >= (3, 9):
+ _DType = np.dtype[ScalarType]
+ NDArray = np.ndarray[Any, np.dtype[ScalarType]]
+else:
+ _DType = _GenericAlias(np.dtype, (ScalarType,))
+ NDArray = _GenericAlias(np.ndarray, (Any, _DType))
diff --git a/numpy/_typing/_nbit.py b/numpy/_typing/_nbit.py
new file mode 100644
index 000000000..b8d35db4f
--- /dev/null
+++ b/numpy/_typing/_nbit.py
@@ -0,0 +1,16 @@
+"""A module with the precisions of platform-specific `~numpy.number`s."""
+
+from typing import Any
+
+# To-be replaced with a `npt.NBitBase` subclass by numpy's mypy plugin
+_NBitByte = Any
+_NBitShort = Any
+_NBitIntC = Any
+_NBitIntP = Any
+_NBitInt = Any
+_NBitLongLong = Any
+
+_NBitHalf = Any
+_NBitSingle = Any
+_NBitDouble = Any
+_NBitLongDouble = Any
diff --git a/numpy/_typing/_nested_sequence.py b/numpy/_typing/_nested_sequence.py
new file mode 100644
index 000000000..7c12c4a87
--- /dev/null
+++ b/numpy/_typing/_nested_sequence.py
@@ -0,0 +1,90 @@
+"""A module containing the `_NestedSequence` protocol."""
+
+from __future__ import annotations
+
+from typing import (
+ Any,
+ Iterator,
+ overload,
+ TypeVar,
+ Protocol,
+)
+
+__all__ = ["_NestedSequence"]
+
+_T_co = TypeVar("_T_co", covariant=True)
+
+
+class _NestedSequence(Protocol[_T_co]):
+ """A protocol for representing nested sequences.
+
+ Warning
+ -------
+ `_NestedSequence` currently does not work in combination with typevars,
+ *e.g.* ``def func(a: _NestedSequnce[T]) -> T: ...``.
+
+ See Also
+ --------
+ collections.abc.Sequence
+ ABCs for read-only and mutable :term:`sequences`.
+
+ Examples
+ --------
+ .. code-block:: python
+
+ >>> from __future__ import annotations
+
+ >>> from typing import TYPE_CHECKING
+ >>> import numpy as np
+ >>> from numpy._typing import _NestedSequnce
+
+ >>> def get_dtype(seq: _NestedSequnce[float]) -> np.dtype[np.float64]:
+ ... return np.asarray(seq).dtype
+
+ >>> a = get_dtype([1.0])
+ >>> b = get_dtype([[1.0]])
+ >>> c = get_dtype([[[1.0]]])
+ >>> d = get_dtype([[[[1.0]]]])
+
+ >>> if TYPE_CHECKING:
+ ... reveal_locals()
+ ... # note: Revealed local types are:
+ ... # note: a: numpy.dtype[numpy.floating[numpy._typing._64Bit]]
+ ... # note: b: numpy.dtype[numpy.floating[numpy._typing._64Bit]]
+ ... # note: c: numpy.dtype[numpy.floating[numpy._typing._64Bit]]
+ ... # note: d: numpy.dtype[numpy.floating[numpy._typing._64Bit]]
+
+ """
+
+ def __len__(self, /) -> int:
+ """Implement ``len(self)``."""
+ raise NotImplementedError
+
+ @overload
+ def __getitem__(self, index: int, /) -> _T_co | _NestedSequence[_T_co]: ...
+ @overload
+ def __getitem__(self, index: slice, /) -> _NestedSequence[_T_co]: ...
+
+ def __getitem__(self, index, /):
+ """Implement ``self[x]``."""
+ raise NotImplementedError
+
+ def __contains__(self, x: object, /) -> bool:
+ """Implement ``x in self``."""
+ raise NotImplementedError
+
+ def __iter__(self, /) -> Iterator[_T_co | _NestedSequence[_T_co]]:
+ """Implement ``iter(self)``."""
+ raise NotImplementedError
+
+ def __reversed__(self, /) -> Iterator[_T_co | _NestedSequence[_T_co]]:
+ """Implement ``reversed(self)``."""
+ raise NotImplementedError
+
+ def count(self, value: Any, /) -> int:
+ """Return the number of occurrences of `value`."""
+ raise NotImplementedError
+
+ def index(self, value: Any, /) -> int:
+ """Return the first index of `value`."""
+ raise NotImplementedError
diff --git a/numpy/_typing/_scalars.py b/numpy/_typing/_scalars.py
new file mode 100644
index 000000000..516b996dc
--- /dev/null
+++ b/numpy/_typing/_scalars.py
@@ -0,0 +1,30 @@
+from typing import Union, Tuple, Any
+
+import numpy as np
+
+# NOTE: `_StrLike_co` and `_BytesLike_co` are pointless, as `np.str_` and
+# `np.bytes_` are already subclasses of their builtin counterpart
+
+_CharLike_co = Union[str, bytes]
+
+# The 6 `<X>Like_co` type-aliases below represent all scalars that can be
+# coerced into `<X>` (with the casting rule `same_kind`)
+_BoolLike_co = Union[bool, np.bool_]
+_UIntLike_co = Union[_BoolLike_co, np.unsignedinteger]
+_IntLike_co = Union[_BoolLike_co, int, np.integer]
+_FloatLike_co = Union[_IntLike_co, float, np.floating]
+_ComplexLike_co = Union[_FloatLike_co, complex, np.complexfloating]
+_TD64Like_co = Union[_IntLike_co, np.timedelta64]
+
+_NumberLike_co = Union[int, float, complex, np.number, np.bool_]
+_ScalarLike_co = Union[
+ int,
+ float,
+ complex,
+ str,
+ bytes,
+ np.generic,
+]
+
+# `_VoidLike_co` is technically not a scalar, but it's close enough
+_VoidLike_co = Union[Tuple[Any, ...], np.void]
diff --git a/numpy/_typing/_shape.py b/numpy/_typing/_shape.py
new file mode 100644
index 000000000..c28859b19
--- /dev/null
+++ b/numpy/_typing/_shape.py
@@ -0,0 +1,6 @@
+from typing import Sequence, Tuple, Union, SupportsIndex
+
+_Shape = Tuple[int, ...]
+
+# Anything that can be coerced to a shape tuple
+_ShapeLike = Union[SupportsIndex, Sequence[SupportsIndex]]
diff --git a/numpy/_typing/_ufunc.pyi b/numpy/_typing/_ufunc.pyi
new file mode 100644
index 000000000..ee0317cf9
--- /dev/null
+++ b/numpy/_typing/_ufunc.pyi
@@ -0,0 +1,403 @@
+"""A module with private type-check-only `numpy.ufunc` subclasses.
+
+The signatures of the ufuncs are too varied to reasonably type
+with a single class. So instead, `ufunc` has been expanded into
+four private subclasses, one for each combination of
+`~ufunc.nin` and `~ufunc.nout`.
+
+"""
+
+from typing import (
+ Any,
+ Generic,
+ overload,
+ TypeVar,
+ Literal,
+ SupportsIndex,
+)
+
+from numpy import ufunc, _CastingKind, _OrderKACF
+from numpy.typing import NDArray
+
+from ._shape import _ShapeLike
+from ._scalars import _ScalarLike_co
+from ._array_like import ArrayLike, _ArrayLikeBool_co, _ArrayLikeInt_co
+from ._dtype_like import DTypeLike
+
+_T = TypeVar("_T")
+_2Tuple = tuple[_T, _T]
+_3Tuple = tuple[_T, _T, _T]
+_4Tuple = tuple[_T, _T, _T, _T]
+
+_NTypes = TypeVar("_NTypes", bound=int)
+_IDType = TypeVar("_IDType", bound=Any)
+_NameType = TypeVar("_NameType", bound=str)
+
+# NOTE: In reality `extobj` should be a length of list 3 containing an
+# int, an int, and a callable, but there's no way to properly express
+# non-homogenous lists.
+# Use `Any` over `Union` to avoid issues related to lists invariance.
+
+# NOTE: `reduce`, `accumulate`, `reduceat` and `outer` raise a ValueError for
+# ufuncs that don't accept two input arguments and return one output argument.
+# In such cases the respective methods are simply typed as `None`.
+
+# NOTE: Similarly, `at` won't be defined for ufuncs that return
+# multiple outputs; in such cases `at` is typed as `None`
+
+# NOTE: If 2 output types are returned then `out` must be a
+# 2-tuple of arrays. Otherwise `None` or a plain array are also acceptable
+
+class _UFunc_Nin1_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc]
+ @property
+ def __name__(self) -> _NameType: ...
+ @property
+ def ntypes(self) -> _NTypes: ...
+ @property
+ def identity(self) -> _IDType: ...
+ @property
+ def nin(self) -> Literal[1]: ...
+ @property
+ def nout(self) -> Literal[1]: ...
+ @property
+ def nargs(self) -> Literal[2]: ...
+ @property
+ def signature(self) -> None: ...
+ @property
+ def reduce(self) -> None: ...
+ @property
+ def accumulate(self) -> None: ...
+ @property
+ def reduceat(self) -> None: ...
+ @property
+ def outer(self) -> None: ...
+
+ @overload
+ def __call__(
+ self,
+ __x1: _ScalarLike_co,
+ out: None = ...,
+ *,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _2Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> Any: ...
+ @overload
+ def __call__(
+ self,
+ __x1: ArrayLike,
+ out: None | NDArray[Any] | tuple[NDArray[Any]] = ...,
+ *,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _2Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> NDArray[Any]: ...
+
+ def at(
+ self,
+ a: NDArray[Any],
+ indices: _ArrayLikeInt_co,
+ /,
+ ) -> None: ...
+
+class _UFunc_Nin2_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc]
+ @property
+ def __name__(self) -> _NameType: ...
+ @property
+ def ntypes(self) -> _NTypes: ...
+ @property
+ def identity(self) -> _IDType: ...
+ @property
+ def nin(self) -> Literal[2]: ...
+ @property
+ def nout(self) -> Literal[1]: ...
+ @property
+ def nargs(self) -> Literal[3]: ...
+ @property
+ def signature(self) -> None: ...
+
+ @overload
+ def __call__(
+ self,
+ __x1: _ScalarLike_co,
+ __x2: _ScalarLike_co,
+ out: None = ...,
+ *,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> Any: ...
+ @overload
+ def __call__(
+ self,
+ __x1: ArrayLike,
+ __x2: ArrayLike,
+ out: None | NDArray[Any] | tuple[NDArray[Any]] = ...,
+ *,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> NDArray[Any]: ...
+
+ def at(
+ self,
+ a: NDArray[Any],
+ indices: _ArrayLikeInt_co,
+ b: ArrayLike,
+ /,
+ ) -> None: ...
+
+ def reduce(
+ self,
+ array: ArrayLike,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: None | NDArray[Any] = ...,
+ keepdims: bool = ...,
+ initial: Any = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+
+ def accumulate(
+ self,
+ array: ArrayLike,
+ axis: SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: None | NDArray[Any] = ...,
+ ) -> NDArray[Any]: ...
+
+ def reduceat(
+ self,
+ array: ArrayLike,
+ indices: _ArrayLikeInt_co,
+ axis: SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: None | NDArray[Any] = ...,
+ ) -> NDArray[Any]: ...
+
+ # Expand `**kwargs` into explicit keyword-only arguments
+ @overload
+ def outer(
+ self,
+ A: _ScalarLike_co,
+ B: _ScalarLike_co,
+ /, *,
+ out: None = ...,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> Any: ...
+ @overload
+ def outer( # type: ignore[misc]
+ self,
+ A: ArrayLike,
+ B: ArrayLike,
+ /, *,
+ out: None | NDArray[Any] | tuple[NDArray[Any]] = ...,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> NDArray[Any]: ...
+
+class _UFunc_Nin1_Nout2(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc]
+ @property
+ def __name__(self) -> _NameType: ...
+ @property
+ def ntypes(self) -> _NTypes: ...
+ @property
+ def identity(self) -> _IDType: ...
+ @property
+ def nin(self) -> Literal[1]: ...
+ @property
+ def nout(self) -> Literal[2]: ...
+ @property
+ def nargs(self) -> Literal[3]: ...
+ @property
+ def signature(self) -> None: ...
+ @property
+ def at(self) -> None: ...
+ @property
+ def reduce(self) -> None: ...
+ @property
+ def accumulate(self) -> None: ...
+ @property
+ def reduceat(self) -> None: ...
+ @property
+ def outer(self) -> None: ...
+
+ @overload
+ def __call__(
+ self,
+ __x1: _ScalarLike_co,
+ __out1: None = ...,
+ __out2: None = ...,
+ *,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> _2Tuple[Any]: ...
+ @overload
+ def __call__(
+ self,
+ __x1: ArrayLike,
+ __out1: None | NDArray[Any] = ...,
+ __out2: None | NDArray[Any] = ...,
+ *,
+ out: _2Tuple[NDArray[Any]] = ...,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> _2Tuple[NDArray[Any]]: ...
+
+class _UFunc_Nin2_Nout2(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc]
+ @property
+ def __name__(self) -> _NameType: ...
+ @property
+ def ntypes(self) -> _NTypes: ...
+ @property
+ def identity(self) -> _IDType: ...
+ @property
+ def nin(self) -> Literal[2]: ...
+ @property
+ def nout(self) -> Literal[2]: ...
+ @property
+ def nargs(self) -> Literal[4]: ...
+ @property
+ def signature(self) -> None: ...
+ @property
+ def at(self) -> None: ...
+ @property
+ def reduce(self) -> None: ...
+ @property
+ def accumulate(self) -> None: ...
+ @property
+ def reduceat(self) -> None: ...
+ @property
+ def outer(self) -> None: ...
+
+ @overload
+ def __call__(
+ self,
+ __x1: _ScalarLike_co,
+ __x2: _ScalarLike_co,
+ __out1: None = ...,
+ __out2: None = ...,
+ *,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _4Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> _2Tuple[Any]: ...
+ @overload
+ def __call__(
+ self,
+ __x1: ArrayLike,
+ __x2: ArrayLike,
+ __out1: None | NDArray[Any] = ...,
+ __out2: None | NDArray[Any] = ...,
+ *,
+ out: _2Tuple[NDArray[Any]] = ...,
+ where: None | _ArrayLikeBool_co = ...,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _4Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ ) -> _2Tuple[NDArray[Any]]: ...
+
+class _GUFunc_Nin2_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc]
+ @property
+ def __name__(self) -> _NameType: ...
+ @property
+ def ntypes(self) -> _NTypes: ...
+ @property
+ def identity(self) -> _IDType: ...
+ @property
+ def nin(self) -> Literal[2]: ...
+ @property
+ def nout(self) -> Literal[1]: ...
+ @property
+ def nargs(self) -> Literal[3]: ...
+
+ # NOTE: In practice the only gufunc in the main name is `matmul`,
+ # so we can use its signature here
+ @property
+ def signature(self) -> Literal["(n?,k),(k,m?)->(n?,m?)"]: ...
+ @property
+ def reduce(self) -> None: ...
+ @property
+ def accumulate(self) -> None: ...
+ @property
+ def reduceat(self) -> None: ...
+ @property
+ def outer(self) -> None: ...
+ @property
+ def at(self) -> None: ...
+
+ # Scalar for 1D array-likes; ndarray otherwise
+ @overload
+ def __call__(
+ self,
+ __x1: ArrayLike,
+ __x2: ArrayLike,
+ out: None = ...,
+ *,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ axes: list[_2Tuple[SupportsIndex]] = ...,
+ ) -> Any: ...
+ @overload
+ def __call__(
+ self,
+ __x1: ArrayLike,
+ __x2: ArrayLike,
+ out: NDArray[Any] | tuple[NDArray[Any]],
+ *,
+ casting: _CastingKind = ...,
+ order: _OrderKACF = ...,
+ dtype: DTypeLike = ...,
+ subok: bool = ...,
+ signature: str | _3Tuple[None | str] = ...,
+ extobj: list[Any] = ...,
+ axes: list[_2Tuple[SupportsIndex]] = ...,
+ ) -> NDArray[Any]: ...
diff --git a/numpy/_typing/setup.py b/numpy/_typing/setup.py
new file mode 100644
index 000000000..24022fdaa
--- /dev/null
+++ b/numpy/_typing/setup.py
@@ -0,0 +1,10 @@
+def configuration(parent_package='', top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('_typing', parent_package, top_path)
+ config.add_data_files('*.pyi')
+ return config
+
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)