Skip to content

Commit 51bb14b

Browse files
committed
Upgrade typing_extensions to 4.3.0
1 parent 69e60a5 commit 51bb14b

File tree

3 files changed

+142
-32
lines changed

3 files changed

+142
-32
lines changed

news/typing_extensions.vendor.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Upgrade typing_extensions to 4.3.0

src/pip/_vendor/typing_extensions.py

Lines changed: 140 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
'Counter',
3838
'Deque',
3939
'DefaultDict',
40+
'NamedTuple',
4041
'OrderedDict',
4142
'TypedDict',
4243

@@ -380,6 +381,46 @@ def _is_callable_members_only(cls):
380381
return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls))
381382

382383

384+
def _maybe_adjust_parameters(cls):
385+
"""Helper function used in Protocol.__init_subclass__ and _TypedDictMeta.__new__.
386+
387+
The contents of this function are very similar
388+
to logic found in typing.Generic.__init_subclass__
389+
on the CPython main branch.
390+
"""
391+
tvars = []
392+
if '__orig_bases__' in cls.__dict__:
393+
tvars = typing._collect_type_vars(cls.__orig_bases__)
394+
# Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn].
395+
# If found, tvars must be a subset of it.
396+
# If not found, tvars is it.
397+
# Also check for and reject plain Generic,
398+
# and reject multiple Generic[...] and/or Protocol[...].
399+
gvars = None
400+
for base in cls.__orig_bases__:
401+
if (isinstance(base, typing._GenericAlias) and
402+
base.__origin__ in (typing.Generic, Protocol)):
403+
# for error messages
404+
the_base = base.__origin__.__name__
405+
if gvars is not None:
406+
raise TypeError(
407+
"Cannot inherit from Generic[...]"
408+
" and/or Protocol[...] multiple types.")
409+
gvars = base.__parameters__
410+
if gvars is None:
411+
gvars = tvars
412+
else:
413+
tvarset = set(tvars)
414+
gvarset = set(gvars)
415+
if not tvarset <= gvarset:
416+
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
417+
s_args = ', '.join(str(g) for g in gvars)
418+
raise TypeError(f"Some type variables ({s_vars}) are"
419+
f" not listed in {the_base}[{s_args}]")
420+
tvars = gvars
421+
cls.__parameters__ = tuple(tvars)
422+
423+
383424
# 3.8+
384425
if hasattr(typing, 'Protocol'):
385426
Protocol = typing.Protocol
@@ -476,43 +517,13 @@ def __class_getitem__(cls, params):
476517
return typing._GenericAlias(cls, params)
477518

478519
def __init_subclass__(cls, *args, **kwargs):
479-
tvars = []
480520
if '__orig_bases__' in cls.__dict__:
481521
error = typing.Generic in cls.__orig_bases__
482522
else:
483523
error = typing.Generic in cls.__bases__
484524
if error:
485525
raise TypeError("Cannot inherit from plain Generic")
486-
if '__orig_bases__' in cls.__dict__:
487-
tvars = typing._collect_type_vars(cls.__orig_bases__)
488-
# Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn].
489-
# If found, tvars must be a subset of it.
490-
# If not found, tvars is it.
491-
# Also check for and reject plain Generic,
492-
# and reject multiple Generic[...] and/or Protocol[...].
493-
gvars = None
494-
for base in cls.__orig_bases__:
495-
if (isinstance(base, typing._GenericAlias) and
496-
base.__origin__ in (typing.Generic, Protocol)):
497-
# for error messages
498-
the_base = base.__origin__.__name__
499-
if gvars is not None:
500-
raise TypeError(
501-
"Cannot inherit from Generic[...]"
502-
" and/or Protocol[...] multiple types.")
503-
gvars = base.__parameters__
504-
if gvars is None:
505-
gvars = tvars
506-
else:
507-
tvarset = set(tvars)
508-
gvarset = set(gvars)
509-
if not tvarset <= gvarset:
510-
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
511-
s_args = ', '.join(str(g) for g in gvars)
512-
raise TypeError(f"Some type variables ({s_vars}) are"
513-
f" not listed in {the_base}[{s_args}]")
514-
tvars = gvars
515-
cls.__parameters__ = tuple(tvars)
526+
_maybe_adjust_parameters(cls)
516527

517528
# Determine if this is a protocol or a concrete subclass.
518529
if not cls.__dict__.get('_is_protocol', None):
@@ -613,6 +624,7 @@ def __index__(self) -> int:
613624
# keyword with old-style TypedDict(). See https://bugs.python.org/issue42059
614625
# The standard library TypedDict below Python 3.11 does not store runtime
615626
# information about optional and required keys when using Required or NotRequired.
627+
# Generic TypedDicts are also impossible using typing.TypedDict on Python <3.11.
616628
TypedDict = typing.TypedDict
617629
_TypedDictMeta = typing._TypedDictMeta
618630
is_typeddict = typing.is_typeddict
@@ -695,8 +707,16 @@ def __new__(cls, name, bases, ns, total=True):
695707
# Subclasses and instances of TypedDict return actual dictionaries
696708
# via _dict_new.
697709
ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new
710+
# Don't insert typing.Generic into __bases__ here,
711+
# or Generic.__init_subclass__ will raise TypeError
712+
# in the super().__new__() call.
713+
# Instead, monkey-patch __bases__ onto the class after it's been created.
698714
tp_dict = super().__new__(cls, name, (dict,), ns)
699715

