Skip to content

Commit 94132ac

Browse files
authored
Merge pull request numpy#28129 from jorenham/typing/deprecate_mypy_plugin
DEP: Deprecate ``numpy.typing.mypy_plugin``
2 parents 9707245 + 797acb3 commit 94132ac

File tree

2 files changed

+57
-54
lines changed

2 files changed

+57
-54
lines changed

numpy/typing/mypy_plugin.py

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
Without the plugin the type will default to `ctypes.c_int64`.
1717
1818
.. versionadded:: 1.22
19+
.. deprecated:: 2.3
1920
2021
Examples
2122
--------
@@ -31,27 +32,10 @@
3132
3233
"""
3334

34-
from __future__ import annotations
35-
36-
from typing import Final, TYPE_CHECKING, Callable
35+
from typing import Final
3736

3837
import numpy as np
3938

40-
if TYPE_CHECKING:
41-
from collections.abc import Iterable
42-
43-
try:
44-
import mypy.types
45-
from mypy.types import Type
46-
from mypy.plugin import Plugin, AnalyzeTypeContext
47-
from mypy.nodes import MypyFile, ImportFrom, Statement
48-
from mypy.build import PRI_MED
49-
50-
_HookFunc = Callable[[AnalyzeTypeContext], Type]
51-
MYPY_EX: None | ModuleNotFoundError = None
52-
except ModuleNotFoundError as ex:
53-
MYPY_EX = ex
54-
5539
__all__: list[str] = []
5640

5741

@@ -70,11 +54,10 @@ def _get_precision_dict() -> dict[str, str]:
7054
("_NBitDouble", np.double),
7155
("_NBitLongDouble", np.longdouble),
7256
]
73-
ret = {}
74-
module = "numpy._typing"
57+
ret: dict[str, str] = {}
7558
for name, typ in names:
76-
n: int = 8 * typ().dtype.itemsize
77-
ret[f'{module}._nbit.{name}'] = f"{module}._nbit_base._{n}Bit"
59+
n = 8 * np.dtype(typ).itemsize
60+
ret[f"{_MODULE}._nbit.{name}"] = f"{_MODULE}._nbit_base._{n}Bit"
7861
return ret
7962

8063

@@ -97,17 +80,15 @@ def _get_extended_precision_list() -> list[str]:
9780

9881
def _get_c_intp_name() -> str:
9982
# Adapted from `np.core._internal._getintp_ctype`
100-
char = np.dtype('n').char
101-
if char == 'i':
102-
return "c_int"
103-
elif char == 'l':
104-
return "c_long"
105-
elif char == 'q':
106-
return "c_longlong"
107-
else:
108-
return "c_long"
83+
return {
84+
"i": "c_int",
85+
"l": "c_long",
86+
"q": "c_longlong",
87+
}.get(np.dtype("n").char, "c_long")
10988

11089

90+
_MODULE: Final = "numpy._typing"
91+
11192
#: A dictionary mapping type-aliases in `numpy._typing._nbit` to
11293
#: concrete `numpy.typing.NBitBase` subclasses.
11394
_PRECISION_DICT: Final = _get_precision_dict()
@@ -119,15 +100,27 @@ def _get_c_intp_name() -> str:
119100
_C_INTP: Final = _get_c_intp_name()
120101

121102

122-
def _hook(ctx: AnalyzeTypeContext) -> Type:
123-
"""Replace a type-alias with a concrete ``NBitBase`` subclass."""
124-
typ, _, api = ctx
125-
name = typ.name.split(".")[-1]
126-
name_new = _PRECISION_DICT[f"numpy._typing._nbit.{name}"]
127-
return api.named_type(name_new)
103+
try:
104+
from collections.abc import Callable, Iterable
105+
from typing import TYPE_CHECKING, TypeAlias, cast
128106

107+
if TYPE_CHECKING:
108+
from mypy.typeanal import TypeAnalyser
109+
110+
import mypy.types
111+
from mypy.plugin import Plugin, AnalyzeTypeContext
112+
from mypy.nodes import MypyFile, ImportFrom, Statement
113+
from mypy.build import PRI_MED
114+
115+
_HookFunc: TypeAlias = Callable[[AnalyzeTypeContext], mypy.types.Type]
116+
117+
def _hook(ctx: AnalyzeTypeContext) -> mypy.types.Type:
118+
"""Replace a type-alias with a concrete ``NBitBase`` subclass."""
119+
typ, _, api = ctx
120+
name = typ.name.split(".")[-1]
121+
name_new = _PRECISION_DICT[f"{_MODULE}._nbit.{name}"]
122+
return cast("TypeAnalyser", api).named_type(name_new)
129123

130-
if TYPE_CHECKING or MYPY_EX is None:
131124
def _index(iterable: Iterable[Statement], id: str) -> int:
132125
"""Identify the first ``ImportFrom`` instance the specified `id`."""
133126
for i, value in enumerate(iterable):
@@ -139,22 +132,22 @@ def _index(iterable: Iterable[Statement], id: str) -> int:
139132
def _override_imports(
140133
file: MypyFile,
141134
module: str,
142-
imports: list[tuple[str, None | str]],
135+
imports: list[tuple[str, str | None]],
143136
) -> None:
144137
"""Override the first `module`-based import with new `imports`."""
145138
# Construct a new `from module import y` statement
146139
import_obj = ImportFrom(module, 0, names=imports)
147140
import_obj.is_top_level = True
148141

149142
# Replace the first `module`-based import statement with `import_obj`
150-
for lst in [file.defs, file.imports]: # type: list[Statement]
143+
for lst in [file.defs, cast("list[Statement]", file.imports)]:
151144
i = _index(lst, module)
152145
lst[i] = import_obj
153146

154147
class _NumpyPlugin(Plugin):
155148
"""A mypy plugin for handling versus numpy-specific typing tasks."""
156149

157-
def get_type_analyze_hook(self, fullname: str) -> None | _HookFunc:
150+
def get_type_analyze_hook(self, fullname: str) -> _HookFunc | None:
158151
"""Set the precision of platform-specific `numpy.number`
159152
subclasses.
160153
@@ -175,25 +168,33 @@ def get_additional_deps(
175168
* Import the appropriate `ctypes` equivalent to `numpy.intp`.
176169
177170
"""
178-
ret = [(PRI_MED, file.fullname, -1)]
179-
180-
if file.fullname == "numpy":
171+
fullname = file.fullname
172+
if fullname == "numpy":
181173
_override_imports(
182-
file, "numpy._typing._extended_precision",
174+
file,
175+
f"{_MODULE}._extended_precision",
183176
imports=[(v, v) for v in _EXTENDED_PRECISION_LIST],
184177
)
185-
elif file.fullname == "numpy.ctypeslib":
178+
elif fullname == "numpy.ctypeslib":
186179
_override_imports(
187-
file, "ctypes",
180+
file,
181+
"ctypes",
188182
imports=[(_C_INTP, "_c_intp")],
189183
)
190-
return ret
184+
return [(PRI_MED, fullname, -1)]
191185

192-
def plugin(version: str) -> type[_NumpyPlugin]:
193-
"""An entry-point for mypy."""
186+
def plugin(version: str) -> type:
187+
import warnings
188+
189+
warnings.warn(
190+
"`numpy.typing.mypy_plugin` is deprecated, and will be removed in "
191+
"a future release.",
192+
category=DeprecationWarning,
193+
stacklevel=3,
194+
)
194195
return _NumpyPlugin
195196

196-
else:
197-
def plugin(version: str) -> type[_NumpyPlugin]:
198-
"""An entry-point for mypy."""
199-
raise MYPY_EX
197+
except ModuleNotFoundError as e:
198+
199+
def plugin(version: str) -> type:
200+
raise e

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ filterwarnings =
2525
# Ignore DeprecationWarnings from distutils
2626
ignore::DeprecationWarning:.*distutils
2727
ignore:\n\n `numpy.distutils`:DeprecationWarning
28+
# Ignore DeprecationWarning from typing.mypy_plugin
29+
ignore:`numpy.typing.mypy_plugin` is deprecated:DeprecationWarning

0 commit comments

Comments
 (0)