Skip to content

Commit 2202af8

Browse files
committed
Use PEP 562 instead of _ModuleWithDeprecations
1 parent b6813ed commit 2202af8

File tree

4 files changed

+30
-35
lines changed

4 files changed

+30
-35
lines changed

src/trio/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,8 @@
112112

113113
from . import _deprecate as _deprecate
114114

115-
_deprecate.enable_attribute_deprecations(__name__)
116-
117-
__deprecated_attributes__: dict[str, _deprecate.DeprecatedAttribute] = {}
115+
if not TYPE_CHECKING:
116+
__getattr__ = _deprecate.getattr_for_deprecated_attributes(__name__, {})
118117

119118
# Having the public path in .__module__ attributes is important for:
120119
# - exception names in printed tracebacks

src/trio/_deprecate.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from __future__ import annotations
22

3-
import sys
43
import warnings
54
from functools import wraps
6-
from types import ModuleType
75
from typing import TYPE_CHECKING, ClassVar, TypeVar
86

97
import attrs
@@ -150,28 +148,20 @@ class DeprecatedAttribute:
150148
instead: object = _not_set
151149

152150

153-
class _ModuleWithDeprecations(ModuleType):
154-
__deprecated_attributes__: dict[str, DeprecatedAttribute]
155-
156-
def __getattr__(self, name: str) -> object:
157-
if name in self.__deprecated_attributes__:
158-
info = self.__deprecated_attributes__[name]
151+
def getattr_for_deprecated_attributes(
152+
module_name: str, deprecated_attributes: dict[str, DeprecatedAttribute]
153+
) -> Callable[[str], object]:
154+
def __getattr__(name: str) -> object:
155+
if name in deprecated_attributes:
156+
info = deprecated_attributes[name]
159157
instead = info.instead
160158
if instead is DeprecatedAttribute._not_set:
161159
instead = info.value
162-
thing = f"{self.__name__}.{name}"
160+
thing = f"{module_name}.{name}"
163161
warn_deprecated(thing, info.version, issue=info.issue, instead=instead)
164162
return info.value
165163

166164
msg = "module '{}' has no attribute '{}'"
167-
raise AttributeError(msg.format(self.__name__, name))
168-
165+
raise AttributeError(msg.format(module_name, name))
169166

170-
def enable_attribute_deprecations(module_name: str) -> None:
171-
module = sys.modules[module_name]
172-
module.__class__ = _ModuleWithDeprecations
173-
assert isinstance(module, _ModuleWithDeprecations)
174-
# Make sure that this is always defined so that
175-
# _ModuleWithDeprecations.__getattr__ can access it without jumping
176-
# through hoops or risking infinite recursion.
177-
module.__deprecated_attributes__ = {}
167+
return __getattr__
Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
regular = "hi"
22

3-
from .. import _deprecate
4-
5-
_deprecate.enable_attribute_deprecations(__name__)
6-
73
# Make sure that we don't trigger infinite recursion when accessing module
84
# attributes in between calling enable_attribute_deprecations and defining
95
# __deprecated_attributes__:
106
import sys
7+
import typing
8+
9+
from .. import _deprecate
1110

1211
this_mod = sys.modules[__name__]
1312
assert this_mod.regular == "hi"
1413
assert not hasattr(this_mod, "dep1")
1514

16-
__deprecated_attributes__ = {
17-
"dep1": _deprecate.DeprecatedAttribute("value1", "1.1", issue=1),
18-
"dep2": _deprecate.DeprecatedAttribute(
19-
"value2",
20-
"1.2",
21-
issue=1,
22-
instead="instead-string",
23-
),
24-
}
15+
if not typing.TYPE_CHECKING:
16+
__getattr__ = _deprecate.getattr_for_deprecated_attributes(
17+
__name__,
18+
{
19+
"dep1": _deprecate.DeprecatedAttribute("value1", "1.1", issue=1),
20+
"dep2": _deprecate.DeprecatedAttribute(
21+
"value2",
22+
"1.2",
23+
issue=1,
24+
instead="instead-string",
25+
),
26+
},
27+
)

src/trio/_tests/test_deprecate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import inspect
44
import warnings
5+
from types import ModuleType
56

67
import pytest
78

@@ -244,6 +245,8 @@ def test_module_with_deprecations(recwarn_always: pytest.WarningsRecorder) -> No
244245
assert module_with_deprecations.regular == "hi"
245246
assert len(recwarn_always) == 0
246247

248+
assert type(module_with_deprecations) is ModuleType
249+
247250
filename, lineno = _here()
248251
assert module_with_deprecations.dep1 == "value1" # type: ignore[attr-defined]
249252
got = recwarn_always.pop(DeprecationWarning)

0 commit comments

Comments
 (0)