Skip to content

Commit 180461f

Browse files
committed
Optimise the import time for typing
1 parent d4cea79 commit 180461f

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

Lib/test/test_typing.py

+4
Original file line numberDiff line numberDiff line change
@@ -9373,6 +9373,10 @@ def test_all(self):
93739373
self.assertIn('SupportsComplex', a)
93749374

93759375
def test_all_exported_names(self):
9376+
# ensure all dynamically created objects are actualised
9377+
for name in typing.__all__:
9378+
getattr(typing, name)
9379+
93769380
actual_all = set(typing.__all__)
93779381
computed_all = {
93789382
k for k, v in vars(typing).items()

Lib/typing.py

+18-8
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@
2323
from collections import defaultdict
2424
import collections.abc
2525
import copyreg
26-
import contextlib
2726
import functools
2827
import operator
29-
import re as stdlib_re # Avoid confusion with the typing.re namespace on <=3.11
3028
import sys
3129
import types
3230
from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias
@@ -2580,8 +2578,6 @@ class Other(Leaf): # Error reported by type checker
25802578
KeysView = _alias(collections.abc.KeysView, 1)
25812579
ItemsView = _alias(collections.abc.ItemsView, 2)
25822580
ValuesView = _alias(collections.abc.ValuesView, 1)
2583-
ContextManager = _alias(contextlib.AbstractContextManager, 1, name='ContextManager')
2584-
AsyncContextManager = _alias(contextlib.AbstractAsyncContextManager, 1, name='AsyncContextManager')
25852581
Dict = _alias(dict, 2, inst=False, name='Dict')
25862582
DefaultDict = _alias(collections.defaultdict, 2, name='DefaultDict')
25872583
OrderedDict = _alias(collections.OrderedDict, 2)
@@ -3238,10 +3234,6 @@ def __enter__(self) -> 'TextIO':
32383234
pass
32393235

32403236

3241-
Pattern = _alias(stdlib_re.Pattern, 1)
3242-
Match = _alias(stdlib_re.Match, 1)
3243-
3244-
32453237
def reveal_type[T](obj: T, /) -> T:
32463238
"""Reveal the inferred type of a variable.
32473239
@@ -3426,3 +3418,21 @@ def get_protocol_members(tp: type, /) -> frozenset[str]:
34263418
if not is_protocol(tp):
34273419
raise TypeError(f'{tp!r} is not a Protocol')
34283420
return frozenset(tp.__protocol_attrs__)
3421+
3422+
3423+
def __getattr__(attr):
3424+
"""Improve the import time of the typing module.
3425+
3426+
Soft-deprecated objects which are costly to create
3427+
are only created on-demand here.
3428+
"""
3429+
if attr in {"Pattern", "Match"}:
3430+
import re
3431+
obj = _alias(getattr(re, attr), 1)
3432+
elif attr in {"ContextManager", "AsyncContextManager"}:
3433+
import contextlib
3434+
obj = _alias(getattr(contextlib, f"Abstract{attr}"), 1, name=attr)
3435+
else:
3436+
raise AttributeError(f"Module 'typing' has no attribute {attr!r}")
3437+
globals()[attr] = obj
3438+
return obj

0 commit comments

Comments
 (0)