diff --git a/.gitignore b/.gitignore index d856762492df..52997523cdea 100644 --- a/.gitignore +++ b/.gitignore @@ -220,3 +220,4 @@ numpy/core/src/umath/loops_arithm_fp.dispatch.c numpy/core/src/umath/loops_arithmetic.dispatch.c numpy/core/src/umath/loops_trigonometric.dispatch.c numpy/core/src/umath/loops_exponent_log.dispatch.c +numpy/core/src/umath/loops_umath_fp.dispatch.c diff --git a/doc/release/upcoming_changes/20201.deprecation.rst b/doc/release/upcoming_changes/20201.deprecation.rst new file mode 100644 index 000000000000..db8cda21f675 --- /dev/null +++ b/doc/release/upcoming_changes/20201.deprecation.rst @@ -0,0 +1,5 @@ +The ``np.MachAr`` class has been deprecated +------------------------------------------- +The `~numpy.MachAr` class and `finfo.machar ` attribute have +been deprecated. Users are encouraged to access the property if interest +directly from the corresponding `~numpy.finfo` attribute. diff --git a/numpy/__init__.py b/numpy/__init__.py index 58adeaeab1c0..c34434e753aa 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -188,12 +188,19 @@ n: (getattr(_builtins, n), _msg.format(n=n, extended_msg=extended_msg)) for n, extended_msg in _type_info }) + # Numpy 1.20.0, 2020-10-19 __deprecated_attrs__["typeDict"] = ( core.numerictypes.typeDict, "`np.typeDict` is a deprecated alias for `np.sctypeDict`." ) + # NumPy 1.22, 2021-10-20 + __deprecated_attrs__["MachAr"] = ( + core._machar.MachAr, + "`np.MachAr` is deprecated (NumPy 1.22)." + ) + _msg = ( "`np.{n}` is a deprecated alias for `np.compat.{n}`. " "To silence this warning, use `np.compat.{n}` by itself. " diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 7abf9c62efb4..463d4a713a48 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -14,7 +14,6 @@ if sys.version_info >= (3, 9): from numpy._pytesttester import PytestTester from numpy.core._internal import _ctypes -from numpy.core.getlimits import MachArLike from numpy.typing import ( # Arrays @@ -665,17 +664,6 @@ test: PytestTester # their annotations are properly implemented # # Placeholders for classes -# TODO: Remove `__getattr__` once the classes are stubbed out -class MachAr: - def __init__( - self, - float_conv: Any = ..., - int_conv: Any = ..., - float_to_float: Any = ..., - float_to_str: Any = ..., - title: Any = ..., - ) -> None: ... - def __getattr__(self, key: str) -> Any: ... # Some of these are aliases; others are wrappers with an identical signature round = around @@ -3395,14 +3383,6 @@ class finfo(Generic[_FloatType]): def smallest_normal(self) -> _FloatType: ... @property def tiny(self) -> _FloatType: ... - - # NOTE: Not technically a property, but this is the only way we can - # access the precision of the underlying float - @property - def machar(self: finfo[floating[_NBit1]]) -> MachArLike[_NBit1]: ... - @machar.setter - def machar(self: finfo[floating[_NBit1]], value: MachArLike[_NBit1]) -> None: ... - @overload def __new__( cls, dtype: inexact[_NBit1] | _DTypeLike[inexact[_NBit1]] @@ -4335,3 +4315,6 @@ class chararray(ndarray[_ShapeType, _CharDType]): def isupper(self) -> ndarray[_ShapeType, dtype[bool_]]: ... def isnumeric(self) -> ndarray[_ShapeType, dtype[bool_]]: ... def isdecimal(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + +# NOTE: Deprecated +# class MachAr: ... diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index dad9293e1a19..332f9940ed78 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -9,6 +9,7 @@ from numpy.version import version as __version__ import os +import warnings # disables OpenBLAS affinity setting of the main thread that limits # python threads or processes to one core @@ -80,8 +81,8 @@ from .defchararray import chararray from . import function_base from .function_base import * -from . import machar -from .machar import * +from . import _machar +from ._machar import * from . import getlimits from .getlimits import * from . import shape_base @@ -109,7 +110,6 @@ __all__ += ['record', 'recarray', 'format_parser'] __all__ += ['chararray'] __all__ += function_base.__all__ -__all__ += machar.__all__ __all__ += getlimits.__all__ __all__ += shape_base.__all__ __all__ += einsumfunc.__all__ @@ -151,6 +151,17 @@ def _DType_reduce(DType): return _DType_reconstruct, (scalar_type,) +def __getattr__(name): + # Deprecated 2021-10-20, NumPy 1.22 + if name == "machar": + warnings.warn( + "The `np.core.machar` module is deprecated (NumPy 1.22)", + DeprecationWarning, stacklevel=2, + ) + return _machar + raise AttributeError(f"Module {__name__!r} has no attribute {name!r}") + + import copyreg copyreg.pickle(ufunc, _ufunc_reduce) diff --git a/numpy/core/machar.py b/numpy/core/_machar.py similarity index 99% rename from numpy/core/machar.py rename to numpy/core/_machar.py index c77be793fdbe..ace19a429f79 100644 --- a/numpy/core/machar.py +++ b/numpy/core/_machar.py @@ -13,6 +13,7 @@ # Need to speed this up...especially for longfloat +# Deprecated 2021-10-20, NumPy 1.22 @set_module('numpy') class MachAr: """ diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py index c96e6d5e7ec8..ab4a4d2be696 100644 --- a/numpy/core/getlimits.py +++ b/numpy/core/getlimits.py @@ -5,7 +5,7 @@ import warnings -from .machar import MachAr +from ._machar import MachAr from .overrides import set_module from . import numeric from . import numerictypes as ntypes @@ -385,6 +385,8 @@ class finfo: machar : MachAr The object which calculated these parameters and holds more detailed information. + + .. deprecated:: 1.22 machep : int The exponent that yields `eps`. max : floating point number of the appropriate type @@ -501,7 +503,7 @@ def _init(self, dtype): self.eps = machar.eps.flat[0] self.nexp = machar.iexp self.nmant = machar.it - self.machar = machar + self._machar = machar self._str_tiny = machar._str_xmin.strip() self._str_max = machar._str_xmax.strip() self._str_epsneg = machar._str_epsneg.strip() @@ -551,11 +553,11 @@ def smallest_normal(self): """ # This check is necessary because the value for smallest_normal is # platform dependent for longdouble types. - if isnan(self.machar.smallest_normal.flat[0]): + if isnan(self._machar.smallest_normal.flat[0]): warnings.warn( 'The value of smallest normal is undefined for double double', UserWarning, stacklevel=2) - return self.machar.smallest_normal.flat[0] + return self._machar.smallest_normal.flat[0] @property def tiny(self): @@ -574,6 +576,20 @@ def tiny(self): """ return self.smallest_normal + @property + def machar(self): + """The object which calculated these parameters and holds more + detailed information. + + .. deprecated:: 1.22 + """ + # Deprecated 2021-10-27, NumPy 1.22 + warnings.warn( + "`finfo.machar` is deprecated (NumPy 1.22)", + DeprecationWarning, stacklevel=2, + ) + return self._machar + @set_module('numpy') class iinfo: diff --git a/numpy/core/getlimits.pyi b/numpy/core/getlimits.pyi index ca22e18f7505..66d0629954d2 100644 --- a/numpy/core/getlimits.pyi +++ b/numpy/core/getlimits.pyi @@ -1,58 +1,8 @@ -from typing import Any, Generic, List, Type, TypeVar +from typing import List from numpy import ( finfo as finfo, iinfo as iinfo, - floating, - signedinteger, ) -from numpy.typing import NBitBase, NDArray - -_NBit = TypeVar("_NBit", bound=NBitBase) - __all__: List[str] - -class MachArLike(Generic[_NBit]): - def __init__( - self, - ftype: Type[floating[_NBit]], - *, - eps: floating[Any], - epsneg: floating[Any], - huge: floating[Any], - tiny: floating[Any], - ibeta: int, - smallest_subnormal: None | floating[Any] = ..., - # Expand `**kwargs` into keyword-only arguments - machep: int, - negep: int, - minexp: int, - maxexp: int, - it: int, - iexp: int, - irnd: int, - ngrd: int, - ) -> None: ... - @property - def smallest_subnormal(self) -> NDArray[floating[_NBit]]: ... - eps: NDArray[floating[_NBit]] - epsilon: NDArray[floating[_NBit]] - epsneg: NDArray[floating[_NBit]] - huge: NDArray[floating[_NBit]] - ibeta: signedinteger[_NBit] - iexp: int - irnd: int - it: int - machep: int - maxexp: int - minexp: int - negep: int - ngrd: int - precision: int - resolution: NDArray[floating[_NBit]] - smallest_normal: NDArray[floating[_NBit]] - tiny: NDArray[floating[_NBit]] - title: str - xmax: NDArray[floating[_NBit]] - xmin: NDArray[floating[_NBit]] diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 898ff8075351..a1b379d9274d 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -1215,3 +1215,18 @@ def test_deprecated(self, func): def test_not_deprecated(self, func): self.assert_not_deprecated(lambda: func(1)) self.assert_not_deprecated(lambda: func([0, 1])) + + +class TestMachAr(_DeprecationTestCase): + # Deprecated 2021-10-19, NumPy 1.22 + warning_cls = DeprecationWarning + + def test_deprecated(self): + self.assert_deprecated(lambda: np.MachAr) + + def test_deprecated_module(self): + self.assert_deprecated(lambda: getattr(np.core, "machar")) + + def test_deprecated_attr(self): + finfo = np.finfo(float) + self.assert_deprecated(lambda: getattr(finfo, "machar")) diff --git a/numpy/core/tests/test_getlimits.py b/numpy/core/tests/test_getlimits.py index de7b3e769394..c5148db2c715 100644 --- a/numpy/core/tests/test_getlimits.py +++ b/numpy/core/tests/test_getlimits.py @@ -46,7 +46,7 @@ def test_basic(self): [np.float16, np.float32, np.float64, np.complex64, np.complex128])) for dt1, dt2 in dts: - for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machar', 'machep', + for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machep', 'max', 'maxexp', 'min', 'minexp', 'negep', 'nexp', 'nmant', 'precision', 'resolution', 'tiny', 'smallest_normal', 'smallest_subnormal'): diff --git a/numpy/core/tests/test_machar.py b/numpy/core/tests/test_machar.py index 673f309f18c3..3a66ec51fd58 100644 --- a/numpy/core/tests/test_machar.py +++ b/numpy/core/tests/test_machar.py @@ -3,7 +3,7 @@ rid of both MachAr and this test at some point. """ -from numpy.core.machar import MachAr +from numpy.core._machar import MachAr import numpy.core.numerictypes as ntypes from numpy import errstate, array diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index a98c7016ae46..96173a482d69 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -646,7 +646,7 @@ def test_floating_exceptions(self, typecode): if np.dtype(ftype).kind == 'f': # Get some extreme values for the type fi = np.finfo(ftype) - ft_tiny = fi.machar.tiny + ft_tiny = fi._machar.tiny ft_max = fi.max ft_eps = fi.eps underflow = 'underflow' @@ -655,7 +655,7 @@ def test_floating_exceptions(self, typecode): # 'c', complex, corresponding real dtype rtype = type(ftype(0).real) fi = np.finfo(rtype) - ft_tiny = ftype(fi.machar.tiny) + ft_tiny = ftype(fi._machar.tiny) ft_max = ftype(fi.max) ft_eps = ftype(fi.eps) # The complex types raise different exceptions diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py index 73a93f4897d9..1e7d389d913a 100644 --- a/numpy/tests/test_public_api.py +++ b/numpy/tests/test_public_api.py @@ -178,7 +178,6 @@ def test_NPY_NO_EXPORT(): "core.fromnumeric", "core.function_base", "core.getlimits", - "core.machar", "core.memmap", "core.multiarray", "core.numeric", diff --git a/numpy/typing/tests/data/reveal/getlimits.pyi b/numpy/typing/tests/data/reveal/getlimits.pyi index e12723bfe646..90bcb06c8c6b 100644 --- a/numpy/typing/tests/data/reveal/getlimits.pyi +++ b/numpy/typing/tests/data/reveal/getlimits.pyi @@ -1,6 +1,4 @@ import numpy as np -from numpy.typing import _32Bit - f: float f8: np.float64 c8: np.complex64 @@ -11,7 +9,6 @@ u4: np.uint32 finfo_f8: np.finfo[np.float64] iinfo_i8: np.iinfo[np.int64] -machar_f4: np.core.getlimits.MachArLike[_32Bit] reveal_type(np.finfo(f)) # E: numpy.finfo[{double}] reveal_type(np.finfo(f8)) # E: numpy.finfo[{float64}] @@ -36,7 +33,6 @@ reveal_type(finfo_f8.resolution) # E: {float64} reveal_type(finfo_f8.tiny) # E: {float64} reveal_type(finfo_f8.smallest_normal) # E: {float64} reveal_type(finfo_f8.smallest_subnormal) # E: {float64} -reveal_type(finfo_f8.machar) # E: MachArLike[numpy.typing._64Bit] reveal_type(np.iinfo(i)) # E: iinfo[{int_}] reveal_type(np.iinfo(i8)) # E: iinfo[{int64}] @@ -49,25 +45,3 @@ reveal_type(iinfo_i8.bits) # E: int reveal_type(iinfo_i8.key) # E: str reveal_type(iinfo_i8.min) # E: int reveal_type(iinfo_i8.max) # E: int - -reveal_type(machar_f4.eps) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.epsilon) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.epsneg) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.huge) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.resolution) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.tiny) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.xmax) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.xmin) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.smallest_subnormal) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.smallest_normal) # E: numpy.ndarray[Any, numpy.dtype[{float32}]] -reveal_type(machar_f4.iexp) # E: int -reveal_type(machar_f4.irnd) # E: int -reveal_type(machar_f4.it) # E: int -reveal_type(machar_f4.machep) # E: int -reveal_type(machar_f4.maxexp) # E: int -reveal_type(machar_f4.minexp) # E: int -reveal_type(machar_f4.negep) # E: int -reveal_type(machar_f4.ngrd) # E: int -reveal_type(machar_f4.precision) # E: int -reveal_type(machar_f4.ibeta) # E: {int32} -reveal_type(machar_f4.title) # E: str