Skip to content

Commit f3340c2

Browse files
committed
Update the magic number, rearrange typing.py accordingly
1 parent b9d8fbb commit f3340c2

File tree

3 files changed

+110
-106
lines changed

3 files changed

+110
-106
lines changed

Lib/importlib/_bootstrap_external.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ def _write_atomic(path, data, mode=0o666):
439439
# Python 3.12a7 3523 (Convert COMPARE_AND_BRANCH back to COMPARE_OP)
440440
# Python 3.12a7 3524 (Shrink the BINARY_SUBSCR caches)
441441
# Python 3.12b1 3525 (Shrink the CALL caches)
442+
# Python 3.12b1 3526 (Add new instructions for PEP 695)
442443

443444
# Python 3.13 will start with 3550
444445

@@ -455,7 +456,7 @@ def _write_atomic(path, data, mode=0o666):
455456
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
456457
# in PC/launcher.c must also be updated.
457458

458-
MAGIC_NUMBER = (3525).to_bytes(2, 'little') + b'\r\n'
459+
MAGIC_NUMBER = (3526).to_bytes(2, 'little') + b'\r\n'
459460

460461
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
461462

Lib/typing.py

Lines changed: 106 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,8 @@ def _is_unpacked_typevartuple(x: Any) -> bool:
918918

919919

920920
def _is_typevar_like(x: Any) -> bool:
921-
return isinstance(x, (TypeVar, ParamSpec)) or _is_unpacked_typevartuple(x)
921+
# TODO(PEP 695): remove TypeVarTuple here
922+
return isinstance(x, (TypeVar, ParamSpec, TypeVarTuple)) or _is_unpacked_typevartuple(x)
922923

923924

924925
class _PickleUsingNameMixin:
@@ -1301,29 +1302,93 @@ def __typing_prepare_subst__(self, alias, args):
13011302

13021303

13031304
import builtins
1304-
if hasattr(builtins, "TypeVar"):
1305-
class _Dummy[T, *Ts, **P]:
1306-
type_params = (T, Ts, P)
13071305

1308-
TypeVar = type(_Dummy.type_params[0])
1309-
TypeVarTuple = type(_Dummy.type_params[1])
1310-
ParamSpec = type(_Dummy.type_params[2])
1311-
ParamSpecArgs = type(ParamSpec("P").args)
1312-
ParamSpecKwargs = type(ParamSpec("P").kwargs)
13131306

1314-
del _Dummy
1307+
@_tp_cache
1308+
def _generic_class_getitem(cls, params):
1309+
"""Parameterizes a generic class.
13151310
1316-
import copyreg
1311+
At least, parameterizing a generic class is the *main* thing this method
1312+
does. For example, for some generic class `Foo`, this is called when we
1313+
do `Foo[int]` - there, with `cls=Foo` and `params=int`.
13171314
1318-
def _pickle_psargs(psargs):
1319-
return ParamSpecArgs, (psargs.__origin__,)
1315+
However, note that this method is also called when defining generic
1316+
classes in the first place with `class Foo(Generic[T]): ...`.
1317+
"""
1318+
if not isinstance(params, tuple):
1319+
params = (params,)
13201320

1321-
copyreg.pickle(ParamSpecArgs, _pickle_psargs)
1321+
params = tuple(_type_convert(p) for p in params)
1322+
if cls in (builtins.Generic, Protocol):
1323+
# Generic and Protocol can only be subscripted with unique type variables.
1324+
if not params:
1325+
raise TypeError(
1326+
f"Parameter list to {cls.__qualname__}[...] cannot be empty"
1327+
)
1328+
if not all(_is_typevar_like(p) for p in params):
1329+
raise TypeError(
1330+
f"Parameters to {cls.__name__}[...] must all be type variables "
1331+
f"or parameter specification variables.")
1332+
if len(set(params)) != len(params):
1333+
raise TypeError(
1334+
f"Parameters to {cls.__name__}[...] must all be unique")
1335+
else:
1336+
# Subscripting a regular Generic subclass.
1337+
for param in cls.__parameters__:
1338+
prepare = getattr(param, '__typing_prepare_subst__', None)
1339+
if prepare is not None:
1340+
params = prepare(cls, params)
1341+
_check_generic(cls, params, len(cls.__parameters__))
13221342

