summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/ast.py26
-rw-r--r--Lib/importlib/_bootstrap_external.py3
-rw-r--r--Lib/keyword.py3
-rw-r--r--Lib/opcode.py20
-rw-r--r--Lib/test/support/__init__.py9
-rw-r--r--Lib/test/test_ast.py125
-rw-r--r--Lib/test/test_keyword.py3
-rw-r--r--Lib/test/test_sys.py2
-rw-r--r--Lib/test/test_type_aliases.py204
-rw-r--r--Lib/test/test_type_params.py847
-rw-r--r--Lib/test/test_typing.py54
-rw-r--r--Lib/typing.py591
12 files changed, 1380 insertions, 507 deletions
diff --git a/Lib/ast.py b/Lib/ast.py
index 6515204..08904af 100644
--- a/Lib/ast.py
+++ b/Lib/ast.py
@@ -1051,6 +1051,7 @@ class _Unparser(NodeVisitor):
self.fill("@")
self.traverse(deco)
self.fill("class " + node.name)
+ self._typeparams_helper(node.typeparams)
with self.delimit_if("(", ")", condition = node.bases or node.keywords):
comma = False
for e in node.bases:
@@ -1082,6 +1083,7 @@ class _Unparser(NodeVisitor):
self.traverse(deco)
def_str = fill_suffix + " " + node.name
self.fill(def_str)
+ self._typeparams_helper(node.typeparams)
with self.delimit("(", ")"):
self.traverse(node.args)
if node.returns:
@@ -1090,6 +1092,30 @@ class _Unparser(NodeVisitor):
with self.block(extra=self.get_type_comment(node)):
self._write_docstring_and_traverse_body(node)
+ def _typeparams_helper(self, typeparams):
+ if typeparams is not None and len(typeparams) > 0:
+ with self.delimit("[", "]"):
+ self.interleave(lambda: self.write(", "), self.traverse, typeparams)
+
+ def visit_TypeVar(self, node):
+ self.write(node.name)
+ if node.bound:
+ self.write(": ")
+ self.traverse(node.bound)
+
+ def visit_TypeVarTuple(self, node):
+ self.write("*" + node.name)
+
+ def visit_ParamSpec(self, node):
+ self.write("**" + node.name)
+
+ def visit_TypeAlias(self, node):
+ self.fill("type ")
+ self.traverse(node.name)
+ self._typeparams_helper(node.typeparams)
+ self.write(" = ")
+ self.traverse(node.value)
+
def visit_For(self, node):
self._for_helper("for ", node)
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 3ca5a1a..73ac440 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -444,6 +444,7 @@ _code_type = type(_write_atomic.__code__)
# Python 3.12b1 3528 (Add LOAD_SUPER_ATTR_METHOD specialization)
# Python 3.12b1 3529 (Inline list/dict/set comprehensions)
# Python 3.12b1 3530 (Shrink the LOAD_SUPER_ATTR caches)
+# Python 3.12b1 3531 (Add PEP 695 changes)
# Python 3.13 will start with 3550
@@ -460,7 +461,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3530).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3531).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
diff --git a/Lib/keyword.py b/Lib/keyword.py
index cc2b46b..e22c837 100644
--- a/Lib/keyword.py
+++ b/Lib/keyword.py
@@ -56,7 +56,8 @@ kwlist = [
softkwlist = [
'_',
'case',
- 'match'
+ 'match',
+ 'type'
]
iskeyword = frozenset(kwlist).__contains__
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 155466b..97d0a65 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -131,6 +131,7 @@ def_op('RETURN_GENERATOR', 75)
def_op('RETURN_VALUE', 83)
def_op('SETUP_ANNOTATIONS', 85)
+def_op('LOAD_LOCALS', 87)
def_op('POP_EXCEPT', 89)
@@ -206,7 +207,6 @@ EXTENDED_ARG = 144
def_op('LIST_APPEND', 145)
def_op('SET_ADD', 146)
def_op('MAP_ADD', 147)
-def_op('LOAD_CLASSDEREF', 148)
hasfree.append(148)
def_op('COPY_FREE_VARS', 149)
def_op('YIELD_VALUE', 150)
@@ -228,6 +228,10 @@ hasconst.append(172)
def_op('CALL_INTRINSIC_1', 173)
def_op('CALL_INTRINSIC_2', 174)
+name_op('LOAD_FROM_DICT_OR_GLOBALS', 175)
+def_op('LOAD_FROM_DICT_OR_DEREF', 176)
+hasfree.append(176)
+
# Instrumented instructions
MIN_INSTRUMENTED_OPCODE = 238
@@ -318,12 +322,20 @@ _intrinsic_1_descs = [
"INTRINSIC_ASYNC_GEN_WRAP",
"INTRINSIC_UNARY_POSITIVE",
"INTRINSIC_LIST_TO_TUPLE",
+ "INTRINSIC_TYPEVAR",
+ "INTRINSIC_PARAMSPEC",
+ "INTRINSIC_TYPEVARTUPLE",
+ "INTRINSIC_SUBSCRIPT_GENERIC",
+ "INTRINSIC_TYPEALIAS",
]
_intrinsic_2_descs = [
- 'INTRINSIC_2_INVALID',
- 'INTRINSIC_PREP_RERAISE_STAR',
- ]
+ "INTRINSIC_2_INVALID",
+ "INTRINSIC_PREP_RERAISE_STAR",
+ "INTRINSIC_TYPEVAR_WITH_BOUND",
+ "INTRINSIC_TYPEVAR_WITH_CONSTRAINTS",
+ "INTRINSIC_SET_FUNCTION_TYPE_PARAMS",
+]
_specializations = {
"BINARY_OP": [
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index d063837..d555c53f 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -12,6 +12,7 @@ import re
import stat
import sys
import sysconfig
+import textwrap
import time
import types
import unittest
@@ -619,6 +620,14 @@ def sortdict(dict):
withcommas = ", ".join(reprpairs)
return "{%s}" % withcommas
+
+def run_code(code: str) -> dict[str, object]:
+ """Run a piece of code after dedenting it, and return its global namespace."""
+ ns = {}
+ exec(textwrap.dedent(code), ns)
+ return ns
+
+
def check_syntax_error(testcase, statement, errtext='', *, lineno=None, offset=None):
with testcase.assertRaisesRegex(SyntaxError, errtext) as cm:
compile(statement, '<test string>', 'exec')
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index 34808ed..cf128e1 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -181,7 +181,22 @@ exec_tests = [
"def f(a=1, /, b=2, *, c): pass",
"def f(a=1, /, b=2, *, c=4, **kwargs): pass",
"def f(a=1, /, b=2, *, c, **kwargs): pass",
-
+ # Type aliases
+ "type X = int",
+ "type X[T] = int",
+ "type X[T, *Ts, **P] = (T, Ts, P)",
+ "type X[T: int, *Ts, **P] = (T, Ts, P)",
+ "type X[T: (int, str), *Ts, **P] = (T, Ts, P)",
+ # Generic classes
+ "class X[T]: pass",
+ "class X[T, *Ts, **P]: pass",
+ "class X[T: int, *Ts, **P]: pass",
+ "class X[T: (int, str), *Ts, **P]: pass",
+ # Generic functions
+ "def f[T](): pass",
+ "def f[T, *Ts, **P](): pass",
+ "def f[T: int, *Ts, **P](): pass",
+ "def f[T: (int, str), *Ts, **P](): pass",
]
# These are compiled through "single"
@@ -262,7 +277,6 @@ eval_tests = [
"()",
# Combination
"a.b.c.d(a.b[1:2])",
-
]
# TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension
@@ -1013,6 +1027,18 @@ class AST_Tests(unittest.TestCase):
with self.assertRaises(SyntaxError):
ast.parse(code, feature_version=(3, 10))
+ def test_type_params_feature_version(self):
+ samples = [
+ "type X = int",
+ "class X[T]: pass",
+ "def f[T](): pass",
+ ]
+ for sample in samples:
+ with self.subTest(sample):
+ ast.parse(sample)
+ with self.assertRaises(SyntaxError):
+ ast.parse(sample, feature_version=(3, 11))
+
def test_invalid_major_feature_version(self):
with self.assertRaises(ValueError):
ast.parse('pass', feature_version=(2, 7))
@@ -1557,16 +1583,16 @@ class ASTValidatorTests(unittest.TestCase):
def test_funcdef(self):
a = ast.arguments([], [], None, [], [], None, [])
- f = ast.FunctionDef("x", a, [], [], None)
+ f = ast.FunctionDef("x", [], a, [], [], None)
self.stmt(f, "empty body on FunctionDef")
- f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())],
+ f = ast.FunctionDef("x", [], a, [ast.Pass()], [ast.Name("x", ast.Store())],
None)
self.stmt(f, "must have Load context")
- f = ast.FunctionDef("x", a, [ast.Pass()], [],
+ f = ast.FunctionDef("x", [], a, [ast.Pass()], [],
ast.Name("x", ast.Store()))
self.stmt(f, "must have Load context")
def fac(args):
- return ast.FunctionDef("x", args, [ast.Pass()], [], None)
+ return ast.FunctionDef("x", [], args, [ast.Pass()], [], None)
self._check_arguments(fac, self.stmt)
def test_classdef(self):
@@ -1579,7 +1605,7 @@ class ASTValidatorTests(unittest.TestCase):
body = [ast.Pass()]
if decorator_list is None:
decorator_list = []
- return ast.ClassDef("myclass", bases, keywords,
+ return ast.ClassDef("myclass", [], bases, keywords,
body, decorator_list)
self.stmt(cls(bases=[ast.Name("x", ast.Store())]),
"must have Load context")
@@ -2869,23 +2895,23 @@ def main():
exec_results = [
('Module', [('Expr', (1, 0, 1, 4), ('Constant', (1, 0, 1, 4), None, None))], []),
('Module', [('Expr', (1, 0, 1, 18), ('Constant', (1, 0, 1, 18), 'module docstring', None))], []),
-('Module', [('FunctionDef', (1, 0, 1, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 14), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 23), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 21), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 71), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 27), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 45), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
-('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [('Pass', (1, 8, 1, 12))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 21), 'C', [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []),
-('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 14), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 23), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 21), 'f', [], ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 71), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 27), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 45), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
+('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [], [('Pass', (1, 8, 1, 12))], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 21), 'C', [], [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []),
('Module', [('Delete', (1, 0, 1, 5), [('Name', (1, 4, 1, 5), 'v', ('Del',))])], []),
('Module', [('Assign', (1, 0, 1, 5), [('Name', (1, 0, 1, 1), 'v', ('Store',))], ('Constant', (1, 4, 1, 5), 1, None), None)], []),
('Module', [('Assign', (1, 0, 1, 7), [('Tuple', (1, 0, 1, 3), [('Name', (1, 0, 1, 1), 'a', ('Store',)), ('Name', (1, 2, 1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 6, 1, 7), 'c', ('Load',)), None)], []),
@@ -2922,28 +2948,41 @@ exec_results = [
('Module', [('Expr', (1, 0, 1, 20), ('DictComp', (1, 0, 1, 20), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'v', ('Store',)), ('Name', (1, 13, 1, 14), 'w', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'x', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 19), ('SetComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 12, 1, 13), 'x', ('Load',)), [('Name', (1, 17, 1, 18), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 16), ('SetComp', (1, 0, 1, 16), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7, 1, 10), [('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 9, 1, 10), 'm', ('Store',))], ('Store',)), ('Name', (1, 14, 1, 15), 'x', ('Load',)), [], 0)]))], []),
-('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []),
-('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []),
-('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []),
+('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []),
+('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []),
+('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []),
('Module', [('Expr', (1, 0, 1, 14), ('Dict', (1, 0, 1, 14), [None, ('Constant', (1, 10, 1, 11), 2, None)], [('Dict', (1, 3, 1, 8), [('Constant', (1, 4, 1, 5), 1, None)], [('Constant', (1, 6, 1, 7), 2, None)]), ('Constant', (1, 12, 1, 13), 3, None)]))], []),
('Module', [('Expr', (1, 0, 1, 12), ('Set', (1, 0, 1, 12), [('Starred', (1, 1, 1, 8), ('Set', (1, 2, 1, 8), [('Constant', (1, 3, 1, 4), 1, None), ('Constant', (1, 6, 1, 7), 2, None)]), ('Load',)), ('Constant', (1, 10, 1, 11), 3, None)]))], []),
-('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
-('Module', [('FunctionDef', (4, 0, 4, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
-('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
-('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []),
-('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
-('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
+('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
+('Module', [('FunctionDef', (4, 0, 4, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
+('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
+('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []),
+('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
+('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
('Module', [('Expr', (1, 0, 1, 8), ('NamedExpr', (1, 1, 1, 7), ('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Constant', (1, 6, 1, 7), 1, None)))], []),
-('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 39), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 20), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 30), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 42), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 40), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 39), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 20), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 30), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 42), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 40), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []),
+('Module', [('TypeAlias', (1, 0, 1, 12), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [], ('Name', (1, 9, 1, 12), 'int', ('Load',)))], []),
+('Module', [('TypeAlias', (1, 0, 1, 15), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None)], ('Name', (1, 12, 1, 15), 'int', ('Load',)))], []),
+('Module', [('TypeAlias', (1, 0, 1, 32), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts'), ('ParamSpec', (1, 15, 1, 18), 'P')], ('Tuple', (1, 22, 1, 32), [('Name', (1, 23, 1, 24), 'T', ('Load',)), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Name', (1, 30, 1, 31), 'P', ('Load',))], ('Load',)))], []),
+('Module', [('TypeAlias', (1, 0, 1, 37), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 13), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',))), ('TypeVarTuple', (1, 15, 1, 18), 'Ts'), ('ParamSpec', (1, 20, 1, 23), 'P')], ('Tuple', (1, 27, 1, 37), [('Name', (1, 28, 1, 29), 'T', ('Load',)), ('Name', (1, 31, 1, 33), 'Ts', ('Load',)), ('Name', (1, 35, 1, 36), 'P', ('Load',))], ('Load',)))], []),
+('Module', [('TypeAlias', (1, 0, 1, 44), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 20), 'T', ('Tuple', (1, 10, 1, 20), [('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Name', (1, 16, 1, 19), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 22, 1, 25), 'Ts'), ('ParamSpec', (1, 27, 1, 30), 'P')], ('Tuple', (1, 34, 1, 44), [('Name', (1, 35, 1, 36), 'T', ('Load',)), ('Name', (1, 38, 1, 40), 'Ts', ('Load',)), ('Name', (1, 42, 1, 43), 'P', ('Load',))], ('Load',)))], []),
+('Module', [('ClassDef', (1, 0, 1, 16), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None)], [], [], [('Pass', (1, 12, 1, 16))], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 26), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts'), ('ParamSpec', (1, 16, 1, 19), 'P')], [], [], [('Pass', (1, 22, 1, 26))], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 31), 'X', [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',))), ('TypeVarTuple', (1, 16, 1, 19), 'Ts'), ('ParamSpec', (1, 21, 1, 24), 'P')], [], [], [('Pass', (1, 27, 1, 31))], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 38), 'X', [('TypeVar', (1, 8, 1, 21), 'T', ('Tuple', (1, 11, 1, 21), [('Name', (1, 12, 1, 15), 'int', ('Load',)), ('Name', (1, 17, 1, 20), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 23, 1, 26), 'Ts'), ('ParamSpec', (1, 28, 1, 31), 'P')], [], [], [('Pass', (1, 34, 1, 38))], [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None)], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts'), ('ParamSpec', (1, 14, 1, 17), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 31), 'f', [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',))), ('TypeVarTuple', (1, 14, 1, 17), 'Ts'), ('ParamSpec', (1, 19, 1, 22), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 38), 'f', [('TypeVar', (1, 6, 1, 19), 'T', ('Tuple', (1, 9, 1, 19), [('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Name', (1, 15, 1, 18), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 21, 1, 24), 'Ts'), ('ParamSpec', (1, 26, 1, 29), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None)], []),
]
single_results = [
('Interactive', [('Expr', (1, 0, 1, 3), ('BinOp', (1, 0, 1, 3), ('Constant', (1, 0, 1, 1), 1, None), ('Add',), ('Constant', (1, 2, 1, 3), 2, None)))]),
diff --git a/Lib/test/test_keyword.py b/Lib/test/test_keyword.py
index f329f88..858e5de 100644
--- a/Lib/test/test_keyword.py
+++ b/Lib/test/test_keyword.py
@@ -39,7 +39,8 @@ class Test_iskeyword(unittest.TestCase):
self.assertIn("async", keyword.kwlist)
self.assertIn("await", keyword.kwlist)
- def test_match_and_case_are_soft_keywords(self):
+ def test_soft_keywords(self):
+ self.assertIn("type", keyword.softkwlist)
self.assertIn("match", keyword.softkwlist)
self.assertIn("case", keyword.softkwlist)
self.assertIn("_", keyword.softkwlist)
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index e1db450..d81501f 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1449,7 +1449,7 @@ class SizeofTest(unittest.TestCase):
check(x, size('3Pi3c7P2ic??2P'))
# function
def func(): pass
- check(func, size('14Pi'))
+ check(func, size('15Pi'))
class c():
@staticmethod
def foo():
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
new file mode 100644
index 0000000..d2abb93
--- /dev/null
+++ b/Lib/test/test_type_aliases.py
@@ -0,0 +1,204 @@
+import types
+import unittest
+from test.support import check_syntax_error, run_code
+
+from typing import Callable, TypeAliasType, TypeVar, get_args
+
+
+class TypeParamsInvalidTest(unittest.TestCase):
+ def test_name_collision_01(self):
+ check_syntax_error(self, """type TA1[A, **A] = None""", "duplicate type parameter 'A'")
+
+ def test_name_non_collision_02(self):
+ ns = run_code("""type TA1[A] = lambda A: A""")
+ self.assertIsInstance(ns["TA1"], TypeAliasType)
+ self.assertTrue(callable(ns["TA1"].__value__))
+ self.assertEqual("arg", ns["TA1"].__value__("arg"))
+
+ def test_name_non_collision_03(self):
+ ns = run_code("""
+ class Outer[A]:
+ type TA1[A] = None
+ """
+ )
+ outer_A, = ns["Outer"].__type_params__
+ inner_A, = ns["Outer"].TA1.__type_params__
+ self.assertIsNot(outer_A, inner_A)
+
+
+class TypeParamsAccessTest(unittest.TestCase):
+ def test_alias_access_01(self):
+ ns = run_code("type TA1[A, B] = dict[A, B]")
+ alias = ns["TA1"]
+ self.assertIsInstance(alias, TypeAliasType)
+ self.assertEqual(alias.__type_params__, get_args(alias.__value__))
+
+ def test_alias_access_02(self):
+ ns = run_code("""
+ type TA1[A, B] = TA1[A, B] | int
+ """
+ )
+ alias = ns["TA1"]
+ self.assertIsInstance(alias, TypeAliasType)
+ A, B = alias.__type_params__
+ self.assertEqual(alias.__value__, alias[A, B] | int)
+
+ def test_alias_access_03(self):
+ ns = run_code("""
+ class Outer[A]:
+ def inner[B](self):
+ type TA1[C] = TA1[A, B] | int
+ return TA1
+ """
+ )
+ cls = ns["Outer"]
+ A, = cls.__type_params__
+ B, = cls.inner.__type_params__
+ alias = cls.inner(None)
+ self.assertIsInstance(alias, TypeAliasType)
+ alias2 = cls.inner(None)
+ self.assertIsNot(alias, alias2)
+ self.assertEqual(len(alias.__type_params__), 1)
+
+ self.assertEqual(alias.__value__, alias[A, B] | int)
+
+
+class TypeParamsAliasValueTest(unittest.TestCase):
+ def test_alias_value_01(self):
+ type TA1 = int
+
+ self.assertIsInstance(TA1, TypeAliasType)
+ self.assertEqual(TA1.__value__, int)
+ self.assertEqual(TA1.__parameters__, ())
+ self.assertEqual(TA1.__type_params__, ())
+
+ type TA2 = TA1 | str
+
+ self.assertIsInstance(TA2, TypeAliasType)
+ a, b = TA2.__value__.__args__
+ self.assertEqual(a, TA1)
+ self.assertEqual(b, str)
+ self.assertEqual(TA2.__parameters__, ())
+ self.assertEqual(TA2.__type_params__, ())
+
+ def test_alias_value_02(self):
+ class Parent[A]:
+ type TA1[B] = dict[A, B]
+
+ self.assertIsInstance(Parent.TA1, TypeAliasType)
+ self.assertEqual(len(Parent.TA1.__parameters__), 1)
+ self.assertEqual(len(Parent.__parameters__), 1)
+ a, = Parent.__parameters__
+ b, = Parent.TA1.__parameters__
+ self.assertEqual(Parent.__type_params__, (a,))
+ self.assertEqual(Parent.TA1.__type_params__, (b,))
+ self.assertEqual(Parent.TA1.__value__, dict[a, b])
+
+ def test_alias_value_03(self):
+ def outer[A]():
+ type TA1[B] = dict[A, B]
+ return TA1
+
+ o = outer()
+ self.assertIsInstance(o, TypeAliasType)
+ self.assertEqual(len(o.__parameters__), 1)
+ self.assertEqual(len(outer.__type_params__), 1)
+ b = o.__parameters__[0]
+ self.assertEqual(o.__type_params__, (b,))
+
+ def test_alias_value_04(self):
+ def more_generic[T, *Ts, **P]():
+ type TA[T2, *Ts2, **P2] = tuple[Callable[P, tuple[T, *Ts]], Callable[P2, tuple[T2, *Ts2]]]
+ return TA
+
+ alias = more_generic()
+ self.assertIsInstance(alias, TypeAliasType)
+ T2, Ts2, P2 = alias.__type_params__
+ self.assertEqual(alias.__parameters__, (T2, *Ts2, P2))
+ T, Ts, P = more_generic.__type_params__
+ self.assertEqual(alias.__value__, tuple[Callable[P, tuple[T, *Ts]], Callable[P2, tuple[T2, *Ts2]]])
+
+ def test_subscripting(self):
+ type NonGeneric = int
+ type Generic[A] = dict[A, A]
+ type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
+
+ with self.assertRaises(TypeError):
+ NonGeneric[int]
+
+ specialized = Generic[int]
+ self.assertIsInstance(specialized, types.GenericAlias)
+ self.assertIs(specialized.__origin__, Generic)
+ self.assertEqual(specialized.__args__, (int,))
+
+ specialized2 = VeryGeneric[int, str, float, [bool, range]]
+ self.assertIsInstance(specialized2, types.GenericAlias)
+ self.assertIs(specialized2.__origin__, VeryGeneric)
+ self.assertEqual(specialized2.__args__, (int, str, float, [bool, range]))
+
+ def test_repr(self):
+ type Simple = int
+ self.assertEqual(repr(Simple), "Simple")
+
+ def test_recursive_repr(self):
+ type Recursive = Recursive
+ self.assertEqual(repr(Recursive), "Recursive")
+
+ type X = list[Y]
+ type Y = list[X]
+ self.assertEqual(repr(X), "X")
+
+
+class TypeAliasConstructorTest(unittest.TestCase):
+ def test_basic(self):
+ TA = TypeAliasType("TA", int)
+ self.assertEqual(TA.__name__, "TA")
+ self.assertIs(TA.__value__, int)
+ self.assertEqual(TA.__type_params__, ())
+
+ def test_generic(self):
+ T = TypeVar("T")
+ TA = TypeAliasType("TA", list[T], type_params=(T,))
+ self.assertEqual(TA.__name__, "TA")
+ self.assertEqual(TA.__value__, list[T])
+ self.assertEqual(TA.__type_params__, (T,))
+
+ def test_keywords(self):
+ TA = TypeAliasType(name="TA", value=int)
+ self.assertEqual(TA.__name__, "TA")
+ self.assertIs(TA.__value__, int)
+ self.assertEqual(TA.__type_params__, ())
+
+ def test_errors(self):
+ with self.assertRaises(TypeError):
+ TypeAliasType()
+ with self.assertRaises(TypeError):
+ TypeAliasType("TA")
+ with self.assertRaises(TypeError):
+ TypeAliasType("TA", list, ())
+ with self.assertRaises(TypeError):
+ TypeAliasType("TA", list, type_params=42)
+
+
+class TypeAliasTypeTest(unittest.TestCase):
+ def test_immutable(self):
+ with self.assertRaises(TypeError):
+ TypeAliasType.whatever = "not allowed"
+
+ def test_no_subclassing(self):
+ with self.assertRaisesRegex(TypeError, "not an acceptable base type"):
+ class MyAlias(TypeAliasType):
+ pass
+
+ def test_union(self):
+ type Alias1 = int
+ type Alias2 = str
+ union = Alias1 | Alias2
+ self.assertIsInstance(union, types.UnionType)
+ self.assertEqual(get_args(union), (Alias1, Alias2))
+ union2 = Alias1 | list[float]
+ self.assertIsInstance(union2, types.UnionType)
+ self.assertEqual(get_args(union2), (Alias1, list[float]))
+ union3 = list[range] | Alias1
+ self.assertIsInstance(union3, types.UnionType)
+ self.assertEqual(get_args(union3), (list[range], Alias1))
diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py
new file mode 100644
index 0000000..3ca13c2
--- /dev/null
+++ b/Lib/test/test_type_params.py
@@ -0,0 +1,847 @@
+import asyncio
+import textwrap
+import types
+import unittest
+from test.support import requires_working_socket, check_syntax_error, run_code
+
+from typing import Generic, Sequence, TypeVar, TypeVarTuple, ParamSpec, get_args
+
+
+class TypeParamsInvalidTest(unittest.TestCase):
+ def test_name_collision_01(self):
+ check_syntax_error(self, """def func[**A, A](): ...""")
+
+ def test_name_non_collision_02(self):
+ ns = run_code("""def func[A](A): return A""")
+ func = ns["func"]
+ self.assertEqual(func(1), 1)
+ A, = func.__type_params__
+ self.assertEqual(A.__name__, "A")
+
+ def test_name_non_collision_03(self):
+ ns = run_code("""def func[A](*A): return A""")
+ func = ns["func"]
+ self.assertEqual(func(1), (1,))
+ A, = func.__type_params__
+ self.assertEqual(A.__name__, "A")
+
+ def test_name_non_collision_04(self):
+ # Mangled names should not cause a conflict.
+ ns = run_code("""
+ class ClassA:
+ def func[__A](self, __A): return __A
+ """
+ )
+ cls = ns["ClassA"]
+ self.assertEqual(cls().func(1), 1)
+ A, = cls.func.__type_params__
+ self.assertEqual(A.__name__, "__A")
+
+ def test_name_non_collision_05(self):
+ ns = run_code("""
+ class ClassA:
+ def func[_ClassA__A](self, __A): return __A
+ """
+ )
+ cls = ns["ClassA"]
+ self.assertEqual(cls().func(1), 1)
+ A, = cls.func.__type_params__
+ self.assertEqual(A.__name__, "_ClassA__A")
+
+ def test_name_non_collision_06(self):
+ ns = run_code("""
+ class ClassA[X]:
+ def func(self, X): return X
+ """
+ )
+ cls = ns["ClassA"]
+ self.assertEqual(cls().func(1), 1)
+ X, = cls.__type_params__
+ self.assertEqual(X.__name__, "X")
+
+ def test_name_non_collision_07(self):
+ ns = run_code("""
+ class ClassA[X]:
+ def func(self):
+ X = 1
+ return X
+ """
+ )
+ cls = ns["ClassA"]
+ self.assertEqual(cls().func(), 1)
+ X, = cls.__type_params__
+ self.assertEqual(X.__name__, "X")
+
+ def test_name_non_collision_08(self):
+ ns = run_code("""
+ class ClassA[X]:
+ def func(self):
+ return [X for X in [1, 2]]
+ """
+ )
+ cls = ns["ClassA"]
+ self.assertEqual(cls().func(), [1, 2])
+ X, = cls.__type_params__
+ self.assertEqual(X.__name__, "X")
+
+ def test_name_non_collision_9(self):
+ ns = run_code("""
+ class ClassA[X]:
+ def func[X](self):
+ ...
+ """
+ )
+ cls = ns["ClassA"]
+ outer_X, = cls.__type_params__
+ inner_X, = cls.func.__type_params__
+ self.assertEqual(outer_X.__name__, "X")
+ self.assertEqual(inner_X.__name__, "X")
+ self.assertIsNot(outer_X, inner_X)
+
+ def test_name_non_collision_10(self):
+ ns = run_code("""
+ class ClassA[X]:
+ X: int
+ """
+ )
+ cls = ns["ClassA"]
+ X, = cls.__type_params__
+ self.assertEqual(X.__name__, "X")
+ self.assertIs(cls.__annotations__["X"], int)
+
+ def test_name_non_collision_13(self):
+ ns = run_code("""
+ X = 1
+ def outer():
+ def inner[X]():
+ global X
+ X = 2
+ return inner
+ """
+ )
+ self.assertEqual(ns["X"], 1)
+ outer = ns["outer"]
+ outer()()
+ self.assertEqual(ns["X"], 2)
+
+ def test_disallowed_expressions(self):
+ check_syntax_error(self, "type X = (yield)")
+ check_syntax_error(self, "type X = (yield from x)")
+ check_syntax_error(self, "type X = (await 42)")
+ check_syntax_error(self, "async def f(): type X = (yield)")
+ check_syntax_error(self, "type X = (y := 3)")
+ check_syntax_error(self, "class X[T: (yield)]: pass")
+ check_syntax_error(self, "class X[T: (yield from x)]: pass")
+ check_syntax_error(self, "class X[T: (await 42)]: pass")
+ check_syntax_error(self, "class X[T: (y := 3)]: pass")
+ check_syntax_error(self, "class X[T](y := Sequence[T]): pass")
+ check_syntax_error(self, "def f[T](y: (x := Sequence[T])): pass")
+
+
+class TypeParamsNonlocalTest(unittest.TestCase):
+ def test_nonlocal_disallowed_01(self):
+ code = """
+ def outer():
+ X = 1
+ def inner[X]():
+ nonlocal X
+ return X
+ """
+ check_syntax_error(self, code)
+
+ def test_nonlocal_disallowed_02(self):
+ code = """
+ def outer2[T]():
+ def inner1():
+ nonlocal T
+ """
+ check_syntax_error(self, textwrap.dedent(code))
+
+ def test_nonlocal_disallowed_03(self):
+ code = """
+ class Cls[T]:
+ nonlocal T
+ """
+ check_syntax_error(self, textwrap.dedent(code))
+
+ def test_nonlocal_allowed(self):
+ code = """
+ def func[T]():
+ T = "func"
+ def inner():
+ nonlocal T
+ T = "inner"
+ inner()
+ assert T == "inner"
+ """
+ ns = run_code(code)
+ func = ns["func"]
+ T, = func.__type_params__
+ self.assertEqual(T.__name__, "T")
+
+
+class TypeParamsAccessTest(unittest.TestCase):
+ def test_class_access_01(self):
+ ns = run_code("""
+ class ClassA[A, B](dict[A, B]):
+ ...
+ """
+ )
+ cls = ns["ClassA"]
+ A, B = cls.__type_params__
+ self.assertEqual(types.get_original_bases(cls), (dict[A, B], Generic[A, B]))
+
+ def test_class_access_02(self):
+ ns = run_code("""
+ class MyMeta[A, B](type): ...
+ class ClassA[A, B](metaclass=MyMeta[A, B]):
+ ...
+ """
+ )
+ meta = ns["MyMeta"]
+ cls = ns["ClassA"]
+ A1, B1 = meta.__type_params__
+ A2, B2 = cls.__type_params__
+ self.assertIsNot(A1, A2)
+ self.assertIsNot(B1, B2)
+ self.assertIs(type(cls), meta)
+
+ def test_class_access_03(self):
+ code = """
+ def my_decorator(a):
+ ...
+ @my_decorator(A)
+ class ClassA[A, B]():
+ ...
+ """
+
+ with self.assertRaisesRegex(NameError, "name 'A' is not defined"):
+ run_code(code)
+
+ def test_function_access_01(self):
+ ns = run_code("""
+ def func[A, B](a: dict[A, B]):
+ ...
+ """
+ )
+ func = ns["func"]
+ A, B = func.__type_params__
+ self.assertEqual(func.__annotations__["a"], dict[A, B])
+
+ def test_function_access_02(self):
+ code = """
+ def func[A](a = list[A]()):
+ ...
+ """
+
+ with self.assertRaisesRegex(NameError, "name 'A' is not defined"):
+ run_code(code)
+
+ def test_function_access_03(self):
+ code = """
+ def my_decorator(a):
+ ...
+ @my_decorator(A)
+ def func[A]():
+ ...
+ """
+
+ with self.assertRaisesRegex(NameError, "name 'A' is not defined"):
+ run_code(code)
+
+ def test_method_access_01(self):
+ ns = run_code("""
+ class ClassA:
+ x = int
+ def func[T](self, a: x, b: T):
+ ...
+ """
+ )
+ cls = ns["ClassA"]
+ self.assertIs(cls.func.__annotations__["a"], int)
+ T, = cls.func.__type_params__
+ self.assertIs(cls.func.__annotations__["b"], T)
+
+ def test_nested_access_01(self):
+ ns = run_code("""
+ class ClassA[A]:
+ def funcB[B](self):
+ class ClassC[C]:
+ def funcD[D](self):
+ return lambda: (A, B, C, D)
+ return ClassC
+ """
+ )
+ cls = ns["ClassA"]
+ A, = cls.__type_params__
+ B, = cls.funcB.__type_params__
+ classC = cls().funcB()
+ C, = classC.__type_params__
+ D, = classC.funcD.__type_params__
+ self.assertEqual(classC().funcD()(), (A, B, C, D))
+
+ def test_out_of_scope_01(self):
+ code = """
+ class ClassA[T]: ...
+ x = T
+ """
+
+ with self.assertRaisesRegex(NameError, "name 'T' is not defined"):
+ run_code(code)
+
+ def test_out_of_scope_02(self):
+ code = """
+ class ClassA[A]:
+ def funcB[B](self): ...
+
+ x = B
+ """
+
+ with self.assertRaisesRegex(NameError, "name 'B' is not defined"):
+ run_code(code)
+
+ def test_class_scope_interaction_01(self):
+ ns = run_code("""
+ class C:
+ x = 1
+ def method[T](self, arg: x): pass
+ """)
+ cls = ns["C"]
+ self.assertEqual(cls.method.__annotations__["arg"], 1)
+
+ def test_class_scope_interaction_02(self):
+ ns = run_code("""
+ class C:
+ class Base: pass
+ class Child[T](Base): pass
+ """)
+ cls = ns["C"]
+ self.assertEqual(cls.Child.__bases__, (cls.Base, Generic))
+ T, = cls.Child.__type_params__
+ self.assertEqual(types.get_original_bases(cls.Child), (cls.Base, Generic[T]))
+
+ def test_class_deref(self):
+ ns = run_code("""
+ class C[T]:
+ T = "class"
+ type Alias = T
+ """)
+ cls = ns["C"]
+ self.assertEqual(cls.Alias.__value__, "class")
+
+ def test_shadowing_nonlocal(self):
+ ns = run_code("""
+ def outer[T]():
+ T = "outer"
+ def inner():
+ nonlocal T
+ T = "inner"
+ return T
+ return lambda: T, inner
+ """)
+ outer = ns["outer"]
+ T, = outer.__type_params__
+ self.assertEqual(T.__name__, "T")
+ getter, inner = outer()
+ self.assertEqual(getter(), "outer")
+ self.assertEqual(inner(), "inner")
+ self.assertEqual(getter(), "inner")
+
+ def test_reference_previous_typevar(self):
+ def func[S, T: Sequence[S]]():
+ pass
+
+ S, T = func.__type_params__
+ self.assertEqual(T.__bound__, Sequence[S])
+
+ def test_super(self):
+ class Base:
+ def meth(self):
+ return "base"
+
+ class Child(Base):
+ # Having int in the annotation ensures the class gets cells for both
+ # __class__ and __classdict__
+ def meth[T](self, arg: int) -> T:
+ return super().meth() + "child"
+
+ c = Child()
+ self.assertEqual(c.meth(1), "basechild")
+
+ def test_type_alias_containing_lambda(self):
+ type Alias[T] = lambda: T
+ T, = Alias.__type_params__
+ self.assertIs(Alias.__value__(), T)
+
+ def test_class_base_containing_lambda(self):
+ # Test that scopes nested inside hidden functions work correctly
+ outer_var = "outer"
+ class Base[T]: ...
+ class Child[T](Base[lambda: (int, outer_var, T)]): ...
+ base, _ = types.get_original_bases(Child)
+ func, = get_args(base)
+ T, = Child.__type_params__
+ self.assertEqual(func(), (int, "outer", T))
+
+ def test_comprehension_01(self):
+ type Alias[T: ([T for T in (T, [1])[1]], T)] = [T for T in T.__name__]
+ self.assertEqual(Alias.__value__, ["T"])
+ T, = Alias.__type_params__
+ self.assertEqual(T.__constraints__, ([1], T))
+
+ def test_comprehension_02(self):
+ type Alias[T: [lambda: T for T in (T, [1])[1]]] = [lambda: T for T in T.__name__]
+ func, = Alias.__value__
+ self.assertEqual(func(), "T")
+ T, = Alias.__type_params__
+ func, = T.__bound__
+ self.assertEqual(func(), 1)
+
+
+def global_generic_func[T]():
+ pass
+
+class GlobalGenericClass[T]:
+ pass
+
+
+class TypeParamsLazyEvaluationTest(unittest.TestCase):
+ def test_qualname(self):
+ class Foo[T]:
+ pass
+
+ def func[T]():
+ pass
+
+ self.assertEqual(Foo.__qualname__, "TypeParamsLazyEvaluationTest.test_qualname.<locals>.Foo")
+ self.assertEqual(func.__qualname__, "TypeParamsLazyEvaluationTest.test_qualname.<locals>.func")
+ self.assertEqual(global_generic_func.__qualname__, "global_generic_func")
+ self.assertEqual(GlobalGenericClass.__qualname__, "GlobalGenericClass")
+
+ def test_recursive_class(self):
+ class Foo[T: Foo, U: (Foo, Foo)]:
+ pass
+
+ type_params = Foo.__type_params__
+ self.assertEqual(len(type_params), 2)
+ self.assertEqual(type_params[0].__name__, "T")
+ self.assertEqual(type_params[0].__bound__, Foo)
+ self.assertEqual(type_params[0].__constraints__, None)
+
+ self.assertEqual(type_params[1].__name__, "U")
+ self.assertEqual(type_params[1].__bound__, None)
+ self.assertEqual(type_params[1].__constraints__, (Foo, Foo))
+
+ def test_evaluation_error(self):
+ class Foo[T: Undefined, U: (Undefined,)]:
+ pass
+
+ type_params = Foo.__type_params__
+ with self.assertRaises(NameError):
+ type_params[0].__bound__
+ self.assertEqual(type_params[0].__constraints__, None)
+ self.assertEqual(type_params[1].__bound__, None)
+ with self.assertRaises(NameError):
+ type_params[1].__constraints__
+
+ Undefined = "defined"
+ self.assertEqual(type_params[0].__bound__, "defined")
+ self.assertEqual(type_params[0].__constraints__, None)
+
+ self.assertEqual(type_params[1].__bound__, None)
+ self.assertEqual(type_params[1].__constraints__, ("defined",))
+
+
+class TypeParamsClassScopeTest(unittest.TestCase):
+ def test_alias(self):
+ class X:
+ T = int
+ type U = T
+ self.assertIs(X.U.__value__, int)
+
+ ns = run_code("""
+ glb = "global"
+ class X:
+ cls = "class"
+ type U = (glb, cls)
+ """)
+ cls = ns["X"]
+ self.assertEqual(cls.U.__value__, ("global", "class"))
+
+ def test_bound(self):
+ class X:
+ T = int
+ def foo[U: T](self): ...
+ self.assertIs(X.foo.__type_params__[0].__bound__, int)
+
+ ns = run_code("""
+ glb = "global"
+ class X:
+ cls = "class"
+ def foo[T: glb, U: cls](self): ...
+ """)
+ cls = ns["X"]
+ T, U = cls.foo.__type_params__
+ self.assertEqual(T.__bound__, "global")
+ self.assertEqual(U.__bound__, "class")
+
+ def test_modified_later(self):
+ class X:
+ T = int
+ def foo[U: T](self): ...
+ type Alias = T
+ X.T = float
+ self.assertIs(X.foo.__type_params__[0].__bound__, float)
+ self.assertIs(X.Alias.__value__, float)
+
+ def test_binding_uses_global(self):
+ ns = run_code("""
+ x = "global"
+ def outer():
+ x = "nonlocal"
+ class Cls:
+ type Alias = x
+ val = Alias.__value__
+ def meth[T: x](self, arg: x): ...
+ bound = meth.__type_params__[0].__bound__
+ annotation = meth.__annotations__["arg"]
+ x = "class"
+ return Cls
+ """)
+ cls = ns["outer"]()
+ self.assertEqual(cls.val, "global")
+ self.assertEqual(cls.bound, "global")
+ self.assertEqual(cls.annotation, "global")
+
+ def test_no_binding_uses_nonlocal(self):
+ ns = run_code("""
+ x = "global"
+ def outer():
+ x = "nonlocal"
+ class Cls:
+ type Alias = x
+ val = Alias.__value__
+ def meth[T: x](self, arg: x): ...
+ bound = meth.__type_params__[0].__bound__
+ return Cls
+ """)
+ cls = ns["outer"]()
+ self.assertEqual(cls.val, "nonlocal")
+ self.assertEqual(cls.bound, "nonlocal")
+ self.assertEqual(cls.meth.__annotations__["arg"], "nonlocal")
+
+ def test_explicit_global(self):
+ ns = run_code("""
+ x = "global"
+ def outer():
+ x = "nonlocal"
+ class Cls:
+ global x
+ type Alias = x
+ Cls.x = "class"
+ return Cls
+ """)
+ cls = ns["outer"]()
+ self.assertEqual(cls.Alias.__value__, "global")
+
+ def test_explicit_global_with_no_static_bound(self):
+ ns = run_code("""
+ def outer():
+ class Cls:
+ global x
+ type Alias = x
+ Cls.x = "class"
+ return Cls
+ """)
+ ns["x"] = "global"
+ cls = ns["outer"]()
+ self.assertEqual(cls.Alias.__value__, "global")
+
+ def test_explicit_global_with_assignment(self):
+ ns = run_code("""
+ x = "global"
+ def outer():
+ x = "nonlocal"
+ class Cls:
+ global x
+ type Alias = x
+ x = "global from class"
+ Cls.x = "class"
+ return Cls
+ """)
+ cls = ns["outer"]()
+ self.assertEqual(cls.Alias.__value__, "global from class")
+
+ def test_explicit_nonlocal(self):
+ ns = run_code("""
+ x = "global"
+ def outer():
+ x = "nonlocal"
+ class Cls:
+ nonlocal x
+ type Alias = x
+ x = "class"
+ return Cls
+ """)
+ cls = ns["outer"]()
+ self.assertEqual(cls.Alias.__value__, "class")
+
+
+class TypeParamsManglingTest(unittest.TestCase):
+ def test_mangling(self):
+ class Foo[__T]:
+ param = __T
+ def meth[__U](self, arg: __T, arg2: __U):
+ return (__T, __U)
+ type Alias[__V] = (__T, __V)
+
+ T = Foo.__type_params__[0]
+ self.assertEqual(T.__name__, "__T")
+ U = Foo.meth.__type_params__[0]
+ self.assertEqual(U.__name__, "__U")
+ V = Foo.Alias.__type_params__[0]
+ self.assertEqual(V.__name__, "__V")
+
+ anno = Foo.meth.__annotations__
+ self.assertIs(anno["arg"], T)
+ self.assertIs(anno["arg2"], U)
+ self.assertEqual(Foo().meth(1, 2), (T, U))
+
+ self.assertEqual(Foo.Alias.__value__, (T, V))
+
+
+class TypeParamsComplexCallsTest(unittest.TestCase):
+ def test_defaults(self):
+ # Generic functions with both defaults and kwdefaults trigger a specific code path
+ # in the compiler.
+ def func[T](a: T = "a", *, b: T = "b"):
+ return (a, b)
+
+ T, = func.__type_params__
+ self.assertIs(func.__annotations__["a"], T)
+ self.assertIs(func.__annotations__["b"], T)
+ self.assertEqual(func(), ("a", "b"))
+ self.assertEqual(func(1), (1, "b"))
+ self.assertEqual(func(b=2), ("a", 2))
+
+ def test_complex_base(self):
+ class Base:
+ def __init_subclass__(cls, **kwargs) -> None:
+ cls.kwargs = kwargs
+
+ kwargs = {"c": 3}
+ # Base classes with **kwargs trigger a different code path in the compiler.
+ class C[T](Base, a=1, b=2, **kwargs):
+ pass
+
+ T, = C.__type_params__
+ self.assertEqual(T.__name__, "T")
+ self.assertEqual(C.kwargs, {"a": 1, "b": 2, "c": 3})
+
+ bases = (Base,)
+ class C2[T](*bases, **kwargs):
+ pass
+
+ T, = C2.__type_params__
+ self.assertEqual(T.__name__, "T")
+ self.assertEqual(C2.kwargs, {"c": 3})
+
+
+class TypeParamsTraditionalTypeVarsTest(unittest.TestCase):
+ def test_traditional_01(self):
+ code = """
+ from typing import Generic
+ class ClassA[T](Generic[T]): ...
+ """
+
+ with self.assertRaisesRegex(TypeError, r"Cannot inherit from Generic\[...\] multiple times."):
+ run_code(code)
+
+ def test_traditional_02(self):
+ from typing import TypeVar
+ S = TypeVar("S")
+ with self.assertRaises(TypeError):
+ class ClassA[T](dict[T, S]): ...
+
+ def test_traditional_03(self):
+ # This does not generate a runtime error, but it should be
+ # flagged as an error by type checkers.
+ from typing import TypeVar
+ S = TypeVar("S")
+ def func[T](a: T, b: S) -> T | S:
+ return a
+
+
+class TypeParamsTypeVarTest(unittest.TestCase):
+ def test_typevar_01(self):
+ def func1[A: str, B: str | int, C: (int, str)]():
+ return (A, B, C)
+
+ a, b, c = func1()
+
+ self.assertIsInstance(a, TypeVar)
+ self.assertEqual(a.__bound__, str)
+ self.assertTrue(a.__infer_variance__)
+ self.assertFalse(a.__covariant__)
+ self.assertFalse(a.__contravariant__)
+
+ self.assertIsInstance(b, TypeVar)
+ self.assertEqual(b.__bound__, str | int)
+ self.assertTrue(b.__infer_variance__)
+ self.assertFalse(b.__covariant__)
+ self.assertFalse(b.__contravariant__)
+
+ self.assertIsInstance(c, TypeVar)
+ self.assertEqual(c.__bound__, None)
+ self.assertEqual(c.__constraints__, (int, str))
+ self.assertTrue(c.__infer_variance__)
+ self.assertFalse(c.__covariant__)
+ self.assertFalse(c.__contravariant__)
+
+ def test_typevar_generator(self):
+ def get_generator[A]():
+ def generator1[C]():
+ yield C
+
+ def generator2[B]():
+ yield A
+ yield B
+ yield from generator1()
+ return generator2
+
+ gen = get_generator()
+
+ a, b, c = [x for x in gen()]
+
+ self.assertIsInstance(a, TypeVar)
+ self.assertEqual(a.__name__, "A")
+ self.assertIsInstance(b, TypeVar)
+ self.assertEqual(b.__name__, "B")
+ self.assertIsInstance(c, TypeVar)
+ self.assertEqual(c.__name__, "C")
+
+ @requires_working_socket()
+ def test_typevar_coroutine(self):
+ def get_coroutine[A]():
+ async def coroutine[B]():
+ return (A, B)
+ return coroutine
+
+ co = get_coroutine()
+
+ self.addCleanup(asyncio.set_event_loop_policy, None)
+ a, b = asyncio.run(co())
+
+ self.assertIsInstance(a, TypeVar)
+ self.assertEqual(a.__name__, "A")
+ self.assertIsInstance(b, TypeVar)
+ self.assertEqual(b.__name__, "B")
+
+
+class TypeParamsTypeVarTupleTest(unittest.TestCase):
+ def test_typevartuple_01(self):
+ code = """def func1[*A: str](): pass"""
+ check_syntax_error(self, code, "cannot use bound with TypeVarTuple")
+ code = """def func1[*A: (int, str)](): pass"""
+ check_syntax_error(self, code, "cannot use constraints with TypeVarTuple")
+ code = """class X[*A: str]: pass"""
+ check_syntax_error(self, code, "cannot use bound with TypeVarTuple")
+ code = """class X[*A: (int, str)]: pass"""
+ check_syntax_error(self, code, "cannot use constraints with TypeVarTuple")
+ code = """type X[*A: str] = int"""
+ check_syntax_error(self, code, "cannot use bound with TypeVarTuple")
+ code = """type X[*A: (int, str)] = int"""
+ check_syntax_error(self, code, "cannot use constraints with TypeVarTuple")
+
+ def test_typevartuple_02(self):
+ def func1[*A]():
+ return A
+
+ a = func1()
+ self.assertIsInstance(a, TypeVarTuple)
+
+
+class TypeParamsTypeVarParamSpecTest(unittest.TestCase):
+ def test_paramspec_01(self):
+ code = """def func1[**A: str](): pass"""
+ check_syntax_error(self, code, "cannot use bound with ParamSpec")
+ code = """def func1[**A: (int, str)](): pass"""
+ check_syntax_error(self, code, "cannot use constraints with ParamSpec")
+ code = """class X[**A: str]: pass"""
+ check_syntax_error(self, code, "cannot use bound with ParamSpec")
+ code = """class X[**A: (int, str)]: pass"""
+ check_syntax_error(self, code, "cannot use constraints with ParamSpec")
+ code = """type X[**A: str] = int"""
+ check_syntax_error(self, code, "cannot use bound with ParamSpec")
+ code = """type X[**A: (int, str)] = int"""
+ check_syntax_error(self, code, "cannot use constraints with ParamSpec")
+
+ def test_paramspec_02(self):
+ def func1[**A]():
+ return A
+
+ a = func1()
+ self.assertIsInstance(a, ParamSpec)
+ self.assertTrue(a.__infer_variance__)
+ self.assertFalse(a.__covariant__)
+ self.assertFalse(a.__contravariant__)
+
+
+class TypeParamsTypeParamsDunder(unittest.TestCase):
+ def test_typeparams_dunder_class_01(self):
+ class Outer[A, B]:
+ class Inner[C, D]:
+ @staticmethod
+ def get_typeparams():
+ return A, B, C, D
+
+ a, b, c, d = Outer.Inner.get_typeparams()
+ self.assertEqual(Outer.__type_params__, (a, b))
+ self.assertEqual(Outer.Inner.__type_params__, (c, d))
+
+ self.assertEqual(Outer.__parameters__, (a, b))
+ self.assertEqual(Outer.Inner.__parameters__, (c, d))
+
+ def test_typeparams_dunder_class_02(self):
+ class ClassA:
+ pass
+
+ self.assertEqual(ClassA.__type_params__, ())
+
+ def test_typeparams_dunder_class_03(self):
+ code = """
+ class ClassA[A]():
+ pass
+ ClassA.__type_params__ = ()
+ """
+
+ with self.assertRaisesRegex(AttributeError, "attribute '__type_params__' of 'type' objects is not writable"):
+ run_code(code)
+
+ def test_typeparams_dunder_function_01(self):
+ def outer[A, B]():
+ def inner[C, D]():
+ return A, B, C, D
+
+ return inner
+
+ inner = outer()
+ a, b, c, d = inner()
+ self.assertEqual(outer.__type_params__, (a, b))
+ self.assertEqual(inner.__type_params__, (c, d))
+
+ def test_typeparams_dunder_function_02(self):
+ def func1():
+ pass
+
+ self.assertEqual(func1.__type_params__, ())
+
+ def test_typeparams_dunder_function_03(self):
+ code = """
+ def func[A]():
+ pass
+ func.__type_params__ = ()
+ """
+
+ with self.assertRaisesRegex(AttributeError, "attribute '__type_params__' of 'function' objects is not writable"):
+ run_code(code)
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index e1c6a8a..71aff87 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -48,11 +48,8 @@ from test import mod_generics_cache
from test import _typed_dict_helper
-py_typing = import_helper.import_fresh_module('typing', blocked=['_typing'])
-c_typing = import_helper.import_fresh_module('typing', fresh=['_typing'])
-
-
CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes'
+NOT_A_BASE_TYPE = "type 'typing.%s' is not an acceptable base type"
CANNOT_SUBCLASS_INSTANCE = 'Cannot subclass an instance of %s'
@@ -430,7 +427,7 @@ class TypeVarTests(BaseTestCase):
self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str))
def test_cannot_subclass(self):
- with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
+ with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVar'):
class V(TypeVar): pass
T = TypeVar("T")
with self.assertRaisesRegex(TypeError,
@@ -446,6 +443,9 @@ class TypeVarTests(BaseTestCase):
TypeVar('X', bound=Union)
with self.assertRaises(TypeError):
TypeVar('X', str, float, bound=Employee)
+ with self.assertRaisesRegex(TypeError,
+ r"Bound must be a type\. Got \(1, 2\)\."):
+ TypeVar('X', bound=(1, 2))
def test_missing__name__(self):
# See bpo-39942
@@ -1161,7 +1161,7 @@ class TypeVarTupleTests(BaseTestCase):
self.assertEndsWith(repr(K[float, str]), 'A[float, str, typing.Unpack[typing.Tuple[str, ...]]]')
def test_cannot_subclass(self):
- with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
+ with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVarTuple'):
class C(TypeVarTuple): pass
Ts = TypeVarTuple('Ts')
with self.assertRaisesRegex(TypeError,
@@ -6444,34 +6444,27 @@ class TypeTests(BaseTestCase):
class TestModules(TestCase):
func_names = ['_idfunc']
- def test_py_functions(self):
- for fname in self.func_names:
- self.assertEqual(getattr(py_typing, fname).__module__, 'typing')
-
- @skipUnless(c_typing, 'requires _typing')
def test_c_functions(self):
for fname in self.func_names:
- self.assertEqual(getattr(c_typing, fname).__module__, '_typing')
+ self.assertEqual(getattr(typing, fname).__module__, '_typing')
-class NewTypeTests:
+class NewTypeTests(BaseTestCase):
def cleanup(self):
- for f in self.module._cleanups:
+ for f in typing._cleanups:
f()
@classmethod
def setUpClass(cls):
- sys.modules['typing'] = cls.module
global UserId
- UserId = cls.module.NewType('UserId', int)
- cls.UserName = cls.module.NewType(cls.__qualname__ + '.UserName', str)
+ UserId = typing.NewType('UserId', int)
+ cls.UserName = typing.NewType(cls.__qualname__ + '.UserName', str)
@classmethod
def tearDownClass(cls):
global UserId
del UserId
del cls.UserName
- sys.modules['typing'] = typing
def tearDown(self):
self.cleanup()
@@ -6491,11 +6484,11 @@ class NewTypeTests:
def test_or(self):
for cls in (int, self.UserName):
with self.subTest(cls=cls):
- self.assertEqual(UserId | cls, self.module.Union[UserId, cls])
- self.assertEqual(cls | UserId, self.module.Union[cls, UserId])
+ self.assertEqual(UserId | cls, typing.Union[UserId, cls])
+ self.assertEqual(cls | UserId, typing.Union[cls, UserId])
- self.assertEqual(self.module.get_args(UserId | cls), (UserId, cls))
- self.assertEqual(self.module.get_args(cls | UserId), (cls, UserId))
+ self.assertEqual(typing.get_args(UserId | cls), (UserId, cls))
+ self.assertEqual(typing.get_args(cls | UserId), (cls, UserId))
def test_special_attrs(self):
self.assertEqual(UserId.__name__, 'UserId')
@@ -6516,7 +6509,7 @@ class NewTypeTests:
f'{__name__}.{self.__class__.__qualname__}.UserName')
def test_pickle(self):
- UserAge = self.module.NewType('UserAge', float)
+ UserAge = typing.NewType('UserAge', float)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(proto=proto):
pickled = pickle.dumps(UserId, proto)
@@ -6548,15 +6541,6 @@ class NewTypeTests:
...
-class NewTypePythonTests(NewTypeTests, BaseTestCase):
- module = py_typing
-
-
-@skipUnless(c_typing, 'requires _typing')
-class NewTypeCTests(NewTypeTests, BaseTestCase):
- module = c_typing
-
-
class NamedTupleTests(BaseTestCase):
class NestedEmployee(NamedTuple):
name: str
@@ -8170,11 +8154,11 @@ class ParamSpecTests(BaseTestCase):
self.assertEqual(C2[Concatenate[T, P2]].__parameters__, (T, P2))
def test_cannot_subclass(self):
- with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
+ with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpec'):
class C(ParamSpec): pass
- with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
+ with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecArgs'):
class C(ParamSpecArgs): pass
- with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
+ with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecKwargs'):
class C(ParamSpecKwargs): pass
P = ParamSpec('P')
with self.assertRaisesRegex(TypeError,
diff --git a/Lib/typing.py b/Lib/typing.py
index 61aed09..8d132e2 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -23,6 +23,7 @@ from abc import abstractmethod, ABCMeta
import collections
from collections import defaultdict
import collections.abc
+import copyreg
import contextlib
import functools
import operator
@@ -32,12 +33,16 @@ import types
import warnings
from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias
-
-try:
- from _typing import _idfunc
-except ImportError:
- def _idfunc(_, x):
- return x
+from _typing import (
+ _idfunc,
+ TypeVar,
+ ParamSpec,
+ TypeVarTuple,
+ ParamSpecArgs,
+ ParamSpecKwargs,
+ TypeAliasType,
+ Generic,
+)
# Please keep __all__ alphabetized within each category.
__all__ = [
@@ -149,6 +154,7 @@ __all__ = [
'TYPE_CHECKING',
'TypeAlias',
'TypeGuard',
+ 'TypeAliasType',
'Unpack',
]
@@ -695,6 +701,15 @@ def Union(self, parameters):
return _UnionGenericAlias(self, parameters, name="Optional")
return _UnionGenericAlias(self, parameters)
+def _make_union(left, right):
+ """Used from the C implementation of TypeVar.
+
+ TypeVar.__or__ calls this instead of returning types.UnionType
+ because we want to allow unions between TypeVars and strings
+ (forward references.)
+ """
+ return Union[left, right]
+
@_SpecialForm
def Optional(self, parameters):
"""Optional type.
@@ -926,333 +941,162 @@ class _PickleUsingNameMixin:
return self.__name__
-class _BoundVarianceMixin:
- """Mixin giving __init__ bound and variance arguments.
-
- This is used by TypeVar and ParamSpec, which both employ the notions of
- a type 'bound' (restricting type arguments to be a subtype of some
- specified type) and type 'variance' (determining subtype relations between
- generic types).
- """
- def __init__(self, bound, covariant, contravariant):
- """Used to setup TypeVars and ParamSpec's bound, covariant and
- contravariant attributes.
- """
- if covariant and contravariant:
- raise ValueError("Bivariant types are not supported.")
- self.__covariant__ = bool(covariant)
- self.__contravariant__ = bool(contravariant)
- if bound:
- self.__bound__ = _type_check(bound, "Bound must be a type.")
- else:
- self.__bound__ = None
-
- def __or__(self, right):
- return Union[self, right]
-
- def __ror__(self, left):
- return Union[left, self]
-
- def __repr__(self):
- if self.__covariant__:
- prefix = '+'
- elif self.__contravariant__:
- prefix = '-'
- else:
- prefix = '~'
- return prefix + self.__name__
-
- def __mro_entries__(self, bases):
- raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
-
-
-class TypeVar(_Final, _Immutable, _BoundVarianceMixin, _PickleUsingNameMixin,
- _root=True):
- """Type variable.
-
- Usage::
-
- T = TypeVar('T') # Can be anything
- A = TypeVar('A', str, bytes) # Must be str or bytes
-
- Type variables exist primarily for the benefit of static type
- checkers. They serve as the parameters for generic types as well
- as for generic function definitions. See class Generic for more
- information on generic types. Generic functions work as follows:
-
- def repeat(x: T, n: int) -> List[T]:
- '''Return a list containing n references to x.'''
- return [x]*n
-
- def longest(x: A, y: A) -> A:
- '''Return the longest of two strings.'''
- return x if len(x) >= len(y) else y
-
- The latter example's signature is essentially the overloading
- of (str, str) -> str and (bytes, bytes) -> bytes. Also note
- that if the arguments are instances of some subclass of str,
- the return type is still plain str.
-
- At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError.
-
- Type variables defined with covariant=True or contravariant=True
- can be used to declare covariant or contravariant generic types.
- See PEP 484 for more details. By default generic types are invariant
- in all type variables.
-
- Type variables can be introspected. e.g.:
-
- T.__name__ == 'T'
- T.__constraints__ == ()
- T.__covariant__ == False
- T.__contravariant__ = False
- A.__constraints__ == (str, bytes)
-
- Note that only type variables defined in global scope can be pickled.
- """
-
- def __init__(self, name, *constraints, bound=None,
- covariant=False, contravariant=False):
- self.__name__ = name
- super().__init__(bound, covariant, contravariant)
- if constraints and bound is not None:
- raise TypeError("Constraints cannot be combined with bound=...")
- if constraints and len(constraints) == 1:
- raise TypeError("A single constraint is not allowed")
- msg = "TypeVar(name, constraint, ...): constraints must be types."
- self.__constraints__ = tuple(_type_check(t, msg) for t in constraints)
- def_mod = _caller()
- if def_mod != 'typing':
- self.__module__ = def_mod
+def _typevar_subst(self, arg):
+ msg = "Parameters to generic types must be types."
+ arg = _type_check(arg, msg, is_argument=True)
+ if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or
+ (isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))):
+ raise TypeError(f"{arg} is not valid as type argument")
+ return arg
- def __typing_subst__(self, arg):
- msg = "Parameters to generic types must be types."
- arg = _type_check(arg, msg, is_argument=True)
- if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or
- (isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))):
- raise TypeError(f"{arg} is not valid as type argument")
- return arg
+def _typevartuple_prepare_subst(self, alias, args):
+ params = alias.__parameters__
+ typevartuple_index = params.index(self)
+ for param in params[typevartuple_index + 1:]:
+ if isinstance(param, TypeVarTuple):
+ raise TypeError(f"More than one TypeVarTuple parameter in {alias}")
+
+ alen = len(args)
+ plen = len(params)
+ left = typevartuple_index
+ right = plen - typevartuple_index - 1
+ var_tuple_index = None
+ fillarg = None
+ for k, arg in enumerate(args):
+ if not isinstance(arg, type):
+ subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
+ if subargs and len(subargs) == 2 and subargs[-1] is ...:
+ if var_tuple_index is not None:
+ raise TypeError("More than one unpacked arbitrary-length tuple argument")
+ var_tuple_index = k
+ fillarg = subargs[0]
+ if var_tuple_index is not None:
+ left = min(left, var_tuple_index)
+ right = min(right, alen - var_tuple_index - 1)
+ elif left + right > alen:
+ raise TypeError(f"Too few arguments for {alias};"
+ f" actual {alen}, expected at least {plen-1}")
-class TypeVarTuple(_Final, _Immutable, _PickleUsingNameMixin, _root=True):
- """Type variable tuple.
+ return (
+ *args[:left],
+ *([fillarg]*(typevartuple_index - left)),
+ tuple(args[left: alen - right]),
+ *([fillarg]*(plen - right - left - typevartuple_index - 1)),
+ *args[alen - right:],
+ )
- Usage:
- Ts = TypeVarTuple('Ts') # Can be given any name
+def _paramspec_subst(self, arg):
+ if isinstance(arg, (list, tuple)):
+ arg = tuple(_type_check(a, "Expected a type.") for a in arg)
+ elif not _is_param_expr(arg):
+ raise TypeError(f"Expected a list of types, an ellipsis, "
+ f"ParamSpec, or Concatenate. Got {arg}")
+ return arg
- Just as a TypeVar (type variable) is a placeholder for a single type,
- a TypeVarTuple is a placeholder for an *arbitrary* number of types. For
- example, if we define a generic class using a TypeVarTuple:
- class C(Generic[*Ts]): ...
+def _paramspec_prepare_subst(self, alias, args):
+ params = alias.__parameters__
+ i = params.index(self)
+ if i >= len(args):
+ raise TypeError(f"Too few arguments for {alias}")
+ # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612.
+ if len(params) == 1 and not _is_param_expr(args[0]):
+ assert i == 0
+ args = (args,)
+ # Convert lists to tuples to help other libraries cache the results.
+ elif isinstance(args[i], list):
+ args = (*args[:i], tuple(args[i]), *args[i+1:])
+ return args
- Then we can parameterize that class with an arbitrary number of type
- arguments:
- C[int] # Fine
- C[int, str] # Also fine
- C[()] # Even this is fine
+@_tp_cache
+def _generic_class_getitem(cls, params):
+ """Parameterizes a generic class.
- For more details, see PEP 646.
+ At least, parameterizing a generic class is the *main* thing this method
+ does. For example, for some generic class `Foo`, this is called when we
+ do `Foo[int]` - there, with `cls=Foo` and `params=int`.
- Note that only TypeVarTuples defined in global scope can be pickled.
+ However, note that this method is also called when defining generic
+ classes in the first place with `class Foo(Generic[T]): ...`.
"""
+ if not isinstance(params, tuple):
+ params = (params,)
- def __init__(self, name):
- self.__name__ = name
-
- # Used for pickling.
- def_mod = _caller()
- if def_mod != 'typing':
- self.__module__ = def_mod
-
- def __iter__(self):
- yield Unpack[self]
-
- def __repr__(self):
- return self.__name__
+ params = tuple(_type_convert(p) for p in params)
+ is_generic_or_protocol = cls in (Generic, Protocol)
- def __typing_subst__(self, arg):
- raise TypeError("Substitution of bare TypeVarTuple is not supported")
+ if is_generic_or_protocol:
+ # Generic and Protocol can only be subscripted with unique type variables.
+ if not params:
+ raise TypeError(
+ f"Parameter list to {cls.__qualname__}[...] cannot be empty"
+ )
+ if not all(_is_typevar_like(p) for p in params):
+ raise TypeError(
+ f"Parameters to {cls.__name__}[...] must all be type variables "
+ f"or parameter specification variables.")
+ if len(set(params)) != len(params):
+ raise TypeError(
+ f"Parameters to {cls.__name__}[...] must all be unique")
+ else:
+ # Subscripting a regular Generic subclass.
+ for param in cls.__parameters__:
+ prepare = getattr(param, '__typing_prepare_subst__', None)
+ if prepare is not None:
+ params = prepare(cls, params)
+ _check_generic(cls, params, len(cls.__parameters__))
- def __typing_prepare_subst__(self, alias, args):
- params = alias.__parameters__
- typevartuple_index = params.index(self)
- for param in params[typevartuple_index + 1:]:
+ new_args = []
+ for param, new_arg in zip(cls.__parameters__, params):
if isinstance(param, TypeVarTuple):
- raise TypeError(f"More than one TypeVarTuple parameter in {alias}")
-
- alen = len(args)
- plen = len(params)
- left = typevartuple_index
- right = plen - typevartuple_index - 1
- var_tuple_index = None
- fillarg = None
- for k, arg in enumerate(args):
- if not isinstance(arg, type):
- subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
- if subargs and len(subargs) == 2 and subargs[-1] is ...:
- if var_tuple_index is not None:
- raise TypeError("More than one unpacked arbitrary-length tuple argument")
- var_tuple_index = k
- fillarg = subargs[0]
- if var_tuple_index is not None:
- left = min(left, var_tuple_index)
- right = min(right, alen - var_tuple_index - 1)
- elif left + right > alen:
- raise TypeError(f"Too few arguments for {alias};"
- f" actual {alen}, expected at least {plen-1}")
-
- return (
- *args[:left],
- *([fillarg]*(typevartuple_index - left)),
- tuple(args[left: alen - right]),
- *([fillarg]*(plen - right - left - typevartuple_index - 1)),
- *args[alen - right:],
- )
-
- def __mro_entries__(self, bases):
- raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
-
-
-class ParamSpecArgs(_Final, _Immutable, _root=True):
- """The args for a ParamSpec object.
-
- Given a ParamSpec object P, P.args is an instance of ParamSpecArgs.
-
- ParamSpecArgs objects have a reference back to their ParamSpec:
-
- P.args.__origin__ is P
-
- This type is meant for runtime introspection and has no special meaning to
- static type checkers.
- """
- def __init__(self, origin):
- self.__origin__ = origin
-
- def __repr__(self):
- return f"{self.__origin__.__name__}.args"
-
- def __eq__(self, other):
- if not isinstance(other, ParamSpecArgs):
- return NotImplemented
- return self.__origin__ == other.__origin__
-
- def __mro_entries__(self, bases):
- raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
-
-
-class ParamSpecKwargs(_Final, _Immutable, _root=True):
- """The kwargs for a ParamSpec object.
-
- Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs.
-
- ParamSpecKwargs objects have a reference back to their ParamSpec:
-
- P.kwargs.__origin__ is P
-
- This type is meant for runtime introspection and has no special meaning to
- static type checkers.
- """
- def __init__(self, origin):
- self.__origin__ = origin
-
- def __repr__(self):
- return f"{self.__origin__.__name__}.kwargs"
-
- def __eq__(self, other):
- if not isinstance(other, ParamSpecKwargs):
- return NotImplemented
- return self.__origin__ == other.__origin__
-
- def __mro_entries__(self, bases):
- raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
-
-
-class ParamSpec(_Final, _Immutable, _BoundVarianceMixin, _PickleUsingNameMixin,
- _root=True):
- """Parameter specification variable.
-
- Usage::
-
- P = ParamSpec('P')
-
- Parameter specification variables exist primarily for the benefit of static
- type checkers. They are used to forward the parameter types of one
- callable to another callable, a pattern commonly found in higher order
- functions and decorators. They are only valid when used in ``Concatenate``,
- or as the first argument to ``Callable``, or as parameters for user-defined
- Generics. See class Generic for more information on generic types. An
- example for annotating a decorator::
-
- T = TypeVar('T')
- P = ParamSpec('P')
-
- def add_logging(f: Callable[P, T]) -> Callable[P, T]:
- '''A type-safe decorator to add logging to a function.'''
- def inner(*args: P.args, **kwargs: P.kwargs) -> T:
- logging.info(f'{f.__name__} was called')
- return f(*args, **kwargs)
- return inner
-
- @add_logging
- def add_two(x: float, y: float) -> float:
- '''Add two numbers together.'''
- return x + y
-
- Parameter specification variables defined with covariant=True or
- contravariant=True can be used to declare covariant or contravariant
- generic types. These keyword arguments are valid, but their actual semantics
- are yet to be decided. See PEP 612 for details.
-
- Parameter specification variables can be introspected. e.g.:
-
- P.__name__ == 'P'
- P.__bound__ == None
- P.__covariant__ == False
- P.__contravariant__ == False
-
- Note that only parameter specification variables defined in global scope can
- be pickled.
- """
+ new_args.extend(new_arg)
+ else:
+ new_args.append(new_arg)
+ params = tuple(new_args)
- @property
- def args(self):
- return ParamSpecArgs(self)
+ return _GenericAlias(cls, params)
- @property
- def kwargs(self):
- return ParamSpecKwargs(self)
-
- def __init__(self, name, *, bound=None, covariant=False, contravariant=False):
- self.__name__ = name
- super().__init__(bound, covariant, contravariant)
- def_mod = _caller()
- if def_mod != 'typing':
- self.__module__ = def_mod
- def __typing_subst__(self, arg):
- if isinstance(arg, (list, tuple)):
- arg = tuple(_type_check(a, "Expected a type.") for a in arg)
- elif not _is_param_expr(arg):
- raise TypeError(f"Expected a list of types, an ellipsis, "
- f"ParamSpec, or Concatenate. Got {arg}")
- return arg
+def _generic_init_subclass(cls, *args, **kwargs):
+ super(Generic, cls).__init_subclass__(*args, **kwargs)
+ tvars = []
+ if '__orig_bases__' in cls.__dict__:
+ error = Generic in cls.__orig_bases__
+ else:
+ error = (Generic in cls.__bases__ and
+ cls.__name__ != 'Protocol' and
+ type(cls) != _TypedDictMeta)
+ if error:
+ raise TypeError("Cannot inherit from plain Generic")
+ if '__orig_bases__' in cls.__dict__:
+ tvars = _collect_parameters(cls.__orig_bases__)
+ # Look for Generic[T1, ..., Tn].
+ # If found, tvars must be a subset of it.
+ # If not found, tvars is it.
+ # Also check for and reject plain Generic,
+ # and reject multiple Generic[...].
+ gvars = None
+ for base in cls.__orig_bases__:
+ if (isinstance(base, _GenericAlias) and
+ base.__origin__ is Generic):
+ if gvars is not None:
+ raise TypeError(
+ "Cannot inherit from Generic[...] multiple times.")
+ gvars = base.__parameters__
+ if gvars is not None:
+ tvarset = set(tvars)
+ gvarset = set(gvars)
+ if not tvarset <= gvarset:
+ s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
+ s_args = ', '.join(str(g) for g in gvars)
+ raise TypeError(f"Some type variables ({s_vars}) are"
+ f" not listed in Generic[{s_args}]")
+ tvars = gvars
+ cls.__parameters__ = tuple(tvars)
- def __typing_prepare_subst__(self, alias, args):
- params = alias.__parameters__
- i = params.index(self)
- if i >= len(args):
- raise TypeError(f"Too few arguments for {alias}")
- # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612.
- if len(params) == 1 and not _is_param_expr(args[0]):
- assert i == 0
- args = (args,)
- # Convert lists to tuples to help other libraries cache the results.
- elif isinstance(args[i], list):
- args = (*args[:i], tuple(args[i]), *args[i+1:])
- return args
def _is_dunder(attr):
return attr.startswith('__') and attr.endswith('__')
@@ -1812,113 +1656,6 @@ class _UnpackGenericAlias(_GenericAlias, _root=True):
return isinstance(self.__args__[0], TypeVarTuple)
-class Generic:
- """Abstract base class for generic types.
-
- A generic type is typically declared by inheriting from
- this class parameterized with one or more type variables.
- For example, a generic mapping type might be defined as::
-
- class Mapping(Generic[KT, VT]):
- def __getitem__(self, key: KT) -> VT:
- ...
- # Etc.
-
- This class can then be used as follows::
-
- def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
- try:
- return mapping[key]
- except KeyError:
- return default
- """
- __slots__ = ()
- _is_protocol = False
-
- @_tp_cache
- def __class_getitem__(cls, params):
- """Parameterizes a generic class.
-
- At least, parameterizing a generic class is the *main* thing this method
- does. For example, for some generic class `Foo`, this is called when we
- do `Foo[int]` - there, with `cls=Foo` and `params=int`.
-
- However, note that this method is also called when defining generic
- classes in the first place with `class Foo(Generic[T]): ...`.
- """
- if not isinstance(params, tuple):
- params = (params,)
-
- params = tuple(_type_convert(p) for p in params)
- if cls in (Generic, Protocol):
- # Generic and Protocol can only be subscripted with unique type variables.
- if not params:
- raise TypeError(
- f"Parameter list to {cls.__qualname__}[...] cannot be empty"
- )
- if not all(_is_typevar_like(p) for p in params):
- raise TypeError(
- f"Parameters to {cls.__name__}[...] must all be type variables "
- f"or parameter specification variables.")
- if len(set(params)) != len(params):
- raise TypeError(
- f"Parameters to {cls.__name__}[...] must all be unique")
- else:
- # Subscripting a regular Generic subclass.
- for param in cls.__parameters__:
- prepare = getattr(param, '__typing_prepare_subst__', None)
- if prepare is not None:
- params = prepare(cls, params)
- _check_generic(cls, params, len(cls.__parameters__))
-
- new_args = []
- for param, new_arg in zip(cls.__parameters__, params):
- if isinstance(param, TypeVarTuple):
- new_args.extend(new_arg)
- else:
- new_args.append(new_arg)
- params = tuple(new_args)
-
- return _GenericAlias(cls, params)
-
- def __init_subclass__(cls, *args, **kwargs):
- super().__init_subclass__(*args, **kwargs)
- tvars = []
- if '__orig_bases__' in cls.__dict__:
- error = Generic in cls.__orig_bases__
- else:
- error = (Generic in cls.__bases__ and
- cls.__name__ != 'Protocol' and
- type(cls) != _TypedDictMeta)
- if error:
- raise TypeError("Cannot inherit from plain Generic")
- if '__orig_bases__' in cls.__dict__:
- tvars = _collect_parameters(cls.__orig_bases__)
- # Look for Generic[T1, ..., Tn].
- # If found, tvars must be a subset of it.
- # If not found, tvars is it.
- # Also check for and reject plain Generic,
- # and reject multiple Generic[...].
- gvars = None
- for base in cls.__orig_bases__:
- if (isinstance(base, _GenericAlias) and
- base.__origin__ is Generic):
- if gvars is not None:
- raise TypeError(
- "Cannot inherit from Generic[...] multiple times.")
- gvars = base.__parameters__
- if gvars is not None:
- tvarset = set(tvars)
- gvarset = set(gvars)
- if not tvarset <= gvarset:
- s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
- s_args = ', '.join(str(g) for g in gvars)
- raise TypeError(f"Some type variables ({s_vars}) are"
- f" not listed in Generic[{s_args}]")
- tvars = gvars
- cls.__parameters__ = tuple(tvars)
-
-
class _TypingEllipsis:
"""Internal placeholder for ... (ellipsis)."""
@@ -2024,6 +1761,18 @@ def _lazy_load_getattr_static():
_cleanups.append(_lazy_load_getattr_static.cache_clear)
+def _pickle_psargs(psargs):
+ return ParamSpecArgs, (psargs.__origin__,)
+
+copyreg.pickle(ParamSpecArgs, _pickle_psargs)
+
+def _pickle_pskwargs(pskwargs):
+ return ParamSpecKwargs, (pskwargs.__origin__,)
+
+copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs)
+
+del _pickle_psargs, _pickle_pskwargs
+
class _ProtocolMeta(ABCMeta):
# This metaclass is really unfortunate and exists only because of
@@ -2943,7 +2692,7 @@ class NamedTupleMeta(type):
module=ns['__module__'])
nm_tpl.__bases__ = bases
if Generic in bases:
- class_getitem = Generic.__class_getitem__.__func__
+ class_getitem = _generic_class_getitem
nm_tpl.__class_getitem__ = classmethod(class_getitem)
# update from user namespace without overriding special namedtuple attributes
for key in ns: