diff --git a/numpy-stubs/__init__.pyi b/numpy-stubs/__init__.pyi index ab4d661..c9ab9d0 100644 --- a/numpy-stubs/__init__.pyi +++ b/numpy-stubs/__init__.pyi @@ -1,6 +1,7 @@ import builtins import sys import datetime as dt +from abc import abstractmethod from numpy.core._internal import _ctypes from numpy.typing import ArrayLike, DtypeLike, _Shape, _ShapeLike @@ -359,22 +360,33 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container): def __contains__(self, key) -> bool: ... def __index__(self) -> int: ... +# NOTE: while `np.generic` is not technically an instance of `ABCMeta`, +# the `@abstractmethod` decorator is herein used to (forcefully) deny +# the creation of `np.generic` instances. +# The `# type: ignore` comments are necessary to silence mypy errors regarding +# the missing `ABCMeta` metaclass. + +# See https://github.com/numpy/numpy-stubs/pull/80 for more details. + class generic(_ArrayOrScalarCommon): - def __init__(self, value: Any = ...) -> None: ... + @abstractmethod + def __init__(self, *args: Any, **kwargs: Any) -> None: ... @property def base(self) -> None: ... -class _real_generic(generic): +class _real_generic(generic): # type: ignore @property def real(self: _ArraySelf) -> _ArraySelf: ... @property def imag(self: _ArraySelf) -> _ArraySelf: ... -class number(generic): - def __init__(self, value: Union[SupportsInt, SupportsFloat] = ...) -> None: ... +class number(generic): ... # type: ignore + +class bool_(_real_generic): + def __init__(self, value: object = ...) -> None: ... -class bool_(_real_generic): ... -class object_(generic): ... +class object_(generic): + def __init__(self, value: object = ...) -> None: ... class datetime64: @overload @@ -386,8 +398,8 @@ class datetime64: def __add__(self, other: Union[timedelta64, int]) -> datetime64: ... def __sub__(self, other: Union[timedelta64, datetime64, int]) -> timedelta64: ... -class integer(number, _real_generic): ... -class signedinteger(integer): ... +class integer(number, _real_generic): ... # type: ignore +class signedinteger(integer): ... # type: ignore class int8(signedinteger): def __init__(self, value: SupportsInt = ...) -> None: ... @@ -419,7 +431,7 @@ class timedelta64(signedinteger): def __truediv__(self, other: float) -> timedelta64: ... def __mod__(self, other: timedelta64) -> timedelta64: ... -class unsignedinteger(integer): ... +class unsignedinteger(integer): ... # type: ignore class uint8(unsignedinteger): def __init__(self, value: SupportsInt = ...) -> None: ... @@ -433,34 +445,60 @@ class uint32(unsignedinteger): class uint64(unsignedinteger): def __init__(self, value: SupportsInt = ...) -> None: ... -class inexact(number): ... -class floating(inexact, _real_generic): ... -class float16(floating): ... -class float32(floating): ... -class float64(floating): ... +class inexact(number): ... # type: ignore +class floating(inexact, _real_generic): ... # type: ignore -class complexfloating(inexact): - def __init__( - self, value: Union[SupportsInt, SupportsFloat, SupportsComplex, complex] = ... - ) -> None: ... +class float16(floating): + def __init__(self, value: SupportsFloat = ...) -> None: ... + +class float32(floating): + def __init__(self, value: SupportsFloat = ...) -> None: ... + +class float64(floating): + def __init__(self, value: SupportsFloat = ...) -> None: ... + +class complexfloating(inexact): ... # type: ignore class complex64(complexfloating): + def __init__( + self, value: Union[SupportsInt, SupportsFloat, SupportsComplex] = ... + ) -> None: ... @property def real(self) -> float32: ... @property def imag(self) -> float32: ... class complex128(complexfloating): + def __init__( + self, value: Union[SupportsInt, SupportsFloat, SupportsComplex] = ... + ) -> None: ... @property def real(self) -> float64: ... @property def imag(self) -> float64: ... -class flexible(_real_generic): ... -class void(flexible): ... -class character(_real_generic): ... -class bytes_(character): ... -class str_(character): ... +class flexible(_real_generic): ... # type: ignore + +class void(flexible): + def __init__(self, value: Union[int, integer, bool_, bytes, bytes_]): ... + +class character(_real_generic): ... # type: ignore + +class bytes_(character): + @overload + def __init__(self, value: object = ...) -> None: ... + @overload + def __init__( + self, value: object, encoding: str = ..., errors: str = ... + ) -> None: ... + +class str_(character): + @overload + def __init__(self, value: object = ...) -> None: ... + @overload + def __init__( + self, value: object, encoding: str = ..., errors: str = ... + ) -> None: ... # TODO(alan): Platform dependent types # longcomplex, longdouble, longfloat diff --git a/tests/fail/scalars.py b/tests/fail/scalars.py index 517e8f2..0dfc551 100644 --- a/tests/fail/scalars.py +++ b/tests/fail/scalars.py @@ -52,3 +52,16 @@ def __float__(self): np.uint16(A()) # E: incompatible type np.uint32(A()) # E: incompatible type np.uint64(A()) # E: incompatible type + +np.void("test") # E: incompatible type + +np.generic(1) # E: Cannot instantiate abstract class +np.number(1) # E: Cannot instantiate abstract class +np.integer(1) # E: Cannot instantiate abstract class +np.signedinteger(1) # E: Cannot instantiate abstract class +np.unsignedinteger(1) # E: Cannot instantiate abstract class +np.inexact(1) # E: Cannot instantiate abstract class +np.floating(1) # E: Cannot instantiate abstract class +np.complexfloating(1) # E: Cannot instantiate abstract class +np.character("test") # E: Cannot instantiate abstract class +np.flexible(b"test") # E: Cannot instantiate abstract class diff --git a/tests/pass/ndarray_conversion.py b/tests/pass/ndarray_conversion.py index 2662cb5..d923602 100644 --- a/tests/pass/ndarray_conversion.py +++ b/tests/pass/ndarray_conversion.py @@ -1,3 +1,4 @@ +import os import tempfile import numpy as np @@ -28,15 +29,16 @@ nd.tobytes(None) # tofile -with tempfile.NamedTemporaryFile(suffix=".txt") as tmp: - nd.tofile(tmp.name) - nd.tofile(tmp.name, "") - nd.tofile(tmp.name, sep="") +if os.name != "nt": + with tempfile.NamedTemporaryFile(suffix=".txt") as tmp: + nd.tofile(tmp.name) + nd.tofile(tmp.name, "") + nd.tofile(tmp.name, sep="") - nd.tofile(tmp.name, "", "%s") - nd.tofile(tmp.name, format="%s") + nd.tofile(tmp.name, "", "%s") + nd.tofile(tmp.name, format="%s") - nd.tofile(tmp) + nd.tofile(tmp) # dump is pretty simple # dumps is pretty simple diff --git a/tests/pass/scalars.py b/tests/pass/scalars.py index e4be14e..bd05567 100644 --- a/tests/pass/scalars.py +++ b/tests/pass/scalars.py @@ -19,6 +19,8 @@ def __float__(self): np.complex64(3j) np.complex64(C()) +np.complex128(3j) +np.complex128(C()) np.int8(4) np.int16(3.4) @@ -77,3 +79,10 @@ def __float__(self): td_64 / 1.0 td_64 / td_64 td_64 % td_64 + +np.void(1) +np.void(np.int64(1)) +np.void(True) +np.void(np.bool_(True)) +np.void(b"test") +np.void(np.bytes_("test"))