1323-
def _pickle_pskwargs(pskwargs):
1324-
return ParamSpecKwargs, (pskwargs.__origin__,)
1343+
new_args = []
1344+
for param, new_arg in zip(cls.__parameters__, params):
1345+
if isinstance(param, TypeVarTuple):
1346+
new_args.extend(new_arg)
1347+
else:
1348+
new_args.append(new_arg)
1349+
params = tuple(new_args)
1350+
1351+
return _GenericAlias(cls, params,
1352+
_paramspec_tvars=True)
1353+
1354+
1355+
def _generic_init_subclass(cls, *args, **kwargs):
1356+
super(builtins.Generic, cls).__init_subclass__(*args, **kwargs)
1357+
tvars = []
1358+
if '__orig_bases__' in cls.__dict__:
1359+
error = builtins.Generic in cls.__orig_bases__
1360+
else:
1361+
error = (builtins.Generic in cls.__bases__ and
1362+
cls.__name__ != 'Protocol' and
1363+
type(cls) != _TypedDictMeta)
1364+
if error:
1365+
raise TypeError("Cannot inherit from plain Generic")
1366+
if '__orig_bases__' in cls.__dict__:
1367+
tvars = _collect_parameters(cls.__orig_bases__)
1368+
# Look for Generic[T1, ..., Tn].
1369+
# If found, tvars must be a subset of it.
1370+
# If not found, tvars is it.
1371+
# Also check for and reject plain Generic,
1372+
# and reject multiple Generic[...].
1373+
gvars = None
1374+
for base in cls.__orig_bases__:
1375+
if (isinstance(base, _GenericAlias) and
1376+
base.__origin__ is builtins.Generic):
1377+
if gvars is not None:
1378+
raise TypeError(
1379+
"Cannot inherit from Generic[...] multiple types.")
1380+
gvars = base.__parameters__
1381+
if gvars is not None:
1382+
tvarset = set(tvars)
1383+
gvarset = set(gvars)
1384+
if not tvarset <= gvarset:
1385+
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
1386+
s_args = ', '.join(str(g) for g in gvars)
1387+
raise TypeError(f"Some type variables ({s_vars}) are"
1388+
f" not listed in Generic[{s_args}]")
1389+
tvars = gvars
1390+
cls.__parameters__ = tuple(tvars)
13251391

1326-
copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs)
13271392

13281393
def _is_dunder(attr):
13291394
return attr.startswith('__') and attr.endswith('__')
@@ -1969,92 +2034,6 @@ def __init_subclass__(cls, *args, **kwargs):
19692034
cls.__parameters__ = tuple(tvars)
19702035

19712036

