Skip to content

Commit 89f9bbd

Browse files
committed
More DRY
1 parent 9cb50cb commit 89f9bbd

File tree

1 file changed

+30
-33
lines changed

1 file changed

+30
-33
lines changed

src/typing_extensions.py

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@
128128
'no_type_check_decorator',
129129
]
130130

131-
_OLD_PYPY_VERSION = sys.implementation.name == "pypy" and sys.version_info < (3, 9)
132-
133131
# for backward compatibility
134132
PEP_560 = True
135133
GenericMeta = type
@@ -955,6 +953,21 @@ def __round__(self, ndigits: int = 0) -> T_co:
955953
pass
956954

957955

956+
def _ensure_subclassable(mro_entries):
957+
def inner(func):
958+
if sys.implementation.name == "pypy" and sys.version_info < (3, 9):
959+
cls_dict = {
960+
"__call__": staticmethod(func),
961+
"__mro_entries__": staticmethod(mro_entries)
962+
}
963+
t = type(func.__name__, (), cls_dict)
964+
return functools.update_wrapper(t(), func)
965+
else:
966+
func.__mro_entries__ = mro_entries
967+
return func
968+
return inner
969+
970+
958971
if sys.version_info >= (3, 13):
959972
# The standard library TypedDict in Python 3.8 does not store runtime information
960973
# about which (if any) keys are optional. See https://bugs.python.org/issue38834
@@ -1061,6 +1074,9 @@ def __subclasscheck__(cls, other):
10611074

10621075
__instancecheck__ = __subclasscheck__
10631076

1077+
_TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
1078+
1079+
@_ensure_subclassable(lambda bases: (_TypedDict,))
10641080
def TypedDict(__typename, __fields=_marker, *, total=True, **kwargs):
10651081
"""A simple typed namespace. At runtime it is equivalent to a plain dict.
10661082
@@ -1144,20 +1160,6 @@ class Point2D(TypedDict):
11441160
td.__orig_bases__ = (TypedDict,)
11451161
return td
11461162

1147-
_TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
1148-
1149-
if _OLD_PYPY_VERSION:
1150-
class _TypedDictType:
1151-
__call__ = staticmethod(TypedDict)
1152-
1153-
def __mro_entries__(self, bases):
1154-
return (_TypedDict,)
1155-
1156-
TypedDict = _TypedDictType()
1157-
functools.update_wrapper(TypedDict, TypedDict.__call__)
1158-
else:
1159-
TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)
1160-
11611163
if hasattr(typing, "_TypedDictMeta"):
11621164
_TYPEDDICT_TYPES = (typing._TypedDictMeta, _TypedDictMeta)
11631165
else:
@@ -2646,6 +2648,13 @@ def __new__(cls, typename, bases, ns):
26462648
nm_tpl.__init_subclass__()
26472649
return nm_tpl
26482650

2651+
_NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {})
2652+
2653+
def _namedtuple_mro_entries(bases):
2654+
assert NamedTuple in bases
2655+
return (_NamedTuple,)
2656+
2657+
@_ensure_subclassable(_namedtuple_mro_entries)
26492658
def NamedTuple(__typename, __fields=_marker, **kwargs):
26502659
"""Typed version of namedtuple.
26512660
@@ -2711,27 +2720,15 @@ class Employee(NamedTuple):
27112720
nt.__orig_bases__ = (NamedTuple,)
27122721
return nt
27132722

2714-
_NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {})
2715-
27162723
# On 3.8+, alter the signature so that it matches typing.NamedTuple.
27172724
# The signature of typing.NamedTuple on >=3.8 is invalid syntax in Python 3.7,
27182725
# so just leave the signature as it is on 3.7.
27192726
if sys.version_info >= (3, 8):
2720-
NamedTuple.__text_signature__ = '(typename, fields=None, /, **kwargs)'
2721-
2722-
def _namedtuple_mro_entries(bases):
2723-
assert NamedTuple in bases
2724-
return (_NamedTuple,)
2725-
2726-
if _OLD_PYPY_VERSION:
2727-
class _NamedTupleType:
2728-
__call__ = staticmethod(NamedTuple)
2729-
__mro_entries__ = staticmethod(_namedtuple_mro_entries)
2730-
2731-
NamedTuple = _NamedTupleType()
2732-
functools.update_wrapper(NamedTuple, NamedTuple.__call__)
2733-
else:
2734-
NamedTuple.__mro_entries__ = _namedtuple_mro_entries
2727+
new_signature = '(typename, fields=None, /, **kwargs)'
2728+
if isinstance(NamedTuple, _types.FunctionType):
2729+
NamedTuple.__text_signature__ = new_signature
2730+
else:
2731+
NamedTuple.__call__.__text_signature__ = new_signature
27352732

27362733

27372734
if hasattr(collections.abc, "Buffer"):

0 commit comments

Comments
 (0)