716+
if any(issubclass(base, typing.Generic) for base in bases):
717+
tp_dict.__bases__ = (typing.Generic, dict)
718+
_maybe_adjust_parameters(tp_dict)
719+
700720
annotations = {}
701721
own_annotations = ns.get('__annotations__', {})
702722
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
@@ -1958,3 +1978,92 @@ def decorator(cls_or_fn):
19581978
if not hasattr(typing, "TypeVarTuple"):
19591979
typing._collect_type_vars = _collect_type_vars
19601980
typing._check_generic = _check_generic
1981+
1982+
1983+
# Backport typing.NamedTuple as it exists in Python 3.11.
1984+
# In 3.11, the ability to define generic `NamedTuple`s was supported.
1985+
# This was explicitly disallowed in 3.9-3.10, and only half-worked in <=3.8.
1986+
if sys.version_info >= (3, 11):
1987+
NamedTuple = typing.NamedTuple
1988+
else:
1989+
def _caller():
1990+
try:
1991+
return sys._getframe(2).f_globals.get('__name__', '__main__')
1992+
except (AttributeError, ValueError): # For platforms without _getframe()
1993+
return None
1994+
1995+
def _make_nmtuple(name, types, module, defaults=()):
1996+
fields = [n for n, t in types]
1997+
annotations = {n: typing._type_check(t, f"field {n} annotation must be a type")
1998+
for n, t in types}
1999+
nm_tpl = collections.namedtuple(name, fields,
2000+
defaults=defaults, module=module)
2001+
nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = annotations
2002+
# The `_field_types` attribute was removed in 3.9;
2003+
# in earlier versions, it is the same as the `__annotations__` attribute
2004+
if sys.version_info < (3, 9):
2005+
nm_tpl._field_types = annotations
2006+
return nm_tpl
2007+
2008+
_prohibited_namedtuple_fields = typing._prohibited
2009+
_special_namedtuple_fields = frozenset({'__module__', '__name__', '__annotations__'})
2010+
2011+
class _NamedTupleMeta(type):
2012+
def __new__(cls, typename, bases, ns):
2013+
assert _NamedTuple in bases
2014+
for base in bases:
2015+
if base is not _NamedTuple and base is not typing.Generic:
2016+
raise TypeError(
2017+
'can only inherit from a NamedTuple type and Generic')
2018+
bases = tuple(tuple if base is _NamedTuple else base for base in bases)
2019+
types = ns.get('__annotations__', {})
2020+
default_names = []
2021+
for field_name in types:
2022+
if field_name in ns:
2023+
default_names.append(field_name)
2024+
elif default_names:
2025+
raise TypeError(f"Non-default namedtuple field {field_name} "
2026+
f"cannot follow default field"
2027+
f"{'s' if len(default_names) > 1 else ''} "
2028+
f"{', '.join(default_names)}")
2029+
nm_tpl = _make_nmtuple(
2030+
typename, types.items(),
2031+
defaults=[ns[n] for n in default_names],
2032+
module=ns['__module__']
2033+
)
2034+
nm_tpl.__bases__ = bases
2035+
if typing.Generic in bases:
2036+
class_getitem = typing.Generic.__class_getitem__.__func__
2037+
nm_tpl.__class_getitem__ = classmethod(class_getitem)
2038+
# update from user namespace without overriding special namedtuple attributes
2039+
for key in ns:
2040+
if key in _prohibited_namedtuple_fields:
2041+
raise AttributeError("Cannot overwrite NamedTuple attribute " + key)
2042+
elif key not in _special_namedtuple_fields and key not in nm_tpl._fields:
2043+
setattr(nm_tpl, key, ns[key])
2044+
if typing.Generic in bases:
2045+
nm_tpl.__init_subclass__()
2046+
return nm_tpl
2047+
2048+
def NamedTuple(__typename, __fields=None, **kwargs):
2049+
if __fields is None:
2050+
__fields = kwargs.items()
2051+
elif kwargs:
2052+
raise TypeError("Either list of fields or keywords"
2053+
" can be provided to NamedTuple, not both")
2054+
return _make_nmtuple(__typename, __fields, module=_caller())
2055+
2056+
NamedTuple.__doc__ = typing.NamedTuple.__doc__
2057+
_NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {})
2058+
2059+
# On 3.8+, alter the signature so that it matches typing.NamedTuple.
2060+
# The signature of typing.NamedTuple on >=3.8 is invalid syntax in Python 3.7,
2061+
# so just leave the signature as it is on 3.7.
2062+
if sys.version_info >= (3, 8):
2063+
NamedTuple.__text_signature__ = '(typename, fields=None, /, **kwargs)'
2064+
2065+
def _namedtuple_mro_entries(bases):
2066+
assert NamedTuple in bases
2067+
return (_NamedTuple,)
2068+
2069+
NamedTuple.__mro_entries__ = _namedtuple_mro_entries

src/pip/_vendor/vendor.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ requests==2.27.1
1414
urllib3==1.26.10
1515
rich==12.5.1
1616
pygments==2.12.0
17-
typing_extensions==4.2.0
17+
typing_extensions==4.3.0
1818
resolvelib==0.8.1
1919
setuptools==44.0.0
2020
six==1.16.0

0 commit comments

Comments
 (0)