From f1194b3a677ac79de9e534121ce08592ec4ec70e Mon Sep 17 00:00:00 2001 From: jorenham Date: Wed, 12 Feb 2025 02:50:20 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=E2=9C=A8=20fix=20and=20improve=20`?= =?UTF-8?q?numpy.{f,i}info`=20in=20`=5Fcore.getlimits`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 + src/numpy-stubs/__init__.pyi | 54 +--------- src/numpy-stubs/_core/getlimits.pyi | 147 +++++++++++++++++++++++++++- test/static/accept/getlimits.pyi | 19 ++-- 4 files changed, 158 insertions(+), 64 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25ae79ee..13567559 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,7 @@ jobs: src/numpy-stubs/_core/_type_aliases.pyi src/numpy-stubs/_core/_ufunc_config.pyi src/numpy-stubs/_core/arrayprint.pyi + src/numpy-stubs/_core/getlimits.pyi src/numpy-stubs/_core/multiarray.pyi src/numpy-stubs/_core/numerictypes.pyi src/numpy-stubs/_core/records.pyi @@ -108,6 +109,7 @@ jobs: src/numpy-stubs/_core/_type_aliases.pyi src/numpy-stubs/_core/_ufunc_config.pyi src/numpy-stubs/_core/arrayprint.pyi + src/numpy-stubs/_core/getlimits.pyi src/numpy-stubs/_core/multiarray.pyi src/numpy-stubs/_core/numerictypes.pyi src/numpy-stubs/_core/records.pyi diff --git a/src/numpy-stubs/__init__.pyi b/src/numpy-stubs/__init__.pyi index 03ab55d9..1b5ec755 100644 --- a/src/numpy-stubs/__init__.pyi +++ b/src/numpy-stubs/__init__.pyi @@ -94,6 +94,7 @@ from numpy._core.fromnumeric import ( var, ) from numpy._core.function_base import geomspace, linspace, logspace +from numpy._core.getlimits import finfo, iinfo from numpy._core.multiarray import ( arange, array, @@ -661,9 +662,7 @@ _SCT = TypeVar("_SCT", bound=generic) _SCT_co = TypeVar("_SCT_co", bound=generic, covariant=True) _NumberT = TypeVar("_NumberT", bound=number) _RealNumberT = TypeVar("_RealNumberT", bound=floating | integer) -_FloatingT_co = TypeVar("_FloatingT_co", bound=floating, default=floating, covariant=True) _IntegerT = TypeVar("_IntegerT", bound=integer) -_IntegerT_co = TypeVar("_IntegerT_co", bound=integer, default=integer, covariant=True) _NBit = TypeVar("_NBit", bound=NBitBase, default=Any) _NBit1 = TypeVar("_NBit1", bound=NBitBase, default=Any) @@ -5241,57 +5240,6 @@ class ndindex: def __iter__(self) -> Self: ... def __next__(self) -> _Shape: ... -class finfo(Generic[_FloatingT_co]): - dtype: Final[dtype[_FloatingT_co]] - bits: Final[int] - eps: Final[_FloatingT_co] - epsneg: Final[_FloatingT_co] - iexp: Final[int] - machep: Final[int] - max: Final[_FloatingT_co] - maxexp: Final[int] - min: Final[_FloatingT_co] - minexp: Final[int] - negep: Final[int] - nexp: Final[int] - nmant: Final[int] - precision: Final[int] - resolution: Final[_FloatingT_co] - smallest_subnormal: Final[_FloatingT_co] - - @property - def smallest_normal(self) -> _FloatingT_co: ... - @property - def tiny(self) -> _FloatingT_co: ... - - # - @overload - def __new__(cls, dtype: inexact[_NBit] | _DTypeLike[inexact[_NBit]]) -> finfo[floating[_NBit]]: ... - @overload - def __new__(cls, dtype: type[float | complex] | float | complex) -> finfo[float64]: ... - @overload - def __new__(cls, dtype: str) -> finfo[floating]: ... - -class iinfo(Generic[_IntegerT_co]): - dtype: Final[dtype[_IntegerT_co]] - kind: Final[LiteralString] - bits: Final[int] - key: Final[LiteralString] - - # - @property - def min(self) -> int: ... - @property - def max(self) -> int: ... - - # - @overload - def __new__(cls, dtype: _IntegerT_co | _DTypeLike[_IntegerT_co]) -> iinfo[_IntegerT_co]: ... - @overload - def __new__(cls, dtype: int | type[int]) -> iinfo[int_]: ... - @overload - def __new__(cls, dtype: str) -> iinfo[Any]: ... - class memmap(ndarray[_ShapeT_co, _DType_co]): __array_priority__: ClassVar[float] # pyright: ignore[reportIncompatibleMethodOverride] diff --git a/src/numpy-stubs/_core/getlimits.pyi b/src/numpy-stubs/_core/getlimits.pyi index 09892b9b..6aff77ae 100644 --- a/src/numpy-stubs/_core/getlimits.pyi +++ b/src/numpy-stubs/_core/getlimits.pyi @@ -1,3 +1,148 @@ -from numpy import finfo, iinfo # noqa: ICN003 +from types import GenericAlias +from typing import Final, Generic, Literal as L, overload +from typing_extensions import Self, TypeVar + +import numpy as np +from numpy._typing import _16Bit, _32Bit, _64Bit, _96Bit, _128Bit, _DTypeLike +from numpy._typing._char_codes import ( + _CLongDoubleCodes, + _Complex64Codes, + _Complex128Codes, + _Complex192Codes, + _Complex256Codes, + _Float16Codes, + _Float32Codes, + _Float64Codes, + _Float96Codes, + _Float128Codes, + _Int8Codes, + _Int16Codes, + _Int32Codes, + _Int64Codes, + _IntPCodes, + _LongCodes, + _LongDoubleCodes, + _UInt8Codes, + _UInt16Codes, + _UInt32Codes, + _UInt64Codes, + _UIntPCodes, + _ULongCodes, +) __all__ = ["finfo", "iinfo"] + +### + +_FloatingT_co = TypeVar("_FloatingT_co", bound=np.floating, default=np.floating, covariant=True) +_IntegerT_co = TypeVar("_IntegerT_co", bound=np.integer, default=np.integer, covariant=True) + +### + +class iinfo(Generic[_IntegerT_co]): + dtype: np.dtype[_IntegerT_co] + bits: Final[L[8, 16, 32, 64]] + kind: Final[L["i", "u"]] + key: Final[L["i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64"]] + + @property + def min(self, /) -> int: ... + @property + def max(self, /) -> int: ... + + # + @overload + def __init__(self, /, int_type: _IntegerT_co | _DTypeLike[_IntegerT_co]) -> None: ... + @overload + def __init__(self: iinfo[np.int8], /, int_type: _Int8Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint8], /, int_type: _UInt8Codes) -> None: ... + @overload + def __init__(self: iinfo[np.int16], /, int_type: _Int16Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint16], /, int_type: _UInt16Codes) -> None: ... + @overload + def __init__(self: iinfo[np.int32], /, int_type: _Int32Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint32], /, int_type: _UInt32Codes) -> None: ... + @overload + def __init__(self: iinfo[np.int64], /, int_type: _Int64Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint64], /, int_type: _UInt64Codes) -> None: ... + @overload + def __init__(self: iinfo[np.long], /, int_type: _LongCodes) -> None: ... + @overload + def __init__(self: iinfo[np.ulong], /, int_type: _ULongCodes) -> None: ... + @overload + def __init__(self: iinfo[np.intp], /, int_type: int | type[int] | _IntPCodes) -> None: ... + @overload + def __init__(self: iinfo[np.uintp], /, int_type: _UIntPCodes) -> None: ... + + # + @classmethod + def __class_getitem__(cls, item: object, /) -> GenericAlias: ... + +# +class finfo(Generic[_FloatingT_co]): + dtype: np.dtype[_FloatingT_co] + eps: _FloatingT_co + epsneg: _FloatingT_co + resolution: _FloatingT_co + smallest_subnormal: _FloatingT_co + max: _FloatingT_co + min: _FloatingT_co + + bits: Final[L[2, 4, 8, 12, 16]] + iexp: Final[int] + machep: Final[int] + maxexp: Final[int] + minexp: Final[int] + negep: Final[int] + nexp: Final[int] + nmant: Final[int] + precision: Final[int] + + @property + def smallest_normal(self, /) -> _FloatingT_co: ... + @property + def tiny(self, /) -> _FloatingT_co: ... + + # + @overload + def __new__(cls, dtype: _FloatingT_co | _DTypeLike[_FloatingT_co]) -> Self: ... + @overload + def __new__(cls, dtype: type[complex | float] | complex | float) -> finfo[np.float64]: ... + @overload + def __new__( # type: ignore[overload-overlap] + cls, + dtype: np.inexact[_16Bit] | _DTypeLike[np.inexact[_16Bit]] | _Float16Codes, + ) -> finfo[np.float16]: ... + @overload + def __new__( # type: ignore[overload-overlap] + cls, + dtype: np.inexact[_32Bit] | _DTypeLike[np.inexact[_32Bit]] | _Float32Codes | _Complex64Codes, + ) -> finfo[np.float32]: ... + @overload + def __new__( + cls, + dtype: np.inexact[_64Bit] | _DTypeLike[np.inexact[_64Bit]] | _Float64Codes | _Complex128Codes, + ) -> finfo[np.float64]: ... + @overload + def __new__( + cls, + dtype: np.inexact[_96Bit] | _DTypeLike[np.inexact[_96Bit]] | _Float96Codes | _Complex192Codes, + ) -> finfo[np.float96]: ... + @overload + def __new__( + cls, + dtype: np.inexact[_128Bit] | _DTypeLike[np.inexact[_128Bit]] | _Float128Codes | _Complex256Codes, + ) -> finfo[np.float128]: ... + @overload + def __new__( + cls, + dtype: np.longdouble | np.clongdouble | _DTypeLike[np.longdouble | np.clongdouble] | _LongDoubleCodes | _CLongDoubleCodes, + ) -> finfo[np.longdouble]: ... + + # + @classmethod + def __class_getitem__(cls, item: object, /) -> GenericAlias: ... diff --git a/test/static/accept/getlimits.pyi b/test/static/accept/getlimits.pyi index f83ec783..dc99ffbe 100644 --- a/test/static/accept/getlimits.pyi +++ b/test/static/accept/getlimits.pyi @@ -1,8 +1,7 @@ -from typing import Any -from typing_extensions import LiteralString, assert_type +from typing import Literal +from typing_extensions import assert_type import numpy as np -from numpy._typing import _64Bit f: float f8: np.float64 @@ -16,12 +15,12 @@ finfo_f8: np.finfo[np.float64] iinfo_i8: np.iinfo[np.int64] assert_type(np.finfo(f), np.finfo[np.float64]) -assert_type(np.finfo(f8), np.finfo[np.floating[_64Bit]]) +assert_type(np.finfo(f8), np.finfo[np.float64]) assert_type(np.finfo(c8), np.finfo[np.float32]) -assert_type(np.finfo("f2"), np.finfo[np.floating[Any]]) +assert_type(np.finfo("f2"), np.finfo[np.float16]) assert_type(finfo_f8.dtype, np.dtype[np.float64]) -assert_type(finfo_f8.bits, int) +assert_type(finfo_f8.bits, Literal[2, 4, 8, 12, 16]) assert_type(finfo_f8.eps, np.float64) assert_type(finfo_f8.epsneg, np.float64) assert_type(finfo_f8.iexp, int) @@ -42,11 +41,11 @@ assert_type(finfo_f8.smallest_subnormal, np.float64) assert_type(np.iinfo(i), np.iinfo[np.int_]) assert_type(np.iinfo(i8), np.iinfo[np.int64]) assert_type(np.iinfo(u4), np.iinfo[np.uint32]) -assert_type(np.iinfo("i2"), np.iinfo[Any]) +assert_type(np.iinfo("i2"), np.iinfo[np.int16]) assert_type(iinfo_i8.dtype, np.dtype[np.int64]) -assert_type(iinfo_i8.kind, LiteralString) -assert_type(iinfo_i8.bits, int) -assert_type(iinfo_i8.key, LiteralString) +assert_type(iinfo_i8.kind, Literal["i", "u"]) +assert_type(iinfo_i8.bits, Literal[8, 16, 32, 64]) +assert_type(iinfo_i8.key, Literal["i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64"]) assert_type(iinfo_i8.min, int) assert_type(iinfo_i8.max, int)