From 40d1cae714d950fb0fc0b272bd384dd30c258172 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sun, 2 Mar 2025 04:08:23 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20stub=20`numpy.=5Futils`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore | 5 + .mypyignore-todo | 2 - src/numpy-stubs/_utils/__init__.pyi | 29 ++++++ src/numpy-stubs/_utils/_convertions.pyi | 4 + src/numpy-stubs/_utils/_inspect.pyi | 70 ++++++++++++++ src/numpy-stubs/_utils/_pep440.pyi | 118 ++++++++++++++++++++++++ 6 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 src/numpy-stubs/_utils/__init__.pyi create mode 100644 src/numpy-stubs/_utils/_convertions.pyi create mode 100644 src/numpy-stubs/_utils/_inspect.pyi create mode 100644 src/numpy-stubs/_utils/_pep440.pyi diff --git a/.mypyignore b/.mypyignore index e08f9739..2d462b87 100644 --- a/.mypyignore +++ b/.mypyignore @@ -16,3 +16,8 @@ numpy\._core\.__all__ numpy\._core\.numeric\.__all__ numpy\._core\.numerictypes\.__all__ numpy\.matlib\.__all__ + +# workaround mypy's lack of Python 3.13 support for `NamedTuple` types (mypy <= 1.15.0) +numpy\._utils\._pep440\._Version\.__replace__ +numpy\.lib\._arraysetops_impl\.Unique(All|Counts|Inverse)Result\.__replace__ +numpy\.linalg\._linalg\.(Eig|Eigh|QR|SVD|Slogdet)Result\.__replace__ diff --git a/.mypyignore-todo b/.mypyignore-todo index 960ea05c..d3cdd7aa 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -194,7 +194,6 @@ numpy.f2py.((cb|common|f90mod|use)_)?rules numpy.fft.helper numpy.lib.Arrayterator.__array__ -numpy.lib._arraysetops_impl.Unique(All|Counts|Inverse)Result.__replace__ numpy.lib._array_utils_impl.normalize_axis_tuple numpy.lib._arrayterator_impl.Arrayterator.__array__ numpy.lib._index_tricks_impl.AxisConcatenator.makemat @@ -209,7 +208,6 @@ numpy.lib.format.read_array(_header_(1|2)_0)? numpy.lib.mixins.NDArrayOperatorsMixin.__array_ufunc__ numpy.lib.recfunctions.unstructured_to_structured -numpy.linalg._linalg.(Eig|Eigh|QR|SVD|Slogdet)Result.__replace__ numpy.linalg(._linalg)?.cholesky numpy.linalg(._linalg)?.pinv numpy.linalg(._linalg)?.tensordot diff --git a/src/numpy-stubs/_utils/__init__.pyi b/src/numpy-stubs/_utils/__init__.pyi new file mode 100644 index 00000000..f7acb78b --- /dev/null +++ b/src/numpy-stubs/_utils/__init__.pyi @@ -0,0 +1,29 @@ +from _typeshed import IdentityFunction +from collections.abc import Callable, Iterable +from typing import Protocol, overload, type_check_only +from typing_extensions import TypeVar + +from ._convertions import asbytes as asbytes, asunicode as asunicode + +### + +_T = TypeVar("_T") +_HasModuleT = TypeVar("_HasModuleT", bound=_HasModule) + +@type_check_only +class _HasModule(Protocol): + __module__: str + +### + +@overload +def set_module(module: None) -> IdentityFunction: ... +@overload +def set_module(module: _HasModuleT) -> _HasModuleT: ... + +# +def _rename_parameter( + old_names: Iterable[str], + new_names: Iterable[str], + dep_version: str | None = None, +) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... diff --git a/src/numpy-stubs/_utils/_convertions.pyi b/src/numpy-stubs/_utils/_convertions.pyi new file mode 100644 index 00000000..6cc599ac --- /dev/null +++ b/src/numpy-stubs/_utils/_convertions.pyi @@ -0,0 +1,4 @@ +__all__ = ["asbytes", "asunicode"] + +def asunicode(s: bytes | str) -> str: ... +def asbytes(s: bytes | str) -> str: ... diff --git a/src/numpy-stubs/_utils/_inspect.pyi b/src/numpy-stubs/_utils/_inspect.pyi new file mode 100644 index 00000000..d8b95662 --- /dev/null +++ b/src/numpy-stubs/_utils/_inspect.pyi @@ -0,0 +1,70 @@ +import types +from _typeshed import SupportsLenAndGetItem +from collections.abc import Callable, Mapping +from typing import Any, Final, TypeAlias, overload +from typing_extensions import TypeIs, TypeVar + +__all__ = ["formatargspec", "getargspec"] + +### + +_T = TypeVar("_T") +_RT = TypeVar("_RT") + +_StrSeq: TypeAlias = SupportsLenAndGetItem[str] +_NestedSeq: TypeAlias = list[_T | _NestedSeq[_T]] | tuple[_T | _NestedSeq[_T], ...] + +_JoinFunc: TypeAlias = Callable[[list[_T]], _T] +_FormatFunc: TypeAlias = Callable[[_T], str] + +### + +CO_OPTIMIZED: Final = 1 +CO_NEWLOCALS: Final = 2 +CO_VARARGS: Final = 4 +CO_VARKEYWORDS: Final = 8 + +### + +def ismethod(object: object) -> TypeIs[types.MethodType]: ... +def isfunction(object: object) -> TypeIs[types.FunctionType]: ... +def iscode(object: object) -> TypeIs[types.CodeType]: ... + +### + +def getargs(co: types.CodeType) -> tuple[list[str], str | None, str | None]: ... +def getargspec(func: types.MethodType | types.FunctionType) -> tuple[list[str], str | None, str | None, tuple[Any, ...]]: ... +def getargvalues(frame: types.FrameType) -> tuple[list[str], str | None, str | None, dict[str, Any]]: ... + +# +def joinseq(seq: _StrSeq) -> str: ... + +# +@overload +def strseq(object: _NestedSeq[str], convert: Callable[[Any], Any], join: _JoinFunc[str] = ...) -> str: ... +@overload +def strseq(object: _NestedSeq[_T], convert: Callable[[_T], _RT], join: _JoinFunc[_RT]) -> _RT: ... + +# +def formatargspec( + args: _StrSeq, + varargs: str | None = None, + varkw: str | None = None, + defaults: SupportsLenAndGetItem[object] | None = None, + formatarg: _FormatFunc[str] = ..., # str + formatvarargs: _FormatFunc[str] = ..., # "*{}".format + formatvarkw: _FormatFunc[str] = ..., # "**{}".format + formatvalue: _FormatFunc[object] = ..., # "={!r}".format + join: _JoinFunc[str] = ..., # joinseq +) -> str: ... +def formatargvalues( + args: _StrSeq, + varargs: str | None, + varkw: str | None, + locals: Mapping[str, object] | None, + formatarg: _FormatFunc[str] = ..., # str + formatvarargs: _FormatFunc[str] = ..., # "*{}".format + formatvarkw: _FormatFunc[str] = ..., # "**{}".format + formatvalue: _FormatFunc[object] = ..., # "={!r}".format + join: _JoinFunc[str] = ..., # joinseq +) -> str: ... diff --git a/src/numpy-stubs/_utils/_pep440.pyi b/src/numpy-stubs/_utils/_pep440.pyi new file mode 100644 index 00000000..11ae02e5 --- /dev/null +++ b/src/numpy-stubs/_utils/_pep440.pyi @@ -0,0 +1,118 @@ +import re +from collections.abc import Callable +from typing import ( + Any, + ClassVar, + Final, + Generic, + Literal as L, + NamedTuple, + TypeVar, + final, + type_check_only, +) +from typing_extensions import TypeIs + +__all__ = ["VERSION_PATTERN", "InvalidVersion", "LegacyVersion", "Version", "parse"] + +### + +_CmpKeyT = TypeVar("_CmpKeyT", bound=tuple[object, ...]) +_CmpKeyT_co = TypeVar("_CmpKeyT_co", bound=tuple[object, ...], default=tuple[Any, ...], covariant=True) + +### + +VERSION_PATTERN: Final[str] = ... + +class InvalidVersion(ValueError): ... + +@type_check_only +@final +class _InfinityType: + def __hash__(self) -> int: ... + def __eq__(self, other: object, /) -> TypeIs[_InfinityType]: ... + def __ne__(self, other: object, /) -> bool: ... + def __lt__(self, other: object, /) -> L[False]: ... + def __le__(self, other: object, /) -> L[False]: ... + def __gt__(self, other: object, /) -> L[True]: ... + def __ge__(self, other: object, /) -> L[True]: ... + def __neg__(self) -> _NegativeInfinityType: ... + +Infinity: Final[_InfinityType] = ... + +@type_check_only +@final +class _NegativeInfinityType: + def __hash__(self) -> int: ... + def __eq__(self, other: object, /) -> TypeIs[_NegativeInfinityType]: ... + def __ne__(self, other: object, /) -> bool: ... + def __lt__(self, other: object, /) -> L[True]: ... + def __le__(self, other: object, /) -> L[True]: ... + def __gt__(self, other: object, /) -> L[False]: ... + def __ge__(self, other: object, /) -> L[False]: ... + def __neg__(self) -> _InfinityType: ... + +NegativeInfinity: Final[_NegativeInfinityType] = ... + +class _Version(NamedTuple): + epoch: int + release: tuple[int, ...] + dev: tuple[str, int] | None + pre: tuple[str, int] | None + post: tuple[str, int] | None + local: tuple[str | int, ...] | None + +class _BaseVersion(Generic[_CmpKeyT_co]): + _key: _CmpKeyT_co + def __hash__(self) -> int: ... + def __eq__(self, other: _BaseVersion, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def __ne__(self, other: _BaseVersion, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def __lt__(self, other: _BaseVersion, /) -> bool: ... + def __le__(self, other: _BaseVersion, /) -> bool: ... + def __ge__(self, other: _BaseVersion, /) -> bool: ... + def __gt__(self, other: _BaseVersion, /) -> bool: ... + def _compare(self, /, other: _BaseVersion[_CmpKeyT], method: Callable[[_CmpKeyT_co, _CmpKeyT], bool]) -> bool: ... + +class LegacyVersion(_BaseVersion[tuple[L[-1], tuple[str, ...]]]): + _version: Final[str] + def __init__(self, /, version: str) -> None: ... + @property + def public(self) -> str: ... + @property + def base_version(self) -> str: ... + @property + def local(self) -> None: ... + @property + def is_prerelease(self) -> L[False]: ... + @property + def is_postrelease(self) -> L[False]: ... + +class Version( + _BaseVersion[ + tuple[ + int, # epoch + tuple[int, ...], # release + tuple[str, int] | _InfinityType | _NegativeInfinityType, # pre + tuple[str, int] | _NegativeInfinityType, # post + tuple[str, int] | _InfinityType, # dev + tuple[tuple[int, L[""]] | tuple[_NegativeInfinityType, str], ...] | _NegativeInfinityType, # local + ], + ], +): + _regex: ClassVar[re.Pattern[str]] = ... + _version: Final[str] + + def __init__(self, /, version: str) -> None: ... + @property + def public(self) -> str: ... + @property + def base_version(self) -> str: ... + @property + def local(self) -> str | None: ... + @property + def is_prerelease(self) -> bool: ... + @property + def is_postrelease(self) -> bool: ... + +# +def parse(version: str) -> Version | LegacyVersion: ...