Skip to content

Commit 7587da9

Browse files
committed
Fix lazy submodule loading and add changelog fragment
- Use sys.modules[mod_name].__dict__ instead of globals() so the lazy-loaded module is cached in the correct package when _make_getattr is used by attrs/__init__.py - Add __dir__ to both attr and attrs packages so that converters and validators appear in dir() (tab-completion, introspection) - Add changelog.d entry for this PR
1 parent 74e661e commit 7587da9

3 files changed

Lines changed: 12 additions & 1 deletion

File tree

changelog.d/1547.change.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deferred the import of `inspect` and the loading of the `validators` and `converters` submodules until first use, reducing `import attr`/`import attrs` time by ~25%.

src/attr/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
Classes Without Boilerplate
55
"""
66

7+
import sys
8+
79
from functools import partial
810
from typing import Callable, Literal, Protocol
911

@@ -92,7 +94,7 @@ def __getattr__(name: str) -> str:
9294
import importlib
9395

9496
mod = importlib.import_module(f".{name}", mod_name)
95-
globals()[name] = mod
97+
sys.modules[mod_name].__dict__[name] = mod
9698
return mod
9799

98100
if name not in ("__version__", "__version_info__"):
@@ -112,3 +114,7 @@ def __getattr__(name: str) -> str:
112114

113115

114116
__getattr__ = _make_getattr(__name__)
117+
118+
119+
def __dir__() -> list[str]:
120+
return __all__

src/attrs/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,7 @@
7070
]
7171

7272
__getattr__ = _make_getattr(__name__)
73+
74+
75+
def __dir__() -> list[str]:
76+
return __all__

0 commit comments

Comments
 (0)