Skip to content

Commit b79320c

Browse files
committed
Backport fixes for more versions
1 parent 103ea46 commit b79320c

File tree

1 file changed

+104
-20
lines changed

1 file changed

+104
-20
lines changed

src/typing_extensions.py

Lines changed: 104 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,19 @@ def __call__(self, *args, **kwargs):
17651765
# 3.8-3.9
17661766
if not hasattr(typing, 'Concatenate'):
17671767
# Inherits from list as a workaround for Callable checks in Python < 3.9.2.
1768+
1769+
#3.9.0-1
1770+
if not hasattr(typing, '_type_convert'):
1771+
def _type_convert(arg, module=None, *, allow_special_forms=False):
1772+
"""For converting None to type(None), and strings to ForwardRef."""
1773+
if arg is None:
1774+
return type(None)
1775+
if isinstance(arg, str):
1776+
return ForwardRef(arg, module=module, is_class=allow_special_forms)
1777+
return arg
1778+
else:
1779+
_type_convert = typing._type_convert
1780+
17681781
class _ConcatenateGenericAlias(list):
17691782

17701783
# Trick Generic into looking into this for __parameters__.
@@ -1797,16 +1810,66 @@ def __parameters__(self):
17971810
)
17981811

17991812
# 3.8; needed for typing._subs_tvars
1800-
if sys.version_info < (3, 9):
1801-
def copy_with(self, params):
1802-
if isinstance(params[-1], (list, tuple)):
1803-
return (*params[:-1], *params[-1])
1804-
if isinstance(params[-1], _ConcatenateGenericAlias):
1805-
params = (*params[:-1], *params[-1].__args__)
1806-
elif not (params[-1] is ... or isinstance(params[-1], ParamSpec)):
1807-
raise TypeError("The last parameter to Concatenate should be a "
1808-
"ParamSpec variable or ellipsis.")
1809-
return self.__class__(self.__origin__, params)
1813+
# 3.9 used by __getitem__ below
1814+
def copy_with(self, params):
1815+
if isinstance(params[-1], (list, tuple)):
1816+
return (*params[:-1], *params[-1])
1817+
if isinstance(params[-1], _ConcatenateGenericAlias):
1818+
params = (*params[:-1], *params[-1].__args__)
1819+
elif (not(params[-1] is ... or isinstance(params[-1], ParamSpec))):
1820+
raise TypeError("The last parameter to Concatenate should be a "
1821+
"ParamSpec variable or ellipsis.")
1822+
return self.__class__(self.__origin__, params)
1823+
1824+
# 3.9; accessed during GenericAlias.__getitem__when substituting
1825+
def __getitem__(self, args):
1826+
if self.__origin__ in (Generic, Protocol):
1827+
# Can't subscript Generic[...] or Protocol[...].
1828+
raise TypeError(f"Cannot subscript already-subscripted {self}")
1829+
if not self.__parameters__:
1830+
raise TypeError(f"{self} is not a generic class")
1831+
1832+
if not isinstance(args, tuple):
1833+
args = (args,)
1834+
args = _unpack_args(*(_type_convert(p) for p in args))
1835+
params = self.__parameters__
1836+
for param in params:
1837+
if isinstance(param, ParamSpec):
1838+
i = params.index(param)
1839+
if (
1840+
i == len(args)
1841+
and getattr(param, '__default__', NoDefault) is not NoDefault
1842+
):
1843+
args = [*args, param.__default__]
1844+
if i >= len(args):
1845+
raise TypeError(f"Too few arguments for {self}")
1846+
# Special case for Z[[int, str, bool]] == Z[int, str, bool]
1847+
if len(params) == 1 and not _is_param_expr(args[0]):
1848+
assert i == 0
1849+
args = (args,)
1850+
# Convert lists to tuples to help other libraries cache the results.
1851+
elif isinstance(args[i], list):
1852+
args = (*args[:i], tuple(args[i]), *args[i+1:])
1853+
1854+
subst = dict(zip(self.__parameters__, args))
1855+
# determine new args
1856+
new_args = []
1857+
for arg in self.__args__:
1858+
if isinstance(arg, type):
1859+
new_args.append(arg)
1860+
continue
1861+
if isinstance(arg, TypeVar):
1862+
arg = subst[arg]
1863+
elif isinstance(arg,
1864+
typing._GenericAlias
1865+
if not hasattr(_types, "GenericAlias") else
1866+
(typing._GenericAlias, _types.GenericAlias)):
1867+
subparams = arg.__parameters__
1868+
if subparams:
1869+
subargs = tuple(subst[x] for x in subparams)
1870+
arg = arg[subargs]
1871+
new_args.append(arg)
1872+
return self.copy_with(tuple(new_args))
18101873

18111874
# 3.10+
18121875
else:
@@ -1830,6 +1893,12 @@ def copy_with(self, params):
18301893
"ParamSpec variable or ellipsis.")
18311894
return super(_typing_ConcatenateGenericAlias, self).copy_with(params)
18321895

1896+
def __getitem__(self, args):
1897+
value = super().__getitem__(args)
1898+
if isinstance(value, tuple) and any(_is_unpack(t) for t in value):
1899+
return tuple(_unpack_args(*(n for n in value)))
1900+
return value
1901+
18331902

18341903
# 3.8-3.9.2
18351904
class _EllipsisDummy: ...
@@ -2509,6 +2578,21 @@ def _is_unpack(obj):
25092578
class _UnpackAlias(typing._GenericAlias, _root=True):
25102579
__class__ = typing.TypeVar
25112580

2581+
def _typing_unpacked_tuple_args(self):
2582+
assert self.__origin__ is Unpack
2583+
assert len(self.__args__) == 1
2584+
arg, = self.__args__
2585+
if isinstance(arg, typing._GenericAlias):
2586+
if arg.__origin__ is not tuple:
2587+
raise TypeError("Unpack[...] must be used with a tuple type")
2588+
return arg.__args__
2589+
return None
2590+
2591+
def __getattr__(self, attr):
2592+
if attr == '__typing_unpacked_tuple_args__':
2593+
return self._typing_unpacked_tuple_args()
2594+
return super().__getattr__(attr)
2595+
25122596
@property
25132597
def __typing_is_unpacked_typevartuple__(self):
25142598
assert self.__origin__ is Unpack
@@ -2532,21 +2616,21 @@ def _is_unpack(obj):
25322616
return isinstance(obj, _UnpackAlias)
25332617

25342618

2619+
def _unpack_args(*args):
2620+
newargs = []
2621+
for arg in args:
2622+
subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
2623+
if subargs is not None and (not (subargs and subargs[-1] is ...)):
2624+
newargs.extend(subargs)
2625+
else:
2626+
newargs.append(arg)
2627+
return newargs
2628+
25352629
if _PEP_696_IMPLEMENTED:
25362630
from typing import TypeVarTuple
25372631

25382632
elif hasattr(typing, "TypeVarTuple"): # 3.11+
25392633

2540-
def _unpack_args(*args):
2541-
newargs = []
2542-
for arg in args:
2543-
subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
2544-
if subargs is not None and not (subargs and subargs[-1] is ...):
2545-
newargs.extend(subargs)
2546-
else:
2547-
newargs.append(arg)
2548-
return newargs
2549-
25502634
# Add default parameter - PEP 696
25512635
class TypeVarTuple(metaclass=_TypeVarLikeMeta):
25522636
"""Type variable tuple."""

0 commit comments

Comments
 (0)