From a5285349805c5e794700a3dfcb378b391c53b0c8 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Mon, 16 Nov 2020 19:08:49 +0100 Subject: [PATCH 01/13] ENH: Added a mypy plugin for handling platform-specific `np.number` precisions --- numpy/__init__.pyi | 85 +++++++++++++---------- numpy/typing/__init__.py | 34 +++++++++ numpy/typing/_nbit.py | 16 +++++ numpy/typing/mypy_plugin.py | 58 ++++++++++++++++ numpy/typing/tests/data/mypy.ini | 2 +- numpy/typing/tests/data/pass/scalars.py | 35 ++++++++++ numpy/typing/tests/data/reveal/scalars.py | 36 ++++++++++ 7 files changed, 229 insertions(+), 37 deletions(-) create mode 100644 numpy/typing/_nbit.py create mode 100644 numpy/typing/mypy_plugin.py diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 3165a6319265..6df10d7a7568 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -21,10 +21,24 @@ from numpy.typing import ( _SupportsDType, _VoidDTypeLike, NBitBase, + _256Bit, + _128Bit, + _96Bit, + _80Bit, _64Bit, _32Bit, _16Bit, _8Bit, + _NBitByte, + _NBitShort, + _NBitIntC, + _NBitIntP, + _NBitInt, + _NBitLongLong, + _NBitHalf, + _NBitSingle, + _NBitDouble, + _NBitLongDouble, ) from numpy.typing._callable import ( _BoolOp, @@ -311,29 +325,22 @@ broadcast_to: Any busday_count: Any busday_offset: Any busdaycalendar: Any -byte: Any byte_bounds: Any bytes0: Any c_: Any can_cast: Any cast: Any -cdouble: Any -cfloat: Any chararray: Any -clongdouble: Any -clongfloat: Any column_stack: Any common_type: Any compare_chararrays: Any complex256: Any -complex_: Any concatenate: Any conj: Any copy: Any copyto: Any corrcoef: Any cov: Any -csingle: Any cumproduct: Any datetime_as_string: Any datetime_data: Any @@ -349,7 +356,6 @@ digitize: Any disp: Any divide: Any dot: Any -double: Any dsplit: Any dstack: Any ediff1d: Any @@ -365,7 +371,6 @@ flip: Any fliplr: Any flipud: Any float128: Any -float_: Any format_parser: Any frombuffer: Any fromfile: Any @@ -377,7 +382,6 @@ genfromtxt: Any get_include: Any geterrobj: Any gradient: Any -half: Any hamming: Any hanning: Any histogram: Any @@ -393,12 +397,8 @@ index_exp: Any info: Any inner: Any insert: Any -int0: Any -int_: Any -intc: Any interp: Any intersect1d: Any -intp: Any is_busday: Any iscomplex: Any iscomplexobj: Any @@ -415,10 +415,6 @@ lexsort: Any load: Any loads: Any loadtxt: Any -longcomplex: Any -longdouble: Any -longfloat: Any -longlong: Any lookfor: Any mafromtxt: Any mask_indices: Any @@ -504,11 +500,8 @@ setdiff1d: Any seterrobj: Any setxor1d: Any shares_memory: Any -short: Any show_config: Any sinc: Any -single: Any -singlecomplex: Any sort_complex: Any source: Any split: Any @@ -527,18 +520,11 @@ triu_indices_from: Any typeDict: Any typecodes: Any typename: Any -ubyte: Any -uint: Any -uint0: Any -uintc: Any -uintp: Any -ulonglong: Any union1d: Any unique: Any unpackbits: Any unravel_index: Any unwrap: Any -ushort: Any vander: Any vdot: Any vectorize: Any @@ -1853,6 +1839,14 @@ int16 = signedinteger[_16Bit] int32 = signedinteger[_32Bit] int64 = signedinteger[_64Bit] +byte = signedinteger[_NBitByte] +short = signedinteger[_NBitShort] +intc = signedinteger[_NBitIntC] +intp = signedinteger[_NBitIntP] +int0 = signedinteger[_NBitIntP] +int_ = signedinteger[_NBitInt] +longlong = signedinteger[_NBitLongLong] + class timedelta64(generic): def __init__( self, @@ -1917,6 +1911,14 @@ uint16 = unsignedinteger[_16Bit] uint32 = unsignedinteger[_32Bit] uint64 = unsignedinteger[_64Bit] +ubyte = unsignedinteger[_NBitByte] +ushort = unsignedinteger[_NBitShort] +uintc = unsignedinteger[_NBitIntC] +uintp = unsignedinteger[_NBitIntP] +uint0 = unsignedinteger[_NBitIntP] +uint = unsignedinteger[_NBitInt] +ulonglong = unsignedinteger[_NBitLongLong] + class inexact(number[_NBit_co]): ... # type: ignore _IntType = TypeVar("_IntType", bound=integer) @@ -1945,6 +1947,13 @@ float16 = floating[_16Bit] float32 = floating[_32Bit] float64 = floating[_64Bit] +half = floating[_NBitHalf] +single = floating[_NBitSingle] +double = floating[_NBitDouble] +float_ = floating[_NBitDouble] +longdouble = floating[_NBitLongDouble] +longfloat = floating[_NBitLongDouble] + # The main reason for `complexfloating` having two typevars is cosmetic. # It is used to clarify why `complex128`s precision is `_64Bit`, the latter # describing the two 64 bit floats representing its real and imaginary component @@ -1972,6 +1981,15 @@ class complexfloating(inexact[_NBit_co], Generic[_NBit_co, _NBit_co2]): complex64 = complexfloating[_32Bit, _32Bit] complex128 = complexfloating[_64Bit, _64Bit] +csingle = complexfloating[_NBitSingle, _NBitSingle] +singlecomplex = complexfloating[_NBitSingle, _NBitSingle] +cdouble = complexfloating[_NBitDouble, _NBitDouble] +complex_ = complexfloating[_NBitDouble, _NBitDouble] +cfloat = complexfloating[_NBitDouble, _NBitDouble] +clongdouble = complexfloating[_NBitLongDouble, _NBitLongDouble] +clongfloat = complexfloating[_NBitLongDouble, _NBitLongDouble] +longcomplex = complexfloating[_NBitLongDouble, _NBitLongDouble] + class flexible(generic): ... # type: ignore class void(flexible): @@ -2007,15 +2025,10 @@ class str_(character, str): self, __value: bytes, encoding: str = ..., errors: str = ... ) -> None: ... -unicode_ = str0 = str_ +unicode_ = str_ +str0 = str_ -# TODO(alan): Platform dependent types -# longcomplex, longdouble, longfloat -# bytes, short, intc, intp, longlong -# half, single, double, longdouble -# uint_, int_, float_, complex_ -# float128, complex256 -# float96 +# TODO: Platform dependent types: float128, complex256, float96 def array( object: object, diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py index d9d9557bf465..694046609054 100644 --- a/numpy/typing/__init__.py +++ b/numpy/typing/__init__.py @@ -19,6 +19,28 @@ .. _typing-extensions: https://pypi.org/project/typing-extensions/ +Mypy plugin +----------- + +A mypy_ plugin is available for automatically assigning the (platform-dependent) +precisions of certain `~numpy.number` subclasses, including the likes of +`~numpy.int_`, `~numpy.intp` and `~numpy.longlong`. See the documentation on +:ref:`scalar types ` for a comprehensive overview +of the affected classes. + +Note that while usage of the plugin is completely optional, without it the +precision of above-mentioned classes will be inferred as `~typing.Any`. + +To enable the plugin, one must add it to their mypy `configuration file`_: + +.. code-block:: ini + + [mypy] + plugins = numpy.typing.mypy_plugin + +.. _mypy: http://mypy-lang.org/ +.. _configuration file: https://mypy.readthedocs.io/en/stable/config_file.html + Differences from the runtime NumPy API -------------------------------------- @@ -207,6 +229,18 @@ class _8Bit(_16Bit): ... # type: ignore[misc] # Clean up the namespace del TYPE_CHECKING, final, List +from ._nbit import ( + _NBitByte, + _NBitShort, + _NBitIntC, + _NBitIntP, + _NBitInt, + _NBitLongLong, + _NBitHalf, + _NBitSingle, + _NBitDouble, + _NBitLongDouble, +) from ._scalars import ( _CharLike, _BoolLike, diff --git a/numpy/typing/_nbit.py b/numpy/typing/_nbit.py new file mode 100644 index 000000000000..b8d35db4f594 --- /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/mypy_plugin.py b/numpy/typing/mypy_plugin.py new file mode 100644 index 000000000000..023ab5fd18f3 --- /dev/null +++ b/numpy/typing/mypy_plugin.py @@ -0,0 +1,58 @@ +"""A module containing `numpy`-specific plugins for mypy.""" + +import typing as t + +import numpy as np + +import mypy.types +from mypy.types import Type +from mypy.plugin import Plugin, AnalyzeTypeContext + +HookFunc = t.Callable[[AnalyzeTypeContext], Type] + + +def _get_precision_dict() -> t.Dict[str, str]: + names = [ + ("_NBitByte", np.byte), + ("_NBitShort", np.short), + ("_NBitIntC", np.intc), + ("_NBitIntP", np.intp), + ("_NBitInt", np.int_), + ("_NBitLongLong", np.longlong), + + ("_NBitHalf", np.half), + ("_NBitSingle", np.single), + ("_NBitDouble", np.double), + ("_NBitLongDouble", np.longdouble), + ] + ret = {} + for name, typ in names: + n: int = 8 * typ().dtype.alignment + ret[f'numpy.typing._nbit.{name}'] = f"numpy._{n}Bit" + return ret + + +#: A dictionary mapping type-aliases in `numpy.typing._nbit` to +#: concrete `numpy.typing.NBitBase` subclasses. +_PRECISION_DICT = _get_precision_dict() + + +def _hook(ctx: AnalyzeTypeContext) -> Type: + """Replace a type-alias with a concrete ``NBitBase`` subclass.""" + typ, _, api = ctx + name = typ.name.split(".")[-1] + name_new = _PRECISION_DICT[f"numpy.typing._nbit.{name}"] + return api.named_type(name_new) + + +class _NumpyPlugin(Plugin): + """A plugin for assigning platform-specific `numpy.number` precisions.""" + + def get_type_analyze_hook(self, fullname: str) -> t.Optional[HookFunc]: + if fullname in _PRECISION_DICT: + return _hook + return None + + +def plugin(version: str) -> t.Type[_NumpyPlugin]: + return _NumpyPlugin diff --git a/numpy/typing/tests/data/mypy.ini b/numpy/typing/tests/data/mypy.ini index 91d93588af15..35cfbec89ec2 100644 --- a/numpy/typing/tests/data/mypy.ini +++ b/numpy/typing/tests/data/mypy.ini @@ -1,5 +1,5 @@ [mypy] -mypy_path = ../../.. +plugins = numpy.typing.mypy_plugin [mypy-numpy] ignore_errors = True diff --git a/numpy/typing/tests/data/pass/scalars.py b/numpy/typing/tests/data/pass/scalars.py index b7f7880e4561..2f2643e8eb33 100644 --- a/numpy/typing/tests/data/pass/scalars.py +++ b/numpy/typing/tests/data/pass/scalars.py @@ -163,3 +163,38 @@ def __float__(self) -> float: c16.squeeze() c16.byteswap() c16.transpose() + +# Aliases +np.str0() + +np.byte() +np.short() +np.intc() +np.intp() +np.int0() +np.int_() +np.longlong() + +np.ubyte() +np.ushort() +np.uintc() +np.uintp() +np.uint0() +np.uint() +np.ulonglong() + +np.half() +np.single() +np.double() +np.float_() +np.longdouble() +np.longfloat() + +np.csingle() +np.singlecomplex() +np.cdouble() +np.complex_() +np.cfloat() +np.clongdouble() +np.clongfloat() +np.longcomplex() diff --git a/numpy/typing/tests/data/reveal/scalars.py b/numpy/typing/tests/data/reveal/scalars.py index e887e302d4f4..841b1473d3a9 100644 --- a/numpy/typing/tests/data/reveal/scalars.py +++ b/numpy/typing/tests/data/reveal/scalars.py @@ -26,3 +26,39 @@ reveal_type(np.unicode_('foo')) # E: numpy.str_ reveal_type(np.str0('foo')) # E: numpy.str_ + +# Aliases +reveal_type(np.unicode_()) # E: numpy.str_ +reveal_type(np.str0()) # E: numpy.str_ + +reveal_type(np.byte()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.short()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.intc()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.intp()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.int0()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.int_()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.longlong()) # E: numpy.signedinteger[numpy.typing._ + +reveal_type(np.ubyte()) # E: numpy.unsignedinteger[numpy.typing._ +reveal_type(np.ushort()) # E: numpy.unsignedinteger[numpy.typing._ +reveal_type(np.uintc()) # E: numpy.unsignedinteger[numpy.typing._ +reveal_type(np.uintp()) # E: numpy.unsignedinteger[numpy.typing._ +reveal_type(np.uint0()) # E: numpy.unsignedinteger[numpy.typing._ +reveal_type(np.uint()) # E: numpy.unsignedinteger[numpy.typing._ +reveal_type(np.ulonglong()) # E: numpy.unsignedinteger[numpy.typing._ + +reveal_type(np.half()) # E: numpy.floating[numpy.typing._ +reveal_type(np.single()) # E: numpy.floating[numpy.typing._ +reveal_type(np.double()) # E: numpy.floating[numpy.typing._ +reveal_type(np.float_()) # E: numpy.floating[numpy.typing._ +reveal_type(np.longdouble()) # E: numpy.floating[numpy.typing._ +reveal_type(np.longfloat()) # E: numpy.floating[numpy.typing._ + +reveal_type(np.csingle()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.singlecomplex()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.cdouble()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.complex_()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.cfloat()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.clongdouble()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.clongfloat()) # E: numpy.complexfloating[numpy.typing._ +reveal_type(np.longcomplex()) # E: numpy.complexfloating[numpy.typing._ From edacfda3da401c56f1eb32d58de08581e03f84d6 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Mon, 16 Nov 2020 19:08:49 +0100 Subject: [PATCH 02/13] ENH: Centralize all `DTypeLike` string aliases in `numpy.typing` --- numpy/__init__.pyi | 372 ++++++++++++------------------------ numpy/typing/__init__.py | 41 ++++ numpy/typing/_char_codes.py | 115 +++++++++++ 3 files changed, 282 insertions(+), 246 deletions(-) create mode 100644 numpy/typing/_char_codes.py diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 6df10d7a7568..514f4dc4a1cf 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -40,6 +40,47 @@ from numpy.typing import ( _NBitDouble, _NBitLongDouble, ) +from numpy.typing 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 numpy.typing._callable import ( _BoolOp, _BoolBitOp, @@ -555,269 +596,108 @@ class dtype(Generic[_DTypeScalar]): # # so we have to make sure the overloads for the narrowest type is # first. + # Builtin types @overload - def __new__( - cls, - dtype: Union[ - Type[bool], - Literal[ - "?", - "=?", - "?", - "bool", - "bool_", - ], - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[bool_]: ... + def __new__(cls, dtype: Type[bool], align: bool = ..., copy: bool = ...) -> dtype[bool_]: ... @overload - def __new__( - cls, - dtype: Literal[ - "uint8", - "u1", - "=u1", - "u1", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[uint8]: ... + def __new__(cls, dtype: Type[int], align: bool = ..., copy: bool = ...) -> dtype[int_]: ... @overload - def __new__( - cls, - dtype: Literal[ - "uint16", - "u2", - "=u2", - "u2", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[uint16]: ... + def __new__(cls, dtype: Optional[Type[float]], align: bool = ..., copy: bool = ...) -> dtype[float_]: ... @overload - def __new__( - cls, - dtype: Literal[ - "uint32", - "u4", - "=u4", - "u4", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[uint32]: ... + def __new__(cls, dtype: Type[complex], align: bool = ..., copy: bool = ...) -> dtype[complex_]: ... @overload - def __new__( - cls, - dtype: Literal[ - "uint64", - "u8", - "=u8", - "u8", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[uint64]: ... + def __new__(cls, dtype: Type[str], align: bool = ..., copy: bool = ...) -> dtype[str_]: ... @overload - def __new__( - cls, - dtype: Literal[ - "int8", - "i1", - "=i1", - "i1", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[int8]: ... + def __new__(cls, dtype: Type[bytes], align: bool = ..., copy: bool = ...) -> dtype[bytes_]: ... + + # `unsignedinteger` string-based representations @overload - def __new__( - cls, - dtype: Literal[ - "int16", - "i2", - "=i2", - "i2", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[int16]: ... + def __new__(cls, dtype: _UInt8Codes, align: bool = ..., copy: bool = ...) -> dtype[uint8]: ... @overload - def __new__( - cls, - dtype: Literal[ - "int32", - "i4", - "=i4", - "i4", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[int32]: ... + def __new__(cls, dtype: _UInt16Codes, align: bool = ..., copy: bool = ...) -> dtype[uint16]: ... @overload - def __new__( - cls, - dtype: Literal[ - "int64", - "i8", - "=i8", - "i8", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[int64]: ... - # "int"/int resolve to int_, which is system dependent and as of - # now untyped. Long-term we'll do something fancier here. + def __new__(cls, dtype: _UInt32Codes, align: bool = ..., copy: bool = ...) -> dtype[uint32]: ... @overload - def __new__( - cls, - dtype: Union[Type[int], Literal["int"]], - align: bool = ..., - copy: bool = ..., - ) -> dtype: ... + def __new__(cls, dtype: _UInt64Codes, align: bool = ..., copy: bool = ...) -> dtype[uint64]: ... @overload - def __new__( - cls, - dtype: Literal[ - "float16", - "f4", - "=f4", - "f4", - "e", - "=e", - "e", - "half", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[float16]: ... + def __new__(cls, dtype: _UByteCodes, align: bool = ..., copy: bool = ...) -> dtype[ubyte]: ... @overload - def __new__( - cls, - dtype: Literal[ - "float32", - "f4", - "=f4", - "f4", - "f", - "=f", - "f", - "single", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[float32]: ... + def __new__(cls, dtype: _UShortCodes, align: bool = ..., copy: bool = ...) -> dtype[ushort]: ... @overload - def __new__( - cls, - dtype: Union[ - None, - Type[float], - Literal[ - "float64", - "f8", - "=f8", - "f8", - "d", - "d", - "float", - "double", - "float_", - ], - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[float64]: ... + def __new__(cls, dtype: _UIntCCodes, align: bool = ..., copy: bool = ...) -> dtype[uintc]: ... @overload - def __new__( - cls, - dtype: Literal[ - "complex64", - "c8", - "=c8", - "c8", - "F", - "=F", - "F", - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[complex64]: ... + def __new__(cls, dtype: _UIntPCodes, align: bool = ..., copy: bool = ...) -> dtype[uintp]: ... @overload - def __new__( - cls, - dtype: Union[ - Type[complex], - Literal[ - "complex128", - "c16", - "=c16", - "c16", - "D", - "=D", - "D", - ], - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[complex128]: ... + def __new__(cls, dtype: _UIntCodes, align: bool = ..., copy: bool = ...) -> dtype[uint]: ... @overload - def __new__( - cls, - dtype: Union[ - Type[bytes], - Literal[ - "S", - "=S", - "S", - "bytes", - "bytes_", - "bytes0", - ], - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[bytes_]: ... + def __new__(cls, dtype: _ULongLongCodes, align: bool = ..., copy: bool = ...) -> dtype[ulonglong]: ... + + # `signedinteger` string-based representations @overload - def __new__( - cls, - dtype: Union[ - Type[str], - Literal[ - "U", - "=U", - # U intentionally not included; they are not - # the same dtype and which one dtype("U") translates - # to is platform-dependent. - "str", - "str_", - "str0", - ], - ], - align: bool = ..., - copy: bool = ..., - ) -> dtype[str_]: ... + def __new__(cls, dtype: _Int8Codes, align: bool = ..., copy: bool = ...) -> dtype[int8]: ... + @overload + def __new__(cls, dtype: _Int16Codes, align: bool = ..., copy: bool = ...) -> dtype[int16]: ... + @overload + def __new__(cls, dtype: _Int32Codes, align: bool = ..., copy: bool = ...) -> dtype[int32]: ... + @overload + def __new__(cls, dtype: _Int64Codes, align: bool = ..., copy: bool = ...) -> dtype[int64]: ... + @overload + def __new__(cls, dtype: _ByteCodes, align: bool = ..., copy: bool = ...) -> dtype[byte]: ... + @overload + def __new__(cls, dtype: _ShortCodes, align: bool = ..., copy: bool = ...) -> dtype[short]: ... + @overload + def __new__(cls, dtype: _IntCCodes, align: bool = ..., copy: bool = ...) -> dtype[intc]: ... + @overload + def __new__(cls, dtype: _IntPCodes, align: bool = ..., copy: bool = ...) -> dtype[intp]: ... + @overload + def __new__(cls, dtype: _IntCodes, align: bool = ..., copy: bool = ...) -> dtype[int_]: ... + @overload + def __new__(cls, dtype: _LongLongCodes, align: bool = ..., copy: bool = ...) -> dtype[longlong]: ... + + # `floating` string-based representations + @overload + def __new__(cls, dtype: _Float16Codes, align: bool = ..., copy: bool = ...) -> dtype[float16]: ... + @overload + def __new__(cls, dtype: _Float32Codes, align: bool = ..., copy: bool = ...) -> dtype[float32]: ... + @overload + def __new__(cls, dtype: _Float64Codes, align: bool = ..., copy: bool = ...) -> dtype[float64]: ... + @overload + def __new__(cls, dtype: _HalfCodes, align: bool = ..., copy: bool = ...) -> dtype[half]: ... + @overload + def __new__(cls, dtype: _SingleCodes, align: bool = ..., copy: bool = ...) -> dtype[single]: ... + @overload + def __new__(cls, dtype: _DoubleCodes, align: bool = ..., copy: bool = ...) -> dtype[double]: ... + @overload + def __new__(cls, dtype: _LongDoubleCodes, align: bool = ..., copy: bool = ...) -> dtype[longdouble]: ... + + # `complexfloating` string-based representations + @overload + def __new__(cls, dtype: _Complex64Codes, align: bool = ..., copy: bool = ...) -> dtype[complex64]: ... + @overload + def __new__(cls, dtype: _Complex128Codes, align: bool = ..., copy: bool = ...) -> dtype[complex128]: ... + @overload + def __new__(cls, dtype: _CSingleCodes, align: bool = ..., copy: bool = ...) -> dtype[csingle]: ... + @overload + def __new__(cls, dtype: _CDoubleCodes, align: bool = ..., copy: bool = ...) -> dtype[cdouble]: ... + @overload + def __new__(cls, dtype: _CLongDoubleCodes, align: bool = ..., copy: bool = ...) -> dtype[clongdouble]: ... + + # Miscellaneous string-based representations + @overload + def __new__(cls, dtype: _BoolCodes, align: bool = ..., copy: bool = ...) -> dtype[bool_]: ... + @overload + def __new__(cls, dtype: _TD64Codes, align: bool = ..., copy: bool = ...) -> dtype[timedelta64]: ... + @overload + def __new__(cls, dtype: _DT64Codes, align: bool = ..., copy: bool = ...) -> dtype[datetime64]: ... + @overload + def __new__(cls, dtype: _StrCodes, align: bool = ..., copy: bool = ...) -> dtype[str_]: ... + @overload + def __new__(cls, dtype: _BytesCodes, align: bool = ..., copy: bool = ...) -> dtype[bytes_]: ... + @overload + def __new__(cls, dtype: _VoidCodes, align: bool = ..., copy: bool = ...) -> dtype[void]: ... + @overload + def __new__(cls, dtype: _ObjectCodes, align: bool = ..., copy: bool = ...) -> dtype[object_]: ... + # dtype of a dtype is the same dtype @overload def __new__( diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py index 694046609054..9f8e27573ba2 100644 --- a/numpy/typing/__init__.py +++ b/numpy/typing/__init__.py @@ -241,6 +241,47 @@ class _8Bit(_16Bit): ... # type: ignore[misc] _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, _BoolLike, diff --git a/numpy/typing/_char_codes.py b/numpy/typing/_char_codes.py new file mode 100644 index 000000000000..7e5b82cfaf73 --- /dev/null +++ b/numpy/typing/_char_codes.py @@ -0,0 +1,115 @@ +import sys +from typing import Any, TYPE_CHECKING + +if sys.version_info >= (3, 8): + from typing import Literal + HAVE_LITERAL = True +else: + try: + from typing_extensions import Literal + except ImportError: + HAVE_LITERAL = False + else: + HAVE_LITERAL = True + +if TYPE_CHECKING or HAVE_LITERAL: + _BoolCodes = Literal["?", "=?", "?", "bool", "bool_", "bool8"] + + _UInt8Codes = Literal["uint8", "u1", "=u1", "u1"] + _UInt16Codes = Literal["uint16", "u2", "=u2", "u2"] + _UInt32Codes = Literal["uint32", "u4", "=u4", "u4"] + _UInt64Codes = Literal["uint64", "u8", "=u8", "u8"] + + _Int8Codes = Literal["int8", "i1", "=i1", "i1"] + _Int16Codes = Literal["int16", "i2", "=i2", "i2"] + _Int32Codes = Literal["int32", "i4", "=i4", "i4"] + _Int64Codes = Literal["int64", "i8", "=i8", "i8"] + + _Float16Codes = Literal["float16", "f2", "=f2", "f2"] + _Float32Codes = Literal["float32", "f4", "=f4", "f4"] + _Float64Codes = Literal["float64", "f8", "=f8", "f8"] + + _Complex64Codes = Literal["complex64", "c8", "=c8", "c8"] + _Complex128Codes = Literal["complex128", "c16", "=c16", "c16"] + + _ByteCodes = Literal["byte", "b", "=b", "b"] + _ShortCodes = Literal["short", "h", "=h", "h"] + _IntCCodes = Literal["intc", "i", "=i", "i"] + _IntPCodes = Literal["intp", "int0", "p", "=p", "p"] + _IntCodes = Literal["long", "int", "int_", "l", "=l", "l"] + _LongLongCodes = Literal["longlong", "q", "=q", "q"] + + _UByteCodes = Literal["ubyte", "B", "=B", "B"] + _UShortCodes = Literal["ushort", "H", "=H", "H"] + _UIntCCodes = Literal["uintc", "I", "=I", "I"] + _UIntPCodes = Literal["uintp", "uint0", "P", "=P", "P"] + _UIntCodes = Literal["uint", "L", "=L", "L"] + _ULongLongCodes = Literal["ulonglong", "Q", "=Q", "Q"] + + _HalfCodes = Literal["half", "e", "=e", "e"] + _SingleCodes = Literal["single", "f", "=f", "f"] + _DoubleCodes = Literal["double" "float", "float_", "d", "=d", "d"] + _LongDoubleCodes = Literal["longdouble", "longfloat", "g", "=g", "g"] + + _CSingleCodes = Literal["csingle", "singlecomplex", "F", "=F", "F"] + _CDoubleCodes = Literal["cdouble" "complex", "complex_", "cfloat", "D", "=D", "D"] + _CLongDoubleCodes = Literal["clongdouble", "clongfloat", "longcomplex", "G", "=G", "G"] + + _DT64Codes = Literal["datetime64", "M", "=M", "M"] + _TD64Codes = Literal["timedelta64", "m", "=m", "m"] + + _StrCodes = Literal["str", "str_", "str0", "unicode", "unicode_", "U", "=U", "U"] + _BytesCodes = Literal["bytes", "bytes_", "bytes0", "S", "=S", "S"] + _VoidCodes = Literal["void", "void0", "V", "=V", "V"] + _ObjectCodes = Literal["object", "object_", "O", "=O", "O"] + +else: + _BoolCodes = Any + + _UInt8Codes = Any + _UInt16Codes = Any + _UInt32Codes = Any + _UInt64Codes = Any + + _Int8Codes = Any + _Int16Codes = Any + _Int32Codes = Any + _Int64Codes = Any + + _Float16Codes = Any + _Float32Codes = Any + _Float64Codes = Any + + _Complex64Codes = Any + _Complex128Codes = Any + + _ByteCodes = Any + _ShortCodes = Any + _IntCCodes = Any + _IntPCodes = Any + _IntCodes = Any + _LongLongCodes = Any + + _UByteCodes = Any + _UShortCodes = Any + _UIntCCodes = Any + _UIntPCodes = Any + _UIntCodes = Any + _ULongLongCodes = Any + + _HalfCodes = Any + _SingleCodes = Any + _DoubleCodes = Any + _LongDoubleCodes = Any + + _CSingleCodes = Any + _CDoubleCodes = Any + _CLongDoubleCodes = Any + + _DT64Codes = Any + _TD64Codes = Any + + _StrCodes = Any + _BytesCodes = Any + _VoidCodes = Any + _ObjectCodes = Any From 0daed8701f941945a10daf4969843a346c933baf Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Tue, 24 Nov 2020 22:55:23 +0100 Subject: [PATCH 03/13] ENH: Use `intp` as return type for all appropiate functions Since `intp` is now annotated it can be used in place of `signedinteger[Any]` --- numpy/__init__.pyi | 8 +++---- numpy/core/fromnumeric.pyi | 13 +++++----- numpy/typing/tests/data/reveal/fromnumeric.py | 24 +++++++++---------- .../typing/tests/data/reveal/ndarray_misc.py | 12 +++++----- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 514f4dc4a1cf..656048173c7d 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -970,21 +970,21 @@ class _ArrayOrScalarCommon: keepdims: bool = ..., ) -> _NdArraySubClass: ... @overload - def argmax(self, axis: None = ..., out: None = ...) -> signedinteger: ... + def argmax(self, axis: None = ..., out: None = ...) -> intp: ... @overload def argmax( self, axis: _ShapeLike = ..., out: None = ... - ) -> Union[signedinteger, ndarray]: ... + ) -> Union[ndarray, intp]: ... @overload def argmax( self, axis: Optional[_ShapeLike] = ..., out: _NdArraySubClass = ... ) -> _NdArraySubClass: ... @overload - def argmin(self, axis: None = ..., out: None = ...) -> signedinteger: ... + def argmin(self, axis: None = ..., out: None = ...) -> intp: ... @overload def argmin( self, axis: _ShapeLike = ..., out: None = ... - ) -> Union[signedinteger, ndarray]: ... + ) -> Union[ndarray, intp]: ... @overload def argmin( self, axis: Optional[_ShapeLike] = ..., out: _NdArraySubClass = ... diff --git a/numpy/core/fromnumeric.pyi b/numpy/core/fromnumeric.pyi index 66eb3bfb892f..3b147e1d732f 100644 --- a/numpy/core/fromnumeric.pyi +++ b/numpy/core/fromnumeric.pyi @@ -6,6 +6,7 @@ from numpy import ( ndarray, number, integer, + intp, bool_, generic, _OrderKACF, @@ -130,7 +131,7 @@ def argpartition( axis: Optional[int] = ..., kind: _PartitionKind = ..., order: Union[None, str, Sequence[str]] = ..., -) -> integer: ... +) -> intp: ... @overload def argpartition( a: _ScalarBuiltin, @@ -160,24 +161,24 @@ def argsort( order: Union[None, str, Sequence[str]] = ..., ) -> ndarray: ... @overload -def argmax(a: ArrayLike, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ... +def argmax(a: ArrayLike, axis: None = ..., out: Optional[ndarray] = ...) -> intp: ... @overload def argmax( a: ArrayLike, axis: int = ..., out: Optional[ndarray] = ... -) -> Union[integer, ndarray]: ... +) -> Union[ndarray, intp]: ... @overload -def argmin(a: ArrayLike, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ... +def argmin(a: ArrayLike, axis: None = ..., out: Optional[ndarray] = ...) -> intp: ... @overload def argmin( a: ArrayLike, axis: int = ..., out: Optional[ndarray] = ... -) -> Union[integer, ndarray]: ... +) -> Union[ndarray, intp]: ... @overload def searchsorted( a: ArrayLike, v: _Scalar, side: _SortSide = ..., sorter: Optional[_ArrayLikeIntOrBool] = ..., # 1D int array -) -> integer: ... +) -> intp: ... @overload def searchsorted( a: ArrayLike, diff --git a/numpy/typing/tests/data/reveal/fromnumeric.py b/numpy/typing/tests/data/reveal/fromnumeric.py index 2972fa1afaab..2d823b2e2cfc 100644 --- a/numpy/typing/tests/data/reveal/fromnumeric.py +++ b/numpy/typing/tests/data/reveal/fromnumeric.py @@ -66,8 +66,8 @@ reveal_type(np.partition(A, 0)) # E: numpy.ndarray[Any, Any] reveal_type(np.partition(B, 0)) # E: numpy.ndarray[Any, Any] -reveal_type(np.argpartition(a, 0)) # E: numpy.integer[Any] -reveal_type(np.argpartition(b, 0)) # E: numpy.integer[Any] +reveal_type(np.argpartition(a, 0)) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.argpartition(b, 0)) # E: numpy.signedinteger[numpy.typing._ reveal_type(np.argpartition(c, 0)) # E: numpy.ndarray[Any, Any] reveal_type(np.argpartition(A, 0)) # E: numpy.ndarray[Any, Any] reveal_type(np.argpartition(B, 0)) # E: numpy.ndarray[Any, Any] @@ -78,18 +78,18 @@ reveal_type(np.argsort(A, 0)) # E: numpy.ndarray[Any, Any] reveal_type(np.argsort(B, 0)) # E: numpy.ndarray[Any, Any] -reveal_type(np.argmax(A)) # E: numpy.integer[Any] -reveal_type(np.argmax(B)) # E: numpy.integer[Any] -reveal_type(np.argmax(A, axis=0)) # E: Union[numpy.integer[Any], numpy.ndarray[Any, Any]] -reveal_type(np.argmax(B, axis=0)) # E: Union[numpy.integer[Any], numpy.ndarray[Any, Any]] +reveal_type(np.argmax(A)) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.argmax(B)) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.argmax(A, axis=0)) # E: Union[numpy.ndarray[Any, Any], numpy.signedinteger[numpy.typing._ +reveal_type(np.argmax(B, axis=0)) # E: Union[numpy.ndarray[Any, Any], numpy.signedinteger[numpy.typing._ -reveal_type(np.argmin(A)) # E: numpy.integer[Any] -reveal_type(np.argmin(B)) # E: numpy.integer[Any] -reveal_type(np.argmin(A, axis=0)) # E: Union[numpy.integer[Any], numpy.ndarray[Any, Any]] -reveal_type(np.argmin(B, axis=0)) # E: Union[numpy.integer[Any], numpy.ndarray[Any, Any]] +reveal_type(np.argmin(A)) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.argmin(B)) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.argmin(A, axis=0)) # E: Union[numpy.ndarray[Any, Any], numpy.signedinteger[numpy.typing._ +reveal_type(np.argmin(B, axis=0)) # E: Union[numpy.ndarray[Any, Any], numpy.signedinteger[numpy.typing._ -reveal_type(np.searchsorted(A[0], 0)) # E: numpy.integer[Any] -reveal_type(np.searchsorted(B[0], 0)) # E: numpy.integer[Any] +reveal_type(np.searchsorted(A[0], 0)) # E: numpy.signedinteger[numpy.typing._ +reveal_type(np.searchsorted(B[0], 0)) # E: numpy.signedinteger[numpy.typing._ reveal_type(np.searchsorted(A[0], [0])) # E: numpy.ndarray[Any, Any] reveal_type(np.searchsorted(B[0], [0])) # E: numpy.ndarray[Any, Any] diff --git a/numpy/typing/tests/data/reveal/ndarray_misc.py b/numpy/typing/tests/data/reveal/ndarray_misc.py index 3e640b3ba8cd..df6cd4586e0a 100644 --- a/numpy/typing/tests/data/reveal/ndarray_misc.py +++ b/numpy/typing/tests/data/reveal/ndarray_misc.py @@ -26,14 +26,14 @@ class SubClass(np.ndarray): ... reveal_type(A.any(keepdims=True)) # E: Union[numpy.bool_, numpy.ndarray[Any, Any]] reveal_type(A.any(out=B)) # E: SubClass -reveal_type(f8.argmax()) # E: numpy.signedinteger[Any] -reveal_type(A.argmax()) # E: numpy.signedinteger[Any] -reveal_type(A.argmax(axis=0)) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, Any]] +reveal_type(f8.argmax()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(A.argmax()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(A.argmax(axis=0)) # E: Union[numpy.ndarray[Any, Any], numpy.signedinteger[numpy.typing._ reveal_type(A.argmax(out=B)) # E: SubClass -reveal_type(f8.argmin()) # E: numpy.signedinteger[Any] -reveal_type(A.argmin()) # E: numpy.signedinteger[Any] -reveal_type(A.argmin(axis=0)) # E: Union[numpy.signedinteger[Any], numpy.ndarray[Any, Any]] +reveal_type(f8.argmin()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(A.argmin()) # E: numpy.signedinteger[numpy.typing._ +reveal_type(A.argmin(axis=0)) # E: Union[numpy.ndarray[Any, Any], numpy.signedinteger[numpy.typing._ reveal_type(A.argmin(out=B)) # E: SubClass reveal_type(f8.argsort()) # E: numpy.ndarray[Any, Any] From 133cf30ad1f34d1d6990133502c5a30209b51e6f Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Tue, 24 Nov 2020 22:55:33 +0100 Subject: [PATCH 04/13] ENH: Take the precision of `np.int_` into account arithmetic operations --- numpy/typing/_callable.py | 30 ++++++++++--------- numpy/typing/tests/data/reveal/arithmetic.py | 24 +++++++-------- numpy/typing/tests/data/reveal/bitwise_ops.py | 20 ++++++------- numpy/typing/tests/data/reveal/mod.py | 24 +++++++-------- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.py index 831921fd7922..8f464cc755ce 100644 --- a/numpy/typing/_callable.py +++ b/numpy/typing/_callable.py @@ -29,11 +29,13 @@ unsignedinteger, signedinteger, int8, + int_, floating, float64, complexfloating, complex128, ) +from ._nbit import _NBitInt from ._scalars import ( _BoolLike, _IntLike, @@ -72,7 +74,7 @@ class _BoolOp(Protocol[_GenericType_co]): @overload def __call__(self, __other: _BoolLike) -> _GenericType_co: ... @overload # platform dependent - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> int_: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -84,7 +86,7 @@ class _BoolBitOp(Protocol[_GenericType_co]): @overload def __call__(self, __other: _BoolLike) -> _GenericType_co: ... @overload # platform dependent - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> int_: ... @overload def __call__(self, __other: _IntType) -> _IntType: ... @@ -93,7 +95,7 @@ class _BoolSub(Protocol): @overload def __call__(self, __other: bool) -> NoReturn: ... @overload # platform dependent - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> int_: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -113,7 +115,7 @@ class _BoolMod(Protocol): @overload def __call__(self, __other: _BoolLike) -> int8: ... @overload # platform dependent - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> int_: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -125,7 +127,7 @@ class _BoolDivMod(Protocol): @overload def __call__(self, __other: _BoolLike) -> _2Tuple[int8]: ... @overload # platform dependent - def __call__(self, __other: int) -> _2Tuple[signedinteger[Any]]: ... + def __call__(self, __other: int) -> _2Tuple[int_]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload @@ -143,7 +145,7 @@ class _IntTrueDiv(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> floating[_NBit_co]: ... @overload - def __call__(self, __other: int) -> floating[Any]: ... + def __call__(self, __other: int) -> floating[_NBitInt]: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -212,7 +214,7 @@ class _SignedIntOp(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... @overload - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -226,7 +228,7 @@ class _SignedIntBitOp(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... @overload - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... @overload def __call__( self, __other: signedinteger[_NBit] @@ -236,7 +238,7 @@ class _SignedIntMod(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... @overload - def __call__(self, __other: int) -> signedinteger[Any]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -248,7 +250,7 @@ class _SignedIntDivMod(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ... @overload - def __call__(self, __other: int) -> _2Tuple[signedinteger[Any]]: ... + def __call__(self, __other: int) -> _2Tuple[signedinteger[Union[_NBit_co, _NBitInt]]]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload @@ -260,7 +262,7 @@ class _FloatOp(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> floating[_NBit_co]: ... @overload - def __call__(self, __other: int) -> floating[Any]: ... + def __call__(self, __other: int) -> floating[Union[_NBit_co, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -274,7 +276,7 @@ class _FloatMod(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> floating[_NBit_co]: ... @overload - def __call__(self, __other: int) -> floating[Any]: ... + def __call__(self, __other: int) -> floating[Union[_NBit_co, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload @@ -286,7 +288,7 @@ class _FloatDivMod(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> _2Tuple[floating[_NBit_co]]: ... @overload - def __call__(self, __other: int) -> _2Tuple[floating[Any]]: ... + def __call__(self, __other: int) -> _2Tuple[floating[Union[_NBit_co, _NBitInt]]]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload @@ -298,7 +300,7 @@ class _ComplexOp(Protocol[_NBit_co]): @overload def __call__(self, __other: bool) -> complexfloating[_NBit_co, _NBit_co]: ... @overload - def __call__(self, __other: int) -> complexfloating[Any, Any]: ... + def __call__(self, __other: int) -> complexfloating[Union[_NBit_co, _NBitInt], Union[_NBit_co, _NBitInt]]: ... @overload def __call__(self, __other: Union[float, complex]) -> complex128: ... @overload diff --git a/numpy/typing/tests/data/reveal/arithmetic.py b/numpy/typing/tests/data/reveal/arithmetic.py index 20310e691647..de88602f3265 100644 --- a/numpy/typing/tests/data/reveal/arithmetic.py +++ b/numpy/typing/tests/data/reveal/arithmetic.py @@ -126,7 +126,7 @@ reveal_type(c16 + b) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(c16 + c) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(c16 + f) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] -reveal_type(c16 + i) # E: numpy.complexfloating[Any, Any] +reveal_type(c16 + i) # E: numpy.complexfloating[numpy.typing._ reveal_type(c16 + AR) # E: Any reveal_type(c16 + c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] @@ -139,7 +139,7 @@ reveal_type(b + c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(c + c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f + c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] -reveal_type(i + c16) # E: numpy.complexfloating[Any, Any] +reveal_type(i + c16) # E: numpy.complexfloating[numpy.typing._ reveal_type(AR + c16) # E: Any reveal_type(c8 + c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] @@ -152,7 +152,7 @@ reveal_type(c8 + b) # E: numpy.complexfloating[numpy.typing._32Bit, numpy.typing._32Bit] reveal_type(c8 + c) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(c8 + f) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] -reveal_type(c8 + i) # E: numpy.complexfloating[Any, Any] +reveal_type(c8 + i) # E: numpy.complexfloating[numpy.typing._ reveal_type(c8 + AR) # E: Any reveal_type(c16 + c8) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] @@ -165,7 +165,7 @@ reveal_type(b + c8) # E: numpy.complexfloating[numpy.typing._32Bit, numpy.typing._32Bit] reveal_type(c + c8) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f + c8) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] -reveal_type(i + c8) # E: numpy.complexfloating[Any, Any] +reveal_type(i + c8) # E: numpy.complexfloating[numpy.typing._ reveal_type(AR + c8) # E: Any # Float @@ -178,7 +178,7 @@ reveal_type(f8 + b) # E: numpy.floating[numpy.typing._64Bit] reveal_type(f8 + c) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f8 + f) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(f8 + i) # E: numpy.floating[Any] +reveal_type(f8 + i) # E: numpy.floating[numpy.typing._ reveal_type(f8 + AR) # E: Any reveal_type(f8 + f8) # E: numpy.floating[numpy.typing._64Bit] @@ -189,7 +189,7 @@ reveal_type(b + f8) # E: numpy.floating[numpy.typing._64Bit] reveal_type(c + f8) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f + f8) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(i + f8) # E: numpy.floating[Any] +reveal_type(i + f8) # E: numpy.floating[numpy.typing._ reveal_type(AR + f8) # E: Any reveal_type(f4 + f8) # E: numpy.floating[numpy.typing._64Bit] @@ -200,7 +200,7 @@ reveal_type(f4 + b) # E: numpy.floating[numpy.typing._32Bit] reveal_type(f4 + c) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f4 + f) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(f4 + i) # E: numpy.floating[Any] +reveal_type(f4 + i) # E: numpy.floating[numpy.typing._ reveal_type(f4 + AR) # E: Any reveal_type(f8 + f4) # E: numpy.floating[numpy.typing._64Bit] @@ -211,7 +211,7 @@ reveal_type(b + f4) # E: umpy.floating[numpy.typing._32Bit] reveal_type(c + f4) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f + f4) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(i + f4) # E: numpy.floating[Any] +reveal_type(i + f4) # E: numpy.floating[numpy.typing._ reveal_type(AR + f4) # E: Any # Int @@ -224,7 +224,7 @@ reveal_type(i8 + b) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(i8 + c) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(i8 + f) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(i8 + i) # E: numpy.signedinteger[Any] +reveal_type(i8 + i) # E: numpy.signedinteger[numpy.typing._ reveal_type(i8 + AR) # E: Any reveal_type(u8 + u8) # E: numpy.unsignedinteger[numpy.typing._64Bit] @@ -245,7 +245,7 @@ reveal_type(b + i8) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(c + i8) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(f + i8) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(i + i8) # E: numpy.signedinteger[Any] +reveal_type(i + i8) # E: numpy.signedinteger[numpy.typing._ reveal_type(AR + i8) # E: Any reveal_type(u8 + u8) # E: numpy.unsignedinteger[numpy.typing._64Bit] @@ -260,7 +260,7 @@ reveal_type(i4 + i8) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(i4 + i4) # E: numpy.signedinteger[numpy.typing._32Bit] -reveal_type(i4 + i) # E: numpy.signedinteger[Any] +reveal_type(i4 + i) # E: numpy.signedinteger[numpy.typing._ reveal_type(i4 + b_) # E: numpy.signedinteger[numpy.typing._32Bit] reveal_type(i4 + b) # E: numpy.signedinteger[numpy.typing._32Bit] reveal_type(i4 + AR) # E: Any @@ -276,7 +276,7 @@ reveal_type(i8 + i4) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(i4 + i4) # E: numpy.signedinteger[numpy.typing._32Bit] -reveal_type(i + i4) # E: numpy.signedinteger[Any] +reveal_type(i + i4) # E: numpy.signedinteger[numpy.typing._ reveal_type(b_ + i4) # E: numpy.signedinteger[numpy.typing._32Bit] reveal_type(b + i4) # E: numpy.signedinteger[numpy.typing._32Bit] reveal_type(AR + i4) # E: Any diff --git a/numpy/typing/tests/data/reveal/bitwise_ops.py b/numpy/typing/tests/data/reveal/bitwise_ops.py index cb9131a96938..af49244834f9 100644 --- a/numpy/typing/tests/data/reveal/bitwise_ops.py +++ b/numpy/typing/tests/data/reveal/bitwise_ops.py @@ -39,11 +39,11 @@ reveal_type(i8 ^ i4) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(i8 & i4) # E: numpy.signedinteger[numpy.typing._64Bit] -reveal_type(i8 << i) # E: numpy.signedinteger[Any] -reveal_type(i8 >> i) # E: numpy.signedinteger[Any] -reveal_type(i8 | i) # E: numpy.signedinteger[Any] -reveal_type(i8 ^ i) # E: numpy.signedinteger[Any] -reveal_type(i8 & i) # E: numpy.signedinteger[Any] +reveal_type(i8 << i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(i8 >> i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(i8 | i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(i8 ^ i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(i8 & i) # E: numpy.signedinteger[numpy.typing._ reveal_type(i8 << b_) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(i8 >> b_) # E: numpy.signedinteger[numpy.typing._64Bit] @@ -117,11 +117,11 @@ reveal_type(b_ ^ b) # E: numpy.bool_ reveal_type(b_ & b) # E: numpy.bool_ -reveal_type(b_ << i) # E: numpy.signedinteger[Any] -reveal_type(b_ >> i) # E: numpy.signedinteger[Any] -reveal_type(b_ | i) # E: numpy.signedinteger[Any] -reveal_type(b_ ^ i) # E: numpy.signedinteger[Any] -reveal_type(b_ & i) # E: numpy.signedinteger[Any] +reveal_type(b_ << i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(b_ >> i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(b_ | i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(b_ ^ i) # E: numpy.signedinteger[numpy.typing._ +reveal_type(b_ & i) # E: numpy.signedinteger[numpy.typing._ reveal_type(~i8) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(~i4) # E: numpy.signedinteger[numpy.typing._32Bit] diff --git a/numpy/typing/tests/data/reveal/mod.py b/numpy/typing/tests/data/reveal/mod.py index 4292041f8302..3330cf175922 100644 --- a/numpy/typing/tests/data/reveal/mod.py +++ b/numpy/typing/tests/data/reveal/mod.py @@ -34,7 +34,7 @@ # Bool reveal_type(b_ % b) # E: numpy.signedinteger[numpy.typing._8Bit] -reveal_type(b_ % i) # E: numpy.signedinteger[Any] +reveal_type(b_ % i) # E: numpy.signedinteger[numpy.typing._ reveal_type(b_ % f) # E: numpy.floating[numpy.typing._64Bit] reveal_type(b_ % b_) # E: numpy.signedinteger[numpy.typing._8Bit] reveal_type(b_ % i8) # E: numpy.signedinteger[numpy.typing._64Bit] @@ -43,7 +43,7 @@ reveal_type(b_ % AR) # E: Any reveal_type(divmod(b_, b)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]] -reveal_type(divmod(b_, i)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]] +reveal_type(divmod(b_, i)) # E: Tuple[numpy.signedinteger[numpy.typing._ reveal_type(divmod(b_, f)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(b_, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]] reveal_type(divmod(b_, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]] @@ -52,7 +52,7 @@ reveal_type(divmod(b_, AR)) # E: Tuple[Any, Any] reveal_type(b % b_) # E: numpy.signedinteger[numpy.typing._8Bit] -reveal_type(i % b_) # E: numpy.signedinteger[Any] +reveal_type(i % b_) # E: numpy.signedinteger[numpy.typing._ reveal_type(f % b_) # E: numpy.floating[numpy.typing._64Bit] reveal_type(b_ % b_) # E: numpy.signedinteger[numpy.typing._8Bit] reveal_type(i8 % b_) # E: numpy.signedinteger[numpy.typing._64Bit] @@ -61,7 +61,7 @@ reveal_type(AR % b_) # E: Any reveal_type(divmod(b, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]] -reveal_type(divmod(i, b_)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]] +reveal_type(divmod(i, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._ reveal_type(divmod(f, b_)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(b_, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]] reveal_type(divmod(i8, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]] @@ -72,7 +72,7 @@ # int reveal_type(i8 % b) # E: numpy.signedinteger[numpy.typing._64Bit] -reveal_type(i8 % i) # E: numpy.signedinteger[Any] +reveal_type(i8 % i) # E: numpy.signedinteger[numpy.typing._ reveal_type(i8 % f) # E: numpy.floating[numpy.typing._64Bit] reveal_type(i8 % i8) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(i8 % f8) # E: numpy.floating[numpy.typing._64Bit] @@ -83,7 +83,7 @@ reveal_type(i8 % AR) # E: Any reveal_type(divmod(i8, b)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]] -reveal_type(divmod(i8, i)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]] +reveal_type(divmod(i8, i)) # E: Tuple[numpy.signedinteger[numpy.typing._ reveal_type(divmod(i8, f)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(i8, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]] reveal_type(divmod(i8, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] @@ -94,7 +94,7 @@ reveal_type(divmod(i8, AR)) # E: Tuple[Any, Any] reveal_type(b % i8) # E: numpy.signedinteger[numpy.typing._64Bit] -reveal_type(i % i8) # E: numpy.signedinteger[Any] +reveal_type(i % i8) # E: numpy.signedinteger[numpy.typing._ reveal_type(f % i8) # E: numpy.floating[numpy.typing._64Bit] reveal_type(i8 % i8) # E: numpy.signedinteger[numpy.typing._64Bit] reveal_type(f8 % i8) # E: numpy.floating[numpy.typing._64Bit] @@ -105,7 +105,7 @@ reveal_type(AR % i8) # E: Any reveal_type(divmod(b, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]] -reveal_type(divmod(i, i8)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]] +reveal_type(divmod(i, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._ reveal_type(divmod(f, i8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(i8, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]] reveal_type(divmod(f8, i8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] @@ -118,14 +118,14 @@ # float reveal_type(f8 % b) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(f8 % i) # E: numpy.floating[Any] +reveal_type(f8 % i) # E: numpy.floating[numpy.typing._ reveal_type(f8 % f) # E: numpy.floating[numpy.typing._64Bit] reveal_type(i8 % f4) # E: numpy.floating[numpy.typing._64Bit] reveal_type(f4 % f4) # E: numpy.floating[numpy.typing._32Bit] reveal_type(f8 % AR) # E: Any reveal_type(divmod(f8, b)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] -reveal_type(divmod(f8, i)) # E: Tuple[numpy.floating[Any], numpy.floating[Any]] +reveal_type(divmod(f8, i)) # E: Tuple[numpy.floating[numpy.typing._ reveal_type(divmod(f8, f)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(f8, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(f8, f4)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] @@ -133,7 +133,7 @@ reveal_type(divmod(f8, AR)) # E: Tuple[Any, Any] reveal_type(b % f8) # E: numpy.floating[numpy.typing._64Bit] -reveal_type(i % f8) # E: numpy.floating[Any] +reveal_type(i % f8) # E: numpy.floating[numpy.typing._ reveal_type(f % f8) # E: numpy.floating[numpy.typing._64Bit] reveal_type(f8 % f8) # E: numpy.floating[numpy.typing._64Bit] reveal_type(f8 % f8) # E: numpy.floating[numpy.typing._64Bit] @@ -141,7 +141,7 @@ reveal_type(AR % f8) # E: Any reveal_type(divmod(b, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] -reveal_type(divmod(i, f8)) # E: Tuple[numpy.floating[Any], numpy.floating[Any]] +reveal_type(divmod(i, f8)) # E: Tuple[numpy.floating[numpy.typing._ reveal_type(divmod(f, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(f8, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] reveal_type(divmod(f4, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]] From dd7e9ad06a2696378f1b501ad44bb3a5094e5a25 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Wed, 25 Nov 2020 12:14:56 +0100 Subject: [PATCH 05/13] DOC,STY: Fixed a few typos and the likes --- numpy/typing/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py index 9f8e27573ba2..0d9c17d10c32 100644 --- a/numpy/typing/__init__.py +++ b/numpy/typing/__init__.py @@ -91,7 +91,7 @@ >>> x.dtype = np.bool_ This sort of mutation is not allowed by the types. Users who want to -write statically typed code should insted use the `numpy.ndarray.view` +write statically typed code should instead use the `numpy.ndarray.view` method to create a view of the array with a different dtype. DTypeLike @@ -104,15 +104,15 @@ >>> x = np.dtype({"field1": (float, 1), "field2": (int, 3)}) -Although this is valid Numpy code, the type checker will complain about it, +Although this is valid NumPy code, the type checker will complain about it, since its usage is discouraged. Please see : :ref:`Data type objects ` -Number Precision +Number precision ~~~~~~~~~~~~~~~~ The precision of `numpy.number` subclasses is treated as a covariant generic -parameter (see :class:`~NBitBase`), simplifying the annoting of proccesses +parameter (see :class:`~NBitBase`), simplifying the annotating of processes involving precision-based casting. .. code-block:: python @@ -171,7 +171,7 @@ class NBitBase: An object representing `numpy.number` precision during static type checking. Used exclusively for the purpose static type checking, `NBitBase` - represents the base of a hierachieral set of subclasses. + 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``. From 0917df2953ebe716c45c92671cb652eacd7dd8fd Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Wed, 25 Nov 2020 13:51:58 +0100 Subject: [PATCH 06/13] DOC: Add a docstring to the mypy plugin entry-point --- numpy/typing/mypy_plugin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/numpy/typing/mypy_plugin.py b/numpy/typing/mypy_plugin.py index 023ab5fd18f3..5110e3707506 100644 --- a/numpy/typing/mypy_plugin.py +++ b/numpy/typing/mypy_plugin.py @@ -55,4 +55,5 @@ def get_type_analyze_hook(self, fullname: str) -> t.Optional[HookFunc]: def plugin(version: str) -> t.Type[_NumpyPlugin]: + """An entry-point for mypy.""" return _NumpyPlugin From fd17d1eb73b93facafac84ecc24f3117de5247b4 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Wed, 25 Nov 2020 13:59:33 +0100 Subject: [PATCH 07/13] TST: Add `numpy.typing.mypy_plugin` to the list of public modules --- numpy/tests/test_public_api.py | 1 + numpy/typing/mypy_plugin.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py index 7b2a590c3872..69430eeda089 100644 --- a/numpy/tests/test_public_api.py +++ b/numpy/tests/test_public_api.py @@ -170,6 +170,7 @@ def test_NPY_NO_EXPORT(): "random", "testing", "typing", + "typing.mypy_plugin", "version", ]] diff --git a/numpy/typing/mypy_plugin.py b/numpy/typing/mypy_plugin.py index 5110e3707506..3418701675e5 100644 --- a/numpy/typing/mypy_plugin.py +++ b/numpy/typing/mypy_plugin.py @@ -8,6 +8,8 @@ from mypy.types import Type from mypy.plugin import Plugin, AnalyzeTypeContext +__all__: t.List[str] = [] + HookFunc = t.Callable[[AnalyzeTypeContext], Type] From 8685cf3ad8faa3dc2828be59fa45351456f55aee Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Wed, 25 Nov 2020 15:24:43 +0100 Subject: [PATCH 08/13] MAINT,TST: Fixed a failure due platform-dependent precisions --- numpy/typing/tests/data/reveal/dtype.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/numpy/typing/tests/data/reveal/dtype.py b/numpy/typing/tests/data/reveal/dtype.py index 626a15270a25..f786637dc9fd 100644 --- a/numpy/typing/tests/data/reveal/dtype.py +++ b/numpy/typing/tests/data/reveal/dtype.py @@ -15,15 +15,15 @@ reveal_type(np.dtype("str")) # E: numpy.dtype[numpy.str_] # Python types -reveal_type(np.dtype(complex)) # E: numpy.dtype[numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit]] -reveal_type(np.dtype(float)) # E: numpy.dtype[numpy.floating[numpy.typing._64Bit]] -reveal_type(np.dtype(int)) # E: numpy.dtype +reveal_type(np.dtype(complex)) # E: numpy.dtype[numpy.complexfloating[numpy.typing._ +reveal_type(np.dtype(float)) # E: numpy.dtype[numpy.floating[numpy.typing._ +reveal_type(np.dtype(int)) # E: numpy.dtype[numpy.signedinteger[numpy.typing._ reveal_type(np.dtype(bool)) # E: numpy.dtype[numpy.bool_] reveal_type(np.dtype(str)) # E: numpy.dtype[numpy.str_] reveal_type(np.dtype(bytes)) # E: numpy.dtype[numpy.bytes_] # Special case for None -reveal_type(np.dtype(None)) # E: numpy.dtype[numpy.floating[numpy.typing._64Bit]] +reveal_type(np.dtype(None)) # E: numpy.dtype[numpy.floating[numpy.typing._ # Dtypes of dtypes reveal_type(np.dtype(np.dtype(np.float64))) # E: numpy.dtype[numpy.floating[numpy.typing._64Bit]] From 92e549fc1c02e86363daf9de5945d2fb5259951c Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Wed, 25 Nov 2020 15:27:14 +0100 Subject: [PATCH 09/13] MAINT: Import `mypy` via a try/except approach Fixes an issue where the `pypy` tests would fail --- numpy/typing/mypy_plugin.py | 38 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/numpy/typing/mypy_plugin.py b/numpy/typing/mypy_plugin.py index 3418701675e5..505a01a0bb1d 100644 --- a/numpy/typing/mypy_plugin.py +++ b/numpy/typing/mypy_plugin.py @@ -4,14 +4,17 @@ import numpy as np -import mypy.types -from mypy.types import Type -from mypy.plugin import Plugin, AnalyzeTypeContext +try: + import mypy.types + from mypy.types import Type + from mypy.plugin import Plugin, AnalyzeTypeContext + _HookFunc = t.Callable[[AnalyzeTypeContext], Type] + MYPY_EX: t.Optional[ModuleNotFoundError] = None +except ModuleNotFoundError as ex: + MYPY_EX = ex __all__: t.List[str] = [] -HookFunc = t.Callable[[AnalyzeTypeContext], Type] - def _get_precision_dict() -> t.Dict[str, str]: names = [ @@ -39,7 +42,7 @@ def _get_precision_dict() -> t.Dict[str, str]: _PRECISION_DICT = _get_precision_dict() -def _hook(ctx: AnalyzeTypeContext) -> Type: +def _hook(ctx: "AnalyzeTypeContext") -> "Type": """Replace a type-alias with a concrete ``NBitBase`` subclass.""" typ, _, api = ctx name = typ.name.split(".")[-1] @@ -47,15 +50,20 @@ def _hook(ctx: AnalyzeTypeContext) -> Type: return api.named_type(name_new) -class _NumpyPlugin(Plugin): - """A plugin for assigning platform-specific `numpy.number` precisions.""" +if MYPY_EX is None: + class _NumpyPlugin(Plugin): + """A plugin for assigning platform-specific `numpy.number` precisions.""" - def get_type_analyze_hook(self, fullname: str) -> t.Optional[HookFunc]: - if fullname in _PRECISION_DICT: - return _hook - return None + def get_type_analyze_hook(self, fullname: str) -> t.Optional[_HookFunc]: + if fullname in _PRECISION_DICT: + return _hook + return None + def plugin(version: str) -> t.Type[_NumpyPlugin]: + """An entry-point for mypy.""" + return _NumpyPlugin -def plugin(version: str) -> t.Type[_NumpyPlugin]: - """An entry-point for mypy.""" - return _NumpyPlugin +else: + def plugin(version: str) -> t.Type["_NumpyPlugin"]: + """An entry-point for mypy.""" + raise MYPY_EX From 9fa57fd482e113c089cc9aae8ac4200ac877455e Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Fri, 27 Nov 2020 12:27:56 +0100 Subject: [PATCH 10/13] ENH: Add unit support to the `datetime64`/`timedelta64` character codes --- numpy/typing/_char_codes.py | 72 +++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/numpy/typing/_char_codes.py b/numpy/typing/_char_codes.py index 7e5b82cfaf73..143644e88de5 100644 --- a/numpy/typing/_char_codes.py +++ b/numpy/typing/_char_codes.py @@ -55,14 +55,74 @@ _CDoubleCodes = Literal["cdouble" "complex", "complex_", "cfloat", "D", "=D", "D"] _CLongDoubleCodes = Literal["clongdouble", "clongfloat", "longcomplex", "G", "=G", "G"] - _DT64Codes = Literal["datetime64", "M", "=M", "M"] - _TD64Codes = Literal["timedelta64", "m", "=m", "m"] - _StrCodes = Literal["str", "str_", "str0", "unicode", "unicode_", "U", "=U", "U"] _BytesCodes = Literal["bytes", "bytes_", "bytes0", "S", "=S", "S"] _VoidCodes = Literal["void", "void0", "V", "=V", "V"] _ObjectCodes = Literal["object", "object_", "O", "=O", "O"] + _DT64Codes = Literal[ + "datetime64", "=datetime64", "datetime64", + "datetime64[Y]", "=datetime64[Y]", "datetime64[Y]", + "datetime64[M]", "=datetime64[M]", "datetime64[M]", + "datetime64[W]", "=datetime64[W]", "datetime64[W]", + "datetime64[D]", "=datetime64[D]", "datetime64[D]", + "datetime64[h]", "=datetime64[h]", "datetime64[h]", + "datetime64[m]", "=datetime64[m]", "datetime64[m]", + "datetime64[s]", "=datetime64[s]", "datetime64[s]", + "datetime64[ms]", "=datetime64[ms]", "datetime64[ms]", + "datetime64[us]", "=datetime64[us]", "datetime64[us]", + "datetime64[ns]", "=datetime64[ns]", "datetime64[ns]", + "datetime64[ps]", "=datetime64[ps]", "datetime64[ps]", + "datetime64[fs]", "=datetime64[fs]", "datetime64[fs]", + "datetime64[as]", "=datetime64[as]", "datetime64[as]", + "M", "=M", "M", + "M8", "=M8", "M8", + "M8[Y]", "=M8[Y]", "M8[Y]", + "M8[M]", "=M8[M]", "M8[M]", + "M8[W]", "=M8[W]", "M8[W]", + "M8[D]", "=M8[D]", "M8[D]", + "M8[h]", "=M8[h]", "M8[h]", + "M8[m]", "=M8[m]", "M8[m]", + "M8[s]", "=M8[s]", "M8[s]", + "M8[ms]", "=M8[ms]", "M8[ms]", + "M8[us]", "=M8[us]", "M8[us]", + "M8[ns]", "=M8[ns]", "M8[ns]", + "M8[ps]", "=M8[ps]", "M8[ps]", + "M8[fs]", "=M8[fs]", "M8[fs]", + "M8[as]", "=M8[as]", "M8[as]", + ] + _TD64Codes = Literal[ + "timedelta64", "=timedelta64", "timedelta64", + "timedelta64[Y]", "=timedelta64[Y]", "timedelta64[Y]", + "timedelta64[M]", "=timedelta64[M]", "timedelta64[M]", + "timedelta64[W]", "=timedelta64[W]", "timedelta64[W]", + "timedelta64[D]", "=timedelta64[D]", "timedelta64[D]", + "timedelta64[h]", "=timedelta64[h]", "timedelta64[h]", + "timedelta64[m]", "=timedelta64[m]", "timedelta64[m]", + "timedelta64[s]", "=timedelta64[s]", "timedelta64[s]", + "timedelta64[ms]", "=timedelta64[ms]", "timedelta64[ms]", + "timedelta64[us]", "=timedelta64[us]", "timedelta64[us]", + "timedelta64[ns]", "=timedelta64[ns]", "timedelta64[ns]", + "timedelta64[ps]", "=timedelta64[ps]", "timedelta64[ps]", + "timedelta64[fs]", "=timedelta64[fs]", "timedelta64[fs]", + "timedelta64[as]", "=timedelta64[as]", "timedelta64[as]", + "m", "=m", "m", + "m8", "=m8", "m8", + "m8[Y]", "=m8[Y]", "m8[Y]", + "m8[M]", "=m8[M]", "m8[M]", + "m8[W]", "=m8[W]", "m8[W]", + "m8[D]", "=m8[D]", "m8[D]", + "m8[h]", "=m8[h]", "m8[h]", + "m8[m]", "=m8[m]", "m8[m]", + "m8[s]", "=m8[s]", "m8[s]", + "m8[ms]", "=m8[ms]", "m8[ms]", + "m8[us]", "=m8[us]", "m8[us]", + "m8[ns]", "=m8[ns]", "m8[ns]", + "m8[ps]", "=m8[ps]", "m8[ps]", + "m8[fs]", "=m8[fs]", "m8[fs]", + "m8[as]", "=m8[as]", "m8[as]", + ] + else: _BoolCodes = Any @@ -106,10 +166,10 @@ _CDoubleCodes = Any _CLongDoubleCodes = Any - _DT64Codes = Any - _TD64Codes = Any - _StrCodes = Any _BytesCodes = Any _VoidCodes = Any _ObjectCodes = Any + + _DT64Codes = Any + _TD64Codes = Any From ba4ad04b356aac976cf7940d8885c66cdab0b706 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Mon, 30 Nov 2020 14:09:57 +0100 Subject: [PATCH 11/13] DOC: Add a comment about truncating and sub-string matching Co-Authored-By: Eric Wieser <425260+eric-wieser@users.noreply.github.com> --- numpy/typing/tests/data/reveal/arithmetic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/numpy/typing/tests/data/reveal/arithmetic.py b/numpy/typing/tests/data/reveal/arithmetic.py index de88602f3265..4d07e8dac069 100644 --- a/numpy/typing/tests/data/reveal/arithmetic.py +++ b/numpy/typing/tests/data/reveal/arithmetic.py @@ -126,6 +126,9 @@ reveal_type(c16 + b) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(c16 + c) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] reveal_type(c16 + f) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit] + +# note this comment is deliberate truncated as the result varies by platform, +# and the numpy `reveal` tests use substring matching reveal_type(c16 + i) # E: numpy.complexfloating[numpy.typing._ reveal_type(c16 + AR) # E: Any From 4b27d3a54d7c8dd4d2ae502f85a15d8bc529ba86 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Fri, 11 Dec 2020 21:45:00 +0100 Subject: [PATCH 12/13] Update mypy_plugin.py --- numpy/typing/mypy_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/typing/mypy_plugin.py b/numpy/typing/mypy_plugin.py index 505a01a0bb1d..bdd5c50f3389 100644 --- a/numpy/typing/mypy_plugin.py +++ b/numpy/typing/mypy_plugin.py @@ -32,7 +32,7 @@ def _get_precision_dict() -> t.Dict[str, str]: ] ret = {} for name, typ in names: - n: int = 8 * typ().dtype.alignment + n: int = 8 * typ().dtype.itemsize ret[f'numpy.typing._nbit.{name}'] = f"numpy._{n}Bit" return ret From 75c532dd95d7233de5a4f57554a88657380dc1ec Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Fri, 11 Dec 2020 22:09:06 +0100 Subject: [PATCH 13/13] REL: Added a release note --- .../upcoming_changes/17843.new_feature.rst | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 doc/release/upcoming_changes/17843.new_feature.rst diff --git a/doc/release/upcoming_changes/17843.new_feature.rst b/doc/release/upcoming_changes/17843.new_feature.rst new file mode 100644 index 000000000000..d2b9d2adc84c --- /dev/null +++ b/doc/release/upcoming_changes/17843.new_feature.rst @@ -0,0 +1,22 @@ +Added a mypy plugin for handling platform-specific `numpy.number` precisions +---------------------------------------------------------------------------- + +A mypy_ plugin is now available for automatically assigning the (platform-dependent) +precisions of certain `~numpy.number` subclasses, including the likes of +`~numpy.int_`, `~numpy.intp` and `~numpy.longlong`. See the documentation on +:ref:`scalar types ` for a comprehensive overview +of the affected classes. + +Note that while usage of the plugin is completely optional, without it the +precision of above-mentioned classes will be inferred as `~typing.Any`. + +To enable the plugin, one must add it to their mypy `configuration file`_: + +.. code-block:: ini + + [mypy] + plugins = numpy.typing.mypy_plugin + + +.. _mypy: http://mypy-lang.org/ +.. _configuration file: https://mypy.readthedocs.io/en/stable/config_file.html