Skip to content

Commit 297caea

Browse files
authored
Merge pull request numpy#28884 from jorenham/typing/deprecate-npt.NBitBase
DEP: deprecate ``numpy.typing.NBitBase``
2 parents 111154a + 72fcaa9 commit 297caea

File tree

5 files changed

+106
-8
lines changed

5 files changed

+106
-8
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
``numpy.typing.NBitBase`` deprecation
2+
-------------------------------------
3+
The ``numpy.typing.NBitBase`` type has been deprecated and will be removed in a future version.
4+
5+
This type was previously intended to be used as a generic upper bound for type-parameters, for example:
6+
7+
.. code-block:: python
8+
9+
import numpy as np
10+
import numpy.typing as npt
11+
12+
def f[NT: npt.NBitBase](x: np.complexfloating[NT]) -> np.floating[NT]: ...
13+
14+
But in NumPy 2.2.0, ``float64`` and ``complex128`` were changed to concrete subtypes, causing static type-checkers to reject ``x: np.float64 = f(np.complex128(42j))``.
15+
16+
So instead, the better approach is to use ``typing.overload``:
17+
18+
.. code-block:: python
19+
20+
import numpy as np
21+
from typing import overload
22+
23+
@overload
24+
def f(x: np.complex64) -> np.float32: ...
25+
@overload
26+
def f(x: np.complex128) -> np.float64: ...
27+
@overload
28+
def f(x: np.clongdouble) -> np.longdouble: ...

numpy/_typing/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
_NestedSequence as _NestedSequence,
77
)
88
from ._nbit_base import (
9-
NBitBase as NBitBase,
9+
NBitBase as NBitBase, # pyright: ignore[reportDeprecated]
1010
_8Bit as _8Bit,
1111
_16Bit as _16Bit,
1212
_32Bit as _32Bit,

numpy/_typing/_nbit_base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ class NBitBase:
99
"""
1010
A type representing `numpy.number` precision during static type checking.
1111
12-
Used exclusively for the purpose static type checking, `NBitBase`
12+
Used exclusively for the purpose of static type checking, `NBitBase`
1313
represents the base of a hierarchical set of subclasses.
1414
Each subsequent subclass is herein used for representing a lower level
1515
of precision, *e.g.* ``64Bit > 32Bit > 16Bit``.
1616
1717
.. versionadded:: 1.20
1818
19+
.. deprecated:: 2.3
20+
Use ``@typing.overload`` or a ``TypeVar`` with a scalar-type as upper
21+
bound, instead.
22+
1923
Examples
2024
--------
2125
Below is a typical usage example: `NBitBase` is herein used for annotating
@@ -48,6 +52,7 @@ class NBitBase:
4852
... # note: out: numpy.floating[numpy.typing._64Bit*]
4953
5054
"""
55+
# Deprecated in NumPy 2.3, 2025-05-01
5156

5257
def __init_subclass__(cls) -> None:
5358
allowed_names = {

numpy/_typing/_nbit_base.pyi

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# pyright: reportDeprecated=false
2+
# pyright: reportGeneralTypeIssues=false
3+
# mypy: disable-error-code=misc
4+
5+
from typing import final
6+
7+
from typing_extensions import deprecated
8+
9+
# Deprecated in NumPy 2.3, 2025-05-01
10+
@deprecated(
11+
"`NBitBase` is deprecated and will be removed from numpy.typing in the "
12+
"future. Use `@typing.overload` or a `TypeVar` with a scalar-type as upper "
13+
"bound, instead. (deprecated in NumPy 2.3)",
14+
)
15+
@final
16+
class NBitBase: ...
17+
18+
@final
19+
class _256Bit(NBitBase): ...
20+
21+
@final
22+
class _128Bit(_256Bit): ...
23+
24+
@final
25+
class _96Bit(_128Bit): ...
26+
27+
@final
28+
class _80Bit(_96Bit): ...
29+
30+
@final
31+
class _64Bit(_80Bit): ...
32+
33+
@final
34+
class _32Bit(_64Bit): ...
35+
36+
@final
37+
class _16Bit(_32Bit): ...
38+
39+
@final
40+
class _8Bit(_16Bit): ...

numpy/typing/__init__.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,40 @@
155155
# NOTE: The API section will be appended with additional entries
156156
# further down in this file
157157

158-
from numpy._typing import (
159-
ArrayLike,
160-
DTypeLike,
161-
NBitBase,
162-
NDArray,
163-
)
158+
# pyright: reportDeprecated=false
159+
160+
from numpy._typing import ArrayLike, DTypeLike, NBitBase, NDArray
164161

165162
__all__ = ["ArrayLike", "DTypeLike", "NBitBase", "NDArray"]
166163

164+
165+
__DIR = __all__ + [k for k in globals() if k.startswith("__") and k.endswith("__")]
166+
__DIR_SET = frozenset(__DIR)
167+
168+
169+
def __dir__() -> list[str]:
170+
return __DIR
171+
172+
def __getattr__(name: str):
173+
if name == "NBitBase":
174+
import warnings
175+
176+
# Deprecated in NumPy 2.3, 2025-05-01
177+
warnings.warn(
178+
"`NBitBase` is deprecated and will be removed from numpy.typing in the "
179+
"future. Use `@typing.overload` or a `TypeVar` with a scalar-type as upper "
180+
"bound, instead. (deprecated in NumPy 2.3)",
181+
DeprecationWarning,
182+
stacklevel=2,
183+
)
184+
return NBitBase
185+
186+
if name in __DIR_SET:
187+
return globals()[name]
188+
189+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
190+
191+
167192
if __doc__ is not None:
168193
from numpy._typing._add_docstring import _docstrings
169194
__doc__ += _docstrings

0 commit comments

Comments
 (0)