Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEP: Deprecate np.MachAr #20201

Merged
merged 5 commits into from Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -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
5 changes: 5 additions & 0 deletions 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 <numpy.finfo>` attribute have
been deprecated. Users are encouraged to access the property if interest
directly from the corresponding `~numpy.finfo` attribute.
7 changes: 7 additions & 0 deletions numpy/__init__.py
Expand Up @@ -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. "
Expand Down
23 changes: 3 additions & 20 deletions numpy/__init__.pyi
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]]
Expand Down Expand Up @@ -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: ...
17 changes: 14 additions & 3 deletions numpy/core/__init__.py
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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__
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions numpy/core/machar.py → numpy/core/_machar.py
Expand Up @@ -13,6 +13,7 @@

# Need to speed this up...especially for longfloat

# Deprecated 2021-10-20, NumPy 1.22
@set_module('numpy')
class MachAr:
"""
Expand Down
24 changes: 20 additions & 4 deletions numpy/core/getlimits.py
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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):
Expand All @@ -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:
Expand Down
52 changes: 1 addition & 51 deletions 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]]
15 changes: 15 additions & 0 deletions numpy/core/tests/test_deprecations.py
Expand Up @@ -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"))
2 changes: 1 addition & 1 deletion numpy/core/tests/test_getlimits.py
Expand Up @@ -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'):
Expand Down
2 changes: 1 addition & 1 deletion numpy/core/tests/test_machar.py
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions numpy/core/tests/test_numeric.py
Expand Up @@ -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'
Expand All @@ -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
Expand Down
1 change: 0 additions & 1 deletion numpy/tests/test_public_api.py
Expand Up @@ -178,7 +178,6 @@ def test_NPY_NO_EXPORT():
"core.fromnumeric",
"core.function_base",
"core.getlimits",
"core.machar",
"core.memmap",
"core.multiarray",
"core.numeric",
Expand Down
26 changes: 0 additions & 26 deletions 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
Expand All @@ -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}]
Expand All @@ -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}]
Expand All @@ -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