1972-
@_tp_cache
1973-
def _generic_class_getitem(cls, params):
1974-
"""Parameterizes a generic class.
1975-
1976-
At least, parameterizing a generic class is the *main* thing this method
1977-
does. For example, for some generic class `Foo`, this is called when we
1978-
do `Foo[int]` - there, with `cls=Foo` and `params=int`.
1979-
1980-
However, note that this method is also called when defining generic
1981-
classes in the first place with `class Foo(Generic[T]): ...`.
1982-
"""
1983-
if not isinstance(params, tuple):
1984-
params = (params,)
1985-
1986-
params = tuple(_type_convert(p) for p in params)
1987-
if cls in (builtins.Generic, Protocol):
1988-
# Generic and Protocol can only be subscripted with unique type variables.
1989-
if not params:
1990-
raise TypeError(
1991-
f"Parameter list to {cls.__qualname__}[...] cannot be empty"
1992-
)
1993-
if not all(_is_typevar_like(p) for p in params):
1994-
raise TypeError(
1995-
f"Parameters to {cls.__name__}[...] must all be type variables "
1996-
f"or parameter specification variables.")
1997-
if len(set(params)) != len(params):
1998-
raise TypeError(
1999-
f"Parameters to {cls.__name__}[...] must all be unique")
2000-
else:
2001-
# Subscripting a regular Generic subclass.
2002-
for param in cls.__parameters__:
2003-
prepare = getattr(param, '__typing_prepare_subst__', None)
2004-
if prepare is not None:
2005-
params = prepare(cls, params)
2006-
_check_generic(cls, params, len(cls.__parameters__))
2007-
2008-
new_args = []
2009-
for param, new_arg in zip(cls.__parameters__, params):
2010-
if isinstance(param, TypeVarTuple):
2011-
new_args.extend(new_arg)
2012-
else:
2013-
new_args.append(new_arg)
2014-
params = tuple(new_args)
2015-
2016-
return _GenericAlias(cls, params,
2017-
_paramspec_tvars=True)
2018-
2019-
import builtins
2020-
2021-
def _generic_init_subclass(cls, *args, **kwargs):
2022-
super(builtins.Generic, cls).__init_subclass__(*args, **kwargs)
2023-
tvars = []
2024-
if '__orig_bases__' in cls.__dict__:
2025-
error = builtins.Generic in cls.__orig_bases__
2026-
else:
2027-
error = (builtins.Generic in cls.__bases__ and
2028-
cls.__name__ != 'Protocol' and
2029-
type(cls) != _TypedDictMeta)
2030-
if error:
2031-
raise TypeError("Cannot inherit from plain Generic")
2032-
if '__orig_bases__' in cls.__dict__:
2033-
tvars = _collect_parameters(cls.__orig_bases__)
2034-
# Look for Generic[T1, ..., Tn].
2035-
# If found, tvars must be a subset of it.
2036-
# If not found, tvars is it.
2037-
# Also check for and reject plain Generic,
2038-
# and reject multiple Generic[...].
2039-
gvars = None
2040-
for base in cls.__orig_bases__:
2041-
if (isinstance(base, _GenericAlias) and
2042-
base.__origin__ is builtins.Generic):
2043-
if gvars is not None:
2044-
raise TypeError(
2045-
"Cannot inherit from Generic[...] multiple types.")
2046-
gvars = base.__parameters__
2047-
if gvars is not None:
2048-
tvarset = set(tvars)
2049-
gvarset = set(gvars)
2050-
if not tvarset <= gvarset:
2051-
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
2052-
s_args = ', '.join(str(g) for g in gvars)
2053-
raise TypeError(f"Some type variables ({s_vars}) are"
2054-
f" not listed in Generic[{s_args}]")
2055-
tvars = gvars
2056-
cls.__parameters__ = tuple(tvars)
2057-
20582037

20592038
class _TypingEllipsis:
20602039
"""Internal placeholder for ... (ellipsis)."""
@@ -2303,6 +2282,30 @@ def _proto_hook(other):
23032282
if cls.__init__ is Protocol.__init__:
23042283
cls.__init__ = _no_init_or_replace_init
23052284

2285+
if hasattr(builtins, "TypeVar"):
2286+
def _dummy[T, *Ts, **P]():
2287+
pass
2288+
2289+
TypeVar = type(_dummy.__type_variables__[0])
2290+
TypeVarTuple = type(_dummy.__type_variables__[1])
2291+
ParamSpec = type(_dummy.__type_variables__[2])
2292+
ParamSpecArgs = type(ParamSpec("P").args)
2293+
ParamSpecKwargs = type(ParamSpec("P").kwargs)
2294+
2295+
del _dummy
2296+
2297+
import copyreg
2298+
2299+
def _pickle_psargs(psargs):
2300+
return ParamSpecArgs, (psargs.__origin__,)
2301+
2302+
copyreg.pickle(ParamSpecArgs, _pickle_psargs)
2303+
2304+
def _pickle_pskwargs(pskwargs):
2305+
return ParamSpecKwargs, (pskwargs.__origin__,)
2306+
2307+
copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs)
2308+
23062309

23072310
class _AnnotatedAlias(_NotIterable, _GenericAlias, _root=True):
23082311
"""Runtime representation of an annotated type.

Objects/typevarobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ class paramspec "paramspecobject *" "&_PyParamSpec_Type"
1111
class paramspecargs "paramspecargsobject *" "&_PyParamSpecArgs_Type"
1212
class paramspeckwargs "paramspeckwargsobject *" "&_PyParamSpecKwargs_Type"
1313
class typevartuple "typevartupleobject *" "&_PyTypeVarTuple_Type"
14-
class Generic "PyObject *" "&PyGeneric_Type
14+
class Generic "PyObject *" "&PyGeneric_Type"
1515
[clinic start generated code]*/
16-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=74cb9c15a049111b]*/
16+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b0f1a94d4a27c0c]*/
1717

1818
typedef struct {
1919
PyObject_HEAD

0 commit comments

Comments
 (0)