diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index ab2a668f590afd8..878f286241ad7bb 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -1914,15 +1914,17 @@ aliases. .. versionchanged:: 3.13 Added the *default_value* parameter. -.. class:: ParamSpec(name, default_value) +.. class:: ParamSpec(name, bound, default_value) A :class:`typing.ParamSpec`. ``name`` is the name of the parameter specification. - ``default_value`` is the default value; if the :class:`!ParamSpec` has no default, - this attribute will be set to ``None``. + ``bound`` is the bound, if any; a parameter specification is bounded by a + parameter list, so the bound is usually a :class:`List`. ``default_value`` + is the default value; if the :class:`!ParamSpec` has no bound or no default, + the corresponding attribute will be set to ``None``. .. doctest:: - >>> print(ast.dump(ast.parse("type Alias[**P = [int, str]] = Callable[P, int]"), indent=4)) + >>> print(ast.dump(ast.parse("type Alias[**P: [int] = [int, str]] = Callable[P, int]"), indent=4)) Module( body=[ TypeAlias( @@ -1930,6 +1932,9 @@ aliases. type_params=[ ParamSpec( name='P', + bound=List( + elts=[ + Name(id='int')]), default_value=List( elts=[ Name(id='int'), @@ -1946,21 +1951,29 @@ aliases. .. versionchanged:: 3.13 Added the *default_value* parameter. -.. class:: TypeVarTuple(name, default_value) + .. versionchanged:: 3.16 + Added the *bound* parameter. + +.. class:: TypeVarTuple(name, bound, default_value) A :class:`typing.TypeVarTuple`. ``name`` is the name of the type variable tuple. - ``default_value`` is the default value; if the :class:`!TypeVarTuple` has no - default, this attribute will be set to ``None``. + ``bound`` is the bound, if any, which applies to each type substituted for the + type variable tuple. ``default_value`` is the default value; if the + :class:`!TypeVarTuple` has no bound or no default, the corresponding attribute + will be set to ``None``. .. doctest:: - >>> print(ast.dump(ast.parse("type Alias[*Ts = ()] = tuple[*Ts]"), indent=4)) + >>> print(ast.dump(ast.parse("type Alias[*Ts: int = ()] = tuple[*Ts]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ - TypeVarTuple(name='Ts', default_value=Tuple())], + TypeVarTuple( + name='Ts', + bound=Name(id='int'), + default_value=Tuple())], value=Subscript( value=Name(id='tuple'), slice=Tuple( @@ -1973,6 +1986,9 @@ aliases. .. versionchanged:: 3.13 Added the *default_value* parameter. + .. versionchanged:: 3.16 + Added the *bound* parameter. + Function and class definitions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c909b8bad6d726c..d5dc459a950a284 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -2109,6 +2109,30 @@ without the dedicated syntax, as documented below. .. versionadded:: 3.15 + .. attribute:: __bound__ + + The upper bound of each of the types the type variable tuple stands for, + if any. + + .. versionchanged:: 3.16 + + For type variable tuples created through + :ref:`type parameter syntax `, the bound is evaluated only + when the attribute is accessed, not when the type variable tuple is + created (see :ref:`lazy-evaluation`). + + .. method:: evaluate_bound + + An :term:`evaluate function` corresponding to the + :attr:`~TypeVarTuple.__bound__` attribute. + When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE` + format, which is equivalent to accessing the :attr:`~TypeVarTuple.__bound__` attribute + directly, but the method object can be passed to + :func:`annotationlib.call_evaluate_function` to evaluate the value in a + different format. + + .. versionadded:: 3.16 + .. attribute:: __default__ The default value of the type variable tuple, or :data:`typing.NoDefault` if it @@ -2135,11 +2159,6 @@ without the dedicated syntax, as documented below. .. versionadded:: 3.13 - Type variable tuples created with ``covariant=True`` or - ``contravariant=True`` can be used to declare covariant or contravariant - generic types. The ``bound`` argument is also accepted, similar to - :class:`TypeVar`, but its actual semantics are yet to be decided. - .. versionadded:: 3.11 .. versionchanged:: 3.12 @@ -2156,6 +2175,12 @@ without the dedicated syntax, as documented below. Added support for the ``bound``, ``covariant``, ``contravariant``, and ``infer_variance`` parameters. + .. versionchanged:: 3.16 + + Type variable tuple bounds can now be declared using the + :ref:`type parameter ` syntax, and are + :ref:`lazily evaluated `. + .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault) Parameter specification variable. A specialized version of @@ -2239,6 +2264,34 @@ without the dedicated syntax, as documented below. .. versionadded:: 3.12 + .. attribute:: __bound__ + + The upper bound of the parameter specification, if any. Because a + parameter specification stands for the parameters of a callable, its + bound is a parameter list, such as ``[int, str]``. + + .. versionchanged:: 3.16 + + For parameter specifications created through + :ref:`type parameter syntax `, the bound is evaluated only + when the attribute is accessed, not when the parameter specification is + created (see :ref:`lazy-evaluation`). + + Previously, :attr:`!__bound__` was :class:`types.NoneType` rather than + ``None`` when no bound was given. + + .. method:: evaluate_bound + + An :term:`evaluate function` corresponding to the + :attr:`~ParamSpec.__bound__` attribute. + When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE` + format, which is equivalent to accessing the :attr:`~ParamSpec.__bound__` attribute + directly, but the method object can be passed to + :func:`annotationlib.call_evaluate_function` to evaluate the value in a + different format. + + .. versionadded:: 3.16 + .. attribute:: __default__ The default value of the parameter specification, or :data:`typing.NoDefault` if it @@ -2267,8 +2320,7 @@ without the dedicated syntax, as documented below. Parameter specification variables created with ``covariant=True`` or ``contravariant=True`` can be used to declare covariant or contravariant - generic types. The ``bound`` argument is also accepted, similar to - :class:`TypeVar`. However the actual semantics of these keywords are yet to + generic types. However the actual semantics of these keywords are yet to be decided. .. versionadded:: 3.10 @@ -2282,6 +2334,12 @@ without the dedicated syntax, as documented below. Support for default values was added. + .. versionchanged:: 3.16 + + Parameter specification bounds can now be declared using the + :ref:`type parameter ` syntax, and are + :ref:`lazily evaluated `. + .. note:: Only parameter specification variables defined in global scope can be pickled. diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index e74f3262ed540cd..23e431cb190f39c 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -1768,8 +1768,8 @@ Type parameter lists type_params: "[" `type_param` ("," `type_param`)* "]" type_param: `typevar` | `typevartuple` | `paramspec` typevar: `identifier` (":" `expression`)? ("=" `expression`)? - typevartuple: "*" `identifier` ("=" `expression`)? - paramspec: "**" `identifier` ("=" `expression`)? + typevartuple: "*" `identifier` (":" `starred_expression`)? ("=" `starred_expression`)? + paramspec: "**" `identifier` (":" `expression`)? ("=" `expression`)? :ref:`Functions ` (including :ref:`coroutines `), :ref:`classes ` and :ref:`type aliases ` may @@ -1832,8 +1832,19 @@ but only when the value is explicitly accessed through the attributes ``__bound_ and ``__constraints__``. To accomplish this, the bounds or constraints are evaluated in a separate :ref:`annotation scope `. -:data:`typing.TypeVarTuple`\ s and :data:`typing.ParamSpec`\ s cannot have bounds -or constraints. +:data:`typing.TypeVarTuple`\ s and :data:`typing.ParamSpec`\ s can also declare a +bound with a colon (``:``) followed by an expression, but they cannot declare +constraints. For a :data:`!typing.TypeVarTuple`, the bound applies to each of the +types it stands for (e.g. in ``*Ts: int``, every type substituted for ``Ts`` must +be a subtype of :class:`int`). For a :data:`!typing.ParamSpec`, the bound is a +parameter list that the substituted parameters must be compatible with (e.g. +``**P: [int]``). As with :data:`!typing.TypeVar`, these bounds are lazily +evaluated in a separate :ref:`annotation scope ` and are not +enforced at runtime. + +.. versionchanged:: 3.16 + Added support for bounds on :data:`!typing.TypeVarTuple`\ s and + :data:`!typing.ParamSpec`\ s. All three flavors of type parameters can also have a *default value*, which is used when the type parameter is not explicitly provided. This is added by appending @@ -1853,7 +1864,9 @@ The following example indicates the full set of allowed type parameter declarati TypeVarWithBound: int, TypeVarWithConstraints: (str, bytes), *SimpleTypeVarTuple = (int, float), + *TypeVarTupleWithBound: int, **SimpleParamSpec = (str, bytearray), + **ParamSpecWithBound: [int], ]( a: SimpleTypeVar, b: TypeVarWithDefault, diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index b017535b96979d9..24db9d262c3c4ad 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -75,6 +75,20 @@ New features Other language changes ====================== +* :ref:`Type parameter lists ` now accept bounds on type variable + tuples and parameter specifications, using the same syntax already available + for :class:`~typing.TypeVar`:: + + def call[*Ts: int, **P: [str]](*args: *Ts, f: Callable[P, int]) -> None: ... + + A :class:`~typing.TypeVarTuple` bound applies to each type the type variable + tuple stands for, while a :class:`~typing.ParamSpec` bound is a parameter + list. Like other type parameter bounds, they are + :ref:`lazily evaluated ` and are available through the + ``__bound__`` attribute and the ``evaluate_bound`` + :term:`evaluate function`. + (Contributed by KotlinIsland in :gh:`148945`.) + * :meth:`memoryview.cast` now allows casting a multidimensional F-contiguous view to a one-dimensional view. (Contributed by Jaemin Park in :gh:`91484`.) diff --git a/Grammar/python.gram b/Grammar/python.gram index 2713ba9466a0b1d..678cfee7bd6ea13 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -694,11 +694,14 @@ type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ [' type_param[type_param_ty] (memo): | a=NAME b=[type_param_bound] c=[type_param_default] { _PyAST_TypeVar(a->v.Name.id, b, c, EXTRA) } - | invalid_type_param - | '*' a=NAME b=[type_param_starred_default] { _PyAST_TypeVarTuple(a->v.Name.id, b, EXTRA) } - | '**' a=NAME b=[type_param_default] { _PyAST_ParamSpec(a->v.Name.id, b, EXTRA) } + | '*' a=NAME b=[type_param_starred_bound] c=[type_param_starred_default] { _PyAST_TypeVarTuple(a->v.Name.id, b, c, EXTRA) } + | '**' a=NAME b=[type_param_paramspec_bound] c=[type_param_default] { _PyAST_ParamSpec(a->v.Name.id, b, c, EXTRA) } type_param_bound[expr_ty]: ':' e=expression { e } +type_param_starred_bound[expr_ty]: ':' e=star_expression { + CHECK_VERSION(expr_ty, 16, "Type variable tuple bounds are", e) } +type_param_paramspec_bound[expr_ty]: ':' e=expression { + CHECK_VERSION(expr_ty, 16, "Parameter specification bounds are", e) } type_param_default[expr_ty]: '=' e=expression { CHECK_VERSION(expr_ty, 13, "Type parameter defaults are", e) } type_param_starred_default[expr_ty]: '=' e=star_expression { @@ -1249,18 +1252,6 @@ invalid_legacy_expression: _PyPegen_check_legacy_stmt(p, a) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "Missing parentheses in call to '%U'. Did you mean %U(...)?", a->v.Name.id, a->v.Name.id) : NULL} -invalid_type_param: - | '*' a=NAME colon=':' e=expression { - RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind - ? "cannot use constraints with TypeVarTuple" - : "cannot use bound with TypeVarTuple") - } - | '**' a=NAME colon=':' e=expression { - RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind - ? "cannot use constraints with ParamSpec" - : "cannot use bound with ParamSpec") - } - invalid_expression: | STRING a=(!STRING expression_without_invalid)+ STRING { RAISE_SYNTAX_ERROR_KNOWN_RANGE( PyPegen_first_item(a, expr_ty), PyPegen_last_item(a, expr_ty), diff --git a/Include/internal/pycore_ast.h b/Include/internal/pycore_ast.h index b47398669bbe513..337fdbd153b891a 100644 --- a/Include/internal/pycore_ast.h +++ b/Include/internal/pycore_ast.h @@ -676,11 +676,13 @@ struct _type_param { struct { identifier name; + expr_ty bound; expr_ty default_value; } ParamSpec; struct { identifier name; + expr_ty bound; expr_ty default_value; } TypeVarTuple; @@ -919,12 +921,13 @@ type_ignore_ty _PyAST_TypeIgnore(int lineno, string tag, PyArena *arena); type_param_ty _PyAST_TypeVar(identifier name, expr_ty bound, expr_ty default_value, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); -type_param_ty _PyAST_ParamSpec(identifier name, expr_ty default_value, int - lineno, int col_offset, int end_lineno, int - end_col_offset, PyArena *arena); -type_param_ty _PyAST_TypeVarTuple(identifier name, expr_ty default_value, int - lineno, int col_offset, int end_lineno, int - end_col_offset, PyArena *arena); +type_param_ty _PyAST_ParamSpec(identifier name, expr_ty bound, expr_ty + default_value, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena); +type_param_ty _PyAST_TypeVarTuple(identifier name, expr_ty bound, expr_ty + default_value, int lineno, int col_offset, + int end_lineno, int end_col_offset, PyArena + *arena); PyObject* PyAST_mod2obj(mod_ty t); diff --git a/Include/internal/pycore_intrinsics.h b/Include/internal/pycore_intrinsics.h index 447cea91716eca9..5b86bfcb8464aa0 100644 --- a/Include/internal/pycore_intrinsics.h +++ b/Include/internal/pycore_intrinsics.h @@ -31,8 +31,10 @@ #define INTRINSIC_SET_FUNCTION_TYPE_PARAMS 4 #define INTRINSIC_SET_TYPEPARAM_DEFAULT 5 #define INTRINSIC_ADD_CONDITIONAL_ANNOTATION 6 +#define INTRINSIC_TYPEVARTUPLE_WITH_BOUND 7 +#define INTRINSIC_PARAMSPEC_WITH_BOUND 8 -#define MAX_INTRINSIC_2 6 +#define MAX_INTRINSIC_2 8 typedef PyObject *(*intrinsic_func1)(PyThreadState* tstate, PyObject *value); typedef PyObject *(*intrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index b6945f2bc5f6e0d..68742ab2f2ff82d 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -303,6 +303,7 @@ Known values: Python 3.16a1 3703 (Replace DELETE_GLOBAL with PUSH_NULL; STORE_GLOBAL) Python 3.16a1 3704 (Replace DELETE_ATTR with PUSH_NULL; STORE_ATTR) Python 3.16a1 3705 (Add INTRINSIC_ADD_CONDITIONAL_ANNOTATION) + Python 3.16a1 3706 (Add INTRINSIC_TYPEVARTUPLE_WITH_BOUND and INTRINSIC_PARAMSPEC_WITH_BOUND) Python 3.17 will start with 3750 @@ -312,7 +313,7 @@ Known values: */ -#define PYC_MAGIC_NUMBER 3705 +#define PYC_MAGIC_NUMBER 3706 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_typevarobject.h b/Include/internal/pycore_typevarobject.h index 4d7556e68cdaeed..00a1f47975cef65 100644 --- a/Include/internal/pycore_typevarobject.h +++ b/Include/internal/pycore_typevarobject.h @@ -10,7 +10,9 @@ extern "C" { extern PyObject *_Py_make_typevar(PyObject *, PyObject *, PyObject *); extern PyObject *_Py_make_paramspec(PyThreadState *, PyObject *); +extern PyObject *_Py_make_paramspec_with_bound(PyObject *, PyObject *); extern PyObject *_Py_make_typevartuple(PyThreadState *, PyObject *); +extern PyObject *_Py_make_typevartuple_with_bound(PyObject *, PyObject *); extern PyObject *_Py_make_typealias(PyThreadState *, PyObject *); extern PyObject *_Py_subscript_generic(PyThreadState *, PyObject *); extern PyObject *_Py_set_typeparam_default(PyThreadState *, PyObject *, PyObject *); diff --git a/Lib/_ast_unparse.py b/Lib/_ast_unparse.py index 916bb25d74dee9b..f342a62ffd88701 100644 --- a/Lib/_ast_unparse.py +++ b/Lib/_ast_unparse.py @@ -453,12 +453,18 @@ def visit_TypeVar(self, node): def visit_TypeVarTuple(self, node): self.write("*" + node.name) + if node.bound: + self.write(": ") + self.traverse(node.bound) if node.default_value: self.write(" = ") self.traverse(node.default_value) def visit_ParamSpec(self, node): self.write("**" + node.name) + if node.bound: + self.write(": ") + self.traverse(node.bound) if node.default_value: self.write(" = ") self.traverse(node.default_value) diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml index dca74eb6e14bbd0..8e39c0472eaf4be 100644 --- a/Lib/test/.ruff.toml +++ b/Lib/test/.ruff.toml @@ -20,6 +20,9 @@ extend-exclude = [ "test_lazy_import/data/**/*.py", # Unary plus literal pattern is not yet supported by Ruff (GH-145239) "test_patma.py", + # Bounds on type variable tuples and parameter specifications are not yet + # supported by Ruff (GH-148945) + "test_type_params.py", ] [lint] diff --git a/Lib/test/test_ast/data/ast_repr.txt b/Lib/test/test_ast/data/ast_repr.txt index cc6accd766b78ad..a2a4913ed99ce1e 100644 --- a/Lib/test/test_ast/data/ast_repr.txt +++ b/Lib/test/test_ast/data/ast_repr.txt @@ -118,20 +118,25 @@ Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[ Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...)], kw_defaults=[None], kwarg=arg(...), defaults=[Constant(...), Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[], value=Name(id='int', ctx=Load(...)))], type_ignores=[]) Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None)], value=Name(id='int', ctx=Load(...)))], type_ignores=[]) -Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) -Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) -Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) -Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', default_value=Constant(...))], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', bound=None, default_value=Constant(...))], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=List(...), default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=List(...), default_value=Constant(...))], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=None, default_value=None)])], type_ignores=[]) -Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) -Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) -Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) -Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', default_value=Constant(...))])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', bound=None, default_value=Constant(...))])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=List(...), default_value=None)])], type_ignores=[]) Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None)])], type_ignores=[]) -Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) -Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) -Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) -Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', default_value=Constant(...))])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', bound=None, default_value=Constant(...))])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=List(...), default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', bound=List(...), default_value=Constant(...))])], type_ignores=[]) Module(body=[Match(subject=Name(id='x', ctx=Load(...)), cases=[match_case(pattern=MatchValue(...), guard=None, body=[Pass(...)])])], type_ignores=[]) Module(body=[Match(subject=Name(id='x', ctx=Load(...)), cases=[match_case(pattern=MatchValue(...), guard=None, body=[Pass(...)]), match_case(pattern=MatchAs(...), guard=None, body=[Pass(...)])])], type_ignores=[]) Module(body=[Expr(value=Constant(value=None, kind=None))], type_ignores=[]) diff --git a/Lib/test/test_ast/snippets.py b/Lib/test/test_ast/snippets.py index a565ed10f8b434b..322959d09d2b4d0 100644 --- a/Lib/test/test_ast/snippets.py +++ b/Lib/test/test_ast/snippets.py @@ -207,18 +207,23 @@ "type X[T: int, *Ts, **P] = (T, Ts, P)", "type X[T: (int, str), *Ts, **P] = (T, Ts, P)", "type X[T: int = 1, *Ts = 2, **P =3] = (T, Ts, P)", + "type X[T, *Ts: int, **P: [int]] = (T, Ts, P)", + "type X[T, *Ts: *tuple[int], **P: [int] = 2] = (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", "class X[T: int = 1, *Ts = 2, **P = 3]: pass", + "class X[T, *Ts: int, **P: [int]]: 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", "def f[T: int = 1, *Ts = 2, **P = 3](): pass", + "def f[T, *Ts: int, **P: [int]](): pass", + "def f[T, *Ts: int = 2, **P: [int] = 3](): pass", # Match "match x:\n\tcase 1:\n\t\tpass", # Match with _ @@ -515,20 +520,25 @@ def main(): ('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, 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, None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts', None), ('ParamSpec', (1, 15, 1, 18), 'P', None)], ('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',)), None), ('TypeVarTuple', (1, 15, 1, 18), 'Ts', None), ('ParamSpec', (1, 20, 1, 23), 'P', None)], ('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',)), None), ('TypeVarTuple', (1, 22, 1, 25), 'Ts', None), ('ParamSpec', (1, 27, 1, 30), 'P', None)], ('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', [('TypeAlias', (1, 0, 1, 48), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 17), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Constant', (1, 16, 1, 17), 1, None)), ('TypeVarTuple', (1, 19, 1, 26), 'Ts', ('Constant', (1, 25, 1, 26), 2, None)), ('ParamSpec', (1, 28, 1, 34), 'P', ('Constant', (1, 33, 1, 34), 3, None))], ('Tuple', (1, 38, 1, 48), [('Name', (1, 39, 1, 40), 'T', ('Load',)), ('Name', (1, 42, 1, 44), 'Ts', ('Load',)), ('Name', (1, 46, 1, 47), 'P', ('Load',))], ('Load',)))], []), +('Module', [('TypeAlias', (1, 0, 1, 32), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None, None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts', None, None), ('ParamSpec', (1, 15, 1, 18), 'P', None, None)], ('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',)), None), ('TypeVarTuple', (1, 15, 1, 18), 'Ts', None, None), ('ParamSpec', (1, 20, 1, 23), 'P', None, None)], ('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',)), None), ('TypeVarTuple', (1, 22, 1, 25), 'Ts', None, None), ('ParamSpec', (1, 27, 1, 30), 'P', None, None)], ('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', [('TypeAlias', (1, 0, 1, 48), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 17), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Constant', (1, 16, 1, 17), 1, None)), ('TypeVarTuple', (1, 19, 1, 26), 'Ts', None, ('Constant', (1, 25, 1, 26), 2, None)), ('ParamSpec', (1, 28, 1, 34), 'P', None, ('Constant', (1, 33, 1, 34), 3, None))], ('Tuple', (1, 38, 1, 48), [('Name', (1, 39, 1, 40), 'T', ('Load',)), ('Name', (1, 42, 1, 44), 'Ts', ('Load',)), ('Name', (1, 46, 1, 47), 'P', ('Load',))], ('Load',)))], []), +('Module', [('TypeAlias', (1, 0, 1, 44), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None, None), ('TypeVarTuple', (1, 10, 1, 18), 'Ts', ('Name', (1, 15, 1, 18), 'int', ('Load',)), None), ('ParamSpec', (1, 20, 1, 30), 'P', ('List', (1, 25, 1, 30), [('Name', (1, 26, 1, 29), 'int', ('Load',))], ('Load',)), None)], ('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', [('TypeAlias', (1, 0, 1, 56), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None, None), ('TypeVarTuple', (1, 10, 1, 26), 'Ts', ('Starred', (1, 15, 1, 26), ('Subscript', (1, 16, 1, 26), ('Name', (1, 16, 1, 21), 'tuple', ('Load',)), ('Name', (1, 22, 1, 25), 'int', ('Load',)), ('Load',)), ('Load',)), None), ('ParamSpec', (1, 28, 1, 42), 'P', ('List', (1, 33, 1, 38), [('Name', (1, 34, 1, 37), 'int', ('Load',))], ('Load',)), ('Constant', (1, 41, 1, 42), 2, None))], ('Tuple', (1, 46, 1, 56), [('Name', (1, 47, 1, 48), 'T', ('Load',)), ('Name', (1, 50, 1, 52), 'Ts', ('Load',)), ('Name', (1, 54, 1, 55), 'P', ('Load',))], ('Load',)))], []), ('Module', [('ClassDef', (1, 0, 1, 16), 'X', [], [], [('Pass', (1, 12, 1, 16))], [], [('TypeVar', (1, 8, 1, 9), 'T', None, None)])], []), -('Module', [('ClassDef', (1, 0, 1, 26), 'X', [], [], [('Pass', (1, 22, 1, 26))], [], [('TypeVar', (1, 8, 1, 9), 'T', None, None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts', None), ('ParamSpec', (1, 16, 1, 19), 'P', None)])], []), -('Module', [('ClassDef', (1, 0, 1, 31), 'X', [], [], [('Pass', (1, 27, 1, 31))], [], [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',)), None), ('TypeVarTuple', (1, 16, 1, 19), 'Ts', None), ('ParamSpec', (1, 21, 1, 24), 'P', None)])], []), -('Module', [('ClassDef', (1, 0, 1, 38), 'X', [], [], [('Pass', (1, 34, 1, 38))], [], [('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',)), None), ('TypeVarTuple', (1, 23, 1, 26), 'Ts', None), ('ParamSpec', (1, 28, 1, 31), 'P', None)])], []), -('Module', [('ClassDef', (1, 0, 1, 43), 'X', [], [], [('Pass', (1, 39, 1, 43))], [], [('TypeVar', (1, 8, 1, 18), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Constant', (1, 17, 1, 18), 1, None)), ('TypeVarTuple', (1, 20, 1, 27), 'Ts', ('Constant', (1, 26, 1, 27), 2, None)), ('ParamSpec', (1, 29, 1, 36), 'P', ('Constant', (1, 35, 1, 36), 3, None))])], []), +('Module', [('ClassDef', (1, 0, 1, 26), 'X', [], [], [('Pass', (1, 22, 1, 26))], [], [('TypeVar', (1, 8, 1, 9), 'T', None, None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts', None, None), ('ParamSpec', (1, 16, 1, 19), 'P', None, None)])], []), +('Module', [('ClassDef', (1, 0, 1, 31), 'X', [], [], [('Pass', (1, 27, 1, 31))], [], [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',)), None), ('TypeVarTuple', (1, 16, 1, 19), 'Ts', None, None), ('ParamSpec', (1, 21, 1, 24), 'P', None, None)])], []), +('Module', [('ClassDef', (1, 0, 1, 38), 'X', [], [], [('Pass', (1, 34, 1, 38))], [], [('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',)), None), ('TypeVarTuple', (1, 23, 1, 26), 'Ts', None, None), ('ParamSpec', (1, 28, 1, 31), 'P', None, None)])], []), +('Module', [('ClassDef', (1, 0, 1, 43), 'X', [], [], [('Pass', (1, 39, 1, 43))], [], [('TypeVar', (1, 8, 1, 18), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Constant', (1, 17, 1, 18), 1, None)), ('TypeVarTuple', (1, 20, 1, 27), 'Ts', None, ('Constant', (1, 26, 1, 27), 2, None)), ('ParamSpec', (1, 29, 1, 36), 'P', None, ('Constant', (1, 35, 1, 36), 3, None))])], []), +('Module', [('ClassDef', (1, 0, 1, 38), 'X', [], [], [('Pass', (1, 34, 1, 38))], [], [('TypeVar', (1, 8, 1, 9), 'T', None, None), ('TypeVarTuple', (1, 11, 1, 19), 'Ts', ('Name', (1, 16, 1, 19), 'int', ('Load',)), None), ('ParamSpec', (1, 21, 1, 31), 'P', ('List', (1, 26, 1, 31), [('Name', (1, 27, 1, 30), 'int', ('Load',))], ('Load',)), None)])], []), ('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts', None), ('ParamSpec', (1, 14, 1, 17), 'P', None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 31), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None, [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',)), None), ('TypeVarTuple', (1, 14, 1, 17), 'Ts', None), ('ParamSpec', (1, 19, 1, 22), 'P', None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 38), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None, [('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',)), None), ('TypeVarTuple', (1, 21, 1, 24), 'Ts', None), ('ParamSpec', (1, 26, 1, 29), 'P', None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 43), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 39, 1, 43))], [], None, None, [('TypeVar', (1, 6, 1, 16), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',)), ('Constant', (1, 15, 1, 16), 1, None)), ('TypeVarTuple', (1, 18, 1, 25), 'Ts', ('Constant', (1, 24, 1, 25), 2, None)), ('ParamSpec', (1, 27, 1, 34), 'P', ('Constant', (1, 33, 1, 34), 3, None))])], []), +('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts', None, None), ('ParamSpec', (1, 14, 1, 17), 'P', None, None)])], []), +('Module', [('FunctionDef', (1, 0, 1, 31), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None, [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',)), None), ('TypeVarTuple', (1, 14, 1, 17), 'Ts', None, None), ('ParamSpec', (1, 19, 1, 22), 'P', None, None)])], []), +('Module', [('FunctionDef', (1, 0, 1, 38), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None, [('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',)), None), ('TypeVarTuple', (1, 21, 1, 24), 'Ts', None, None), ('ParamSpec', (1, 26, 1, 29), 'P', None, None)])], []), +('Module', [('FunctionDef', (1, 0, 1, 43), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 39, 1, 43))], [], None, None, [('TypeVar', (1, 6, 1, 16), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',)), ('Constant', (1, 15, 1, 16), 1, None)), ('TypeVarTuple', (1, 18, 1, 25), 'Ts', None, ('Constant', (1, 24, 1, 25), 2, None)), ('ParamSpec', (1, 27, 1, 34), 'P', None, ('Constant', (1, 33, 1, 34), 3, None))])], []), +('Module', [('FunctionDef', (1, 0, 1, 38), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None), ('TypeVarTuple', (1, 9, 1, 17), 'Ts', ('Name', (1, 14, 1, 17), 'int', ('Load',)), None), ('ParamSpec', (1, 19, 1, 29), 'P', ('List', (1, 24, 1, 29), [('Name', (1, 25, 1, 28), 'int', ('Load',))], ('Load',)), None)])], []), +('Module', [('FunctionDef', (1, 0, 1, 46), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 42, 1, 46))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None), ('TypeVarTuple', (1, 9, 1, 21), 'Ts', ('Name', (1, 14, 1, 17), 'int', ('Load',)), ('Constant', (1, 20, 1, 21), 2, None)), ('ParamSpec', (1, 23, 1, 37), 'P', ('List', (1, 28, 1, 33), [('Name', (1, 29, 1, 32), 'int', ('Load',))], ('Load',)), ('Constant', (1, 36, 1, 37), 3, None))])], []), ('Module', [('Match', (1, 0, 3, 6), ('Name', (1, 6, 1, 7), 'x', ('Load',)), [('match_case', ('MatchValue', (2, 6, 2, 7), ('Constant', (2, 6, 2, 7), 1, None)), None, [('Pass', (3, 2, 3, 6))])])], []), ('Module', [('Match', (1, 0, 5, 6), ('Name', (1, 6, 1, 7), 'x', ('Load',)), [('match_case', ('MatchValue', (2, 6, 2, 7), ('Constant', (2, 6, 2, 7), 1, None)), None, [('Pass', (3, 2, 3, 6))]), ('match_case', ('MatchAs', (4, 6, 4, 7), None, None), None, [('Pass', (5, 2, 5, 6))])])], []), ] diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 28ac6c6fcbccc1f..cc625bd243b4b90 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -970,6 +970,21 @@ def test_type_params_default_feature_version(self): with self.assertRaises(SyntaxError): ast.parse(sample, feature_version=(3, 12)) + def test_type_params_bound_feature_version(self): + samples = [ + "type X[*Ts: int] = int", + "class X[*Ts: int]: pass", + "def f[*Ts: int](): pass", + "type X[**P: [int]] = int", + "class X[**P: [int]]: pass", + "def f[**P: [int]](): pass", + ] + for sample in samples: + with self.subTest(sample): + ast.parse(sample) + with self.assertRaises(SyntaxError): + ast.parse(sample, feature_version=(3, 15)) + def test_invalid_major_feature_version(self): with self.assertRaises(ValueError): ast.parse('pass', feature_version=(2, 7)) diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py index b6588269e1d0c65..c880d83ccb57b78 100644 --- a/Lib/test/test_type_params.py +++ b/Lib/test/test_type_params.py @@ -1076,18 +1076,22 @@ async def coroutine[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 func1[*A: str, *B: str | int](): + return A, B + + a, b = func1() + + self.assertIsInstance(a, TypeVarTuple) + self.assertEqual(a.__bound__, str) + self.assertTrue(a.__infer_variance__) + self.assertFalse(a.__covariant__) + self.assertFalse(a.__contravariant__) + + self.assertIsInstance(b, TypeVarTuple) + self.assertEqual(b.__bound__, str | int) + self.assertTrue(b.__infer_variance__) + self.assertFalse(b.__covariant__) + self.assertFalse(b.__contravariant__) def test_typevartuple_02(self): def func1[*A](): @@ -1095,22 +1099,83 @@ def func1[*A](): a = func1() self.assertIsInstance(a, TypeVarTuple) + self.assertIsNone(a.__bound__) + self.assertIsNone(a.evaluate_bound) + + def test_typevartuple_starred_bound(self): + # A type variable tuple bound is a star_expression, like its default. + def func1[*A: *tuple[int, str]](): + return A + + a = func1() + self.assertEqual(a.__bound__, (*tuple[int, str],)[0]) + self.assertEqual(repr(a.__bound__), "*tuple[int, str]") + + def test_typevartuple_bound_is_lazily_evaluated(self): + # The bound must not be evaluated when the type parameter is created. + def func1[*A: Undefined](): + return A + + a = func1() + with self.assertRaises(NameError): + a.__bound__ + + global Undefined + Undefined = int + try: + self.assertIs(a.__bound__, int) + # The evaluated bound is cached. + self.assertIs(a.__bound__, int) + finally: + del Undefined + + def test_typevartuple_bound_in_class_and_alias(self): + class Cls[*A: int]: ... + a, = Cls.__type_params__ + self.assertIs(a.__bound__, int) + + type Alias[*B: int] = int + b, = Alias.__type_params__ + self.assertIs(b.__bound__, int) + + def test_typevartuple_bound_scope(self): + # The bound is evaluated in an annotation scope nested inside the + # scope of the type parameter list, so it can see earlier type params. + def func1[T, *A: T](): + return T, A + + t, a = func1() + self.assertIs(a.__bound__, t) + + def test_typevartuple_bound_and_default_have_separate_scopes(self): + # Regression guard: the bound and the default must not share a key, + # or a comprehension in both would collide. + def func1[*A: [x for x in (int,)][0] = [y for y in (str,)][0]](): + return A + + a = func1() + self.assertIs(a.__bound__, int) + self.assertIs(a.__default__, str) 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 func1[**A: [str], **B: [str | int]](): + return A, B + + a, b = func1() + + self.assertIsInstance(a, ParamSpec) + self.assertEqual(a.__bound__, [str]) + self.assertTrue(a.__infer_variance__) + self.assertFalse(a.__covariant__) + self.assertFalse(a.__contravariant__) + + self.assertIsInstance(b, ParamSpec) + self.assertEqual(b.__bound__, [str | int]) + self.assertTrue(b.__infer_variance__) + self.assertFalse(b.__covariant__) + self.assertFalse(b.__contravariant__) def test_paramspec_02(self): def func1[**A](): @@ -1118,10 +1183,58 @@ def func1[**A](): a = func1() self.assertIsInstance(a, ParamSpec) + self.assertIsNone(a.__bound__) + self.assertIsNone(a.evaluate_bound) self.assertTrue(a.__infer_variance__) self.assertFalse(a.__covariant__) self.assertFalse(a.__contravariant__) + def test_paramspec_constructor_no_bound(self): + # gh-148945: previously this was types.NoneType, unlike TypeVar and + # TypeVarTuple. + self.assertIsNone(ParamSpec("P").__bound__) + self.assertIsNone(ParamSpec("P", bound=None).__bound__) + + def test_paramspec_bound_is_lazily_evaluated(self): + def func1[**A: [Undefined]](): + return A + + a = func1() + with self.assertRaises(NameError): + a.__bound__ + + global Undefined + Undefined = int + try: + self.assertEqual(a.__bound__, [int]) + self.assertEqual(a.__bound__, [int]) + finally: + del Undefined + + def test_paramspec_bound_in_class_and_alias(self): + class Cls[**A: [int]]: ... + a, = Cls.__type_params__ + self.assertEqual(a.__bound__, [int]) + + type Alias[**B: [int]] = int + b, = Alias.__type_params__ + self.assertEqual(b.__bound__, [int]) + + def test_paramspec_bound_scope(self): + def func1[T, **A: [T]](): + return T, A + + t, a = func1() + self.assertEqual(a.__bound__, [t]) + + def test_paramspec_bound_and_default_have_separate_scopes(self): + def func1[**A: [x for x in (int,)] = [y for y in (str,)]](): + return A + + a = func1() + self.assertEqual(a.__bound__, [int]) + self.assertEqual(a.__default__, [str]) + class TypeParamsTypeParamsDunder(unittest.TestCase): def test_typeparams_dunder_class_01(self): @@ -1265,7 +1378,7 @@ class NewStyle[T]: P, P.args, P.kwargs, - TypeVarTuple('Ts'), + TypeVarTuple('Ts', bound=int), OldStyle, OldStyle[int], OldStyle(), @@ -1423,29 +1536,38 @@ class TestEvaluateFunctions(unittest.TestCase): def test_general(self): type Alias = int Alias2 = TypeAliasType("Alias2", int) - def f[T: int = int, **P = int, *Ts = int](): pass - T, P, Ts = f.__type_params__ + def f[T: int = int, *Ts: int = int, **P: [int] = int](): pass + T, Ts, P = f.__type_params__ T2 = TypeVar("T2", bound=int, default=int) - P2 = ParamSpec("P2", default=int) - Ts2 = TypeVarTuple("Ts2", default=int) + Ts2 = TypeVarTuple("Ts2", bound=int, default=int) + P2 = ParamSpec("P2", bound=[int], default=int) + # A ParamSpec bound is a parameter list, so it evaluates to a list + # rather than to a bare type. cases = [ - Alias.evaluate_value, - Alias2.evaluate_value, - T.evaluate_bound, - T.evaluate_default, - P.evaluate_default, - Ts.evaluate_default, - T2.evaluate_bound, - T2.evaluate_default, - P2.evaluate_default, - Ts2.evaluate_default, + (Alias.evaluate_value, int, 'int'), + (Alias2.evaluate_value, int, 'int'), + (T.evaluate_bound, int, 'int'), + (T.evaluate_default, int, 'int'), + (Ts.evaluate_bound, int, 'int'), + (Ts.evaluate_default, int, 'int'), + (P.evaluate_bound, [int], '[int]'), + (P.evaluate_default, int, 'int'), + (T2.evaluate_bound, int, 'int'), + (T2.evaluate_default, int, 'int'), + (Ts2.evaluate_bound, int, 'int'), + (Ts2.evaluate_default, int, 'int'), + # A constevaluator does not recurse into containers, so the + # STRING format falls back to repr() (as it already does for + # ParamSpec defaults such as ParamSpec("P", default=[int])). + (P2.evaluate_bound, [int], "[]"), + (P2.evaluate_default, int, 'int'), ] - for case in cases: + for case, value, string in cases: with self.subTest(case=case): - self.assertIs(case(1), int) - self.assertIs(annotationlib.call_evaluate_function(case, annotationlib.Format.VALUE), int) - self.assertIs(annotationlib.call_evaluate_function(case, annotationlib.Format.FORWARDREF), int) - self.assertEqual(annotationlib.call_evaluate_function(case, annotationlib.Format.STRING), 'int') + self.assertEqual(case(1), value) + self.assertEqual(annotationlib.call_evaluate_function(case, annotationlib.Format.VALUE), value) + self.assertEqual(annotationlib.call_evaluate_function(case, annotationlib.Format.FORWARDREF), value) + self.assertEqual(annotationlib.call_evaluate_function(case, annotationlib.Format.STRING), string) def test_signature(self): # gh-151665: the ".format" parameter of compiler-generated evaluators diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-00-00-00.gh-issue-148945.Bo0nds.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-00-00-00.gh-issue-148945.Bo0nds.rst new file mode 100644 index 000000000000000..18b0711e554193c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-00-00-00.gh-issue-148945.Bo0nds.rst @@ -0,0 +1,7 @@ +Add support for bounds on type variable tuples and parameter specifications in +:ref:`type parameter lists `, for example ``def f[*Ts: int, **P: +[str]](): ...``. As with :class:`~typing.TypeVar` bounds, the bound is +:ref:`lazily evaluated ` and is exposed through the +``__bound__`` attribute and the ``evaluate_bound`` :term:`evaluate function`. +The :class:`ast.TypeVarTuple` and :class:`ast.ParamSpec` nodes gain a ``bound`` +field. diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index b2c3c79c93ff195..9c25bae44bd1180 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -37,6 +37,7 @@ typedef struct { PyObject_HEAD PyObject *name; PyObject *bound; + PyObject *evaluate_bound; PyObject *default_value; PyObject *evaluate_default; bool covariant; @@ -48,6 +49,7 @@ typedef struct { PyObject_HEAD PyObject *name; PyObject *bound; + PyObject *evaluate_bound; PyObject *default_value; PyObject *evaluate_default; bool covariant; @@ -1180,6 +1182,7 @@ paramspec_dealloc(PyObject *self) Py_XDECREF(ps->name); Py_XDECREF(ps->bound); + Py_XDECREF(ps->evaluate_bound); Py_XDECREF(ps->default_value); Py_XDECREF(ps->evaluate_default); PyObject_ClearManagedDict(self); @@ -1196,6 +1199,7 @@ paramspec_traverse(PyObject *self, visitproc visit, void *arg) paramspecobject *ps = paramspecobject_CAST(self); Py_VISIT(ps->name); Py_VISIT(ps->bound); + Py_VISIT(ps->evaluate_bound); Py_VISIT(ps->default_value); Py_VISIT(ps->evaluate_default); return PyObject_VisitManagedDict(self, visit, arg); @@ -1207,6 +1211,7 @@ paramspec_clear(PyObject *op) paramspecobject *self = paramspecobject_CAST(op); Py_CLEAR(self->name); Py_CLEAR(self->bound); + Py_CLEAR(self->evaluate_bound); Py_CLEAR(self->default_value); Py_CLEAR(self->evaluate_default); PyObject_ClearManagedDict(op); @@ -1228,7 +1233,6 @@ paramspec_repr(PyObject *self) static PyMemberDef paramspec_members[] = { {"__name__", _Py_T_OBJECT, offsetof(paramspecobject, name), Py_READONLY}, - {"__bound__", _Py_T_OBJECT, offsetof(paramspecobject, bound), Py_READONLY}, {"__covariant__", Py_T_BOOL, offsetof(paramspecobject, covariant), Py_READONLY}, {"__contravariant__", Py_T_BOOL, offsetof(paramspecobject, contravariant), Py_READONLY}, {"__infer_variance__", Py_T_BOOL, offsetof(paramspecobject, infer_variance), Py_READONLY}, @@ -1249,6 +1253,34 @@ paramspec_kwargs(PyObject *self, void *Py_UNUSED(closure)) return (PyObject *)paramspecattr_new(tp, self); } +static PyObject * +paramspec_bound(PyObject *op, void *Py_UNUSED(closure)) +{ + paramspecobject *self = paramspecobject_CAST(op); + if (self->bound != NULL) { + return Py_NewRef(self->bound); + } + if (self->evaluate_bound == NULL) { + Py_RETURN_NONE; + } + PyObject *bound = PyObject_CallNoArgs(self->evaluate_bound); + self->bound = Py_XNewRef(bound); + return bound; +} + +static PyObject * +paramspec_evaluate_bound(PyObject *op, void *Py_UNUSED(closure)) +{ + paramspecobject *self = paramspecobject_CAST(op); + if (self->evaluate_bound != NULL) { + return Py_NewRef(self->evaluate_bound); + } + if (self->bound != NULL) { + return constevaluator_alloc(self->bound); + } + Py_RETURN_NONE; +} + static PyObject * paramspec_default(PyObject *op, void *Py_UNUSED(closure)) { @@ -1280,13 +1312,16 @@ paramspec_evaluate_default(PyObject *op, void *Py_UNUSED(closure)) static PyGetSetDef paramspec_getset[] = { {"args", paramspec_args, NULL, PyDoc_STR("Represents positional arguments."), NULL}, {"kwargs", paramspec_kwargs, NULL, PyDoc_STR("Represents keyword arguments."), NULL}, + {"__bound__", paramspec_bound, NULL, "The bound for this ParamSpec.", NULL}, {"__default__", paramspec_default, NULL, "The default value for this ParamSpec.", NULL}, + {"evaluate_bound", paramspec_evaluate_bound, NULL, NULL, NULL}, {"evaluate_default", paramspec_evaluate_default, NULL, NULL, NULL}, {0}, }; static paramspecobject * -paramspec_alloc(PyObject *name, PyObject *bound, PyObject *default_value, bool covariant, +paramspec_alloc(PyObject *name, PyObject *bound, PyObject *evaluate_bound, + PyObject *default_value, bool covariant, bool contravariant, bool infer_variance, PyObject *module) { PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.paramspec_type; @@ -1296,6 +1331,7 @@ paramspec_alloc(PyObject *name, PyObject *bound, PyObject *default_value, bool c } ps->name = Py_NewRef(name); ps->bound = Py_XNewRef(bound); + ps->evaluate_bound = Py_XNewRef(evaluate_bound); ps->covariant = covariant; ps->contravariant = contravariant; ps->infer_variance = infer_variance; @@ -1340,12 +1376,16 @@ paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound, PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); return NULL; } + if (Py_IsNone(bound)) { + bound = NULL; + } PyObject *module = caller(); if (module == NULL) { return NULL; } PyObject *ps = (PyObject *)paramspec_alloc( - name, bound, default_value, covariant, contravariant, infer_variance, module); + name, bound, NULL, default_value, covariant, contravariant, + infer_variance, module); Py_DECREF(module); return ps; } @@ -1521,6 +1561,7 @@ typevartuple_dealloc(PyObject *self) Py_XDECREF(tvt->name); Py_XDECREF(tvt->bound); + Py_XDECREF(tvt->evaluate_bound); Py_XDECREF(tvt->default_value); Py_XDECREF(tvt->evaluate_default); PyObject_ClearManagedDict(self); @@ -1563,7 +1604,6 @@ typevartuple_repr(PyObject *self) static PyMemberDef typevartuple_members[] = { {"__name__", _Py_T_OBJECT, offsetof(typevartupleobject, name), Py_READONLY}, - {"__bound__", _Py_T_OBJECT, offsetof(typevartupleobject, bound), Py_READONLY}, {"__covariant__", Py_T_BOOL, offsetof(typevartupleobject, covariant), Py_READONLY}, {"__contravariant__", Py_T_BOOL, offsetof(typevartupleobject, contravariant), Py_READONLY}, {"__infer_variance__", Py_T_BOOL, offsetof(typevartupleobject, infer_variance), Py_READONLY}, @@ -1571,7 +1611,8 @@ static PyMemberDef typevartuple_members[] = { }; static typevartupleobject * -typevartuple_alloc(PyObject *name, PyObject *bound, PyObject *default_value, +typevartuple_alloc(PyObject *name, PyObject *bound, PyObject *evaluate_bound, + PyObject *default_value, bool covariant, bool contravariant, bool infer_variance, PyObject *module) { @@ -1582,6 +1623,7 @@ typevartuple_alloc(PyObject *name, PyObject *bound, PyObject *default_value, } tvt->name = Py_NewRef(name); tvt->bound = Py_XNewRef(bound); + tvt->evaluate_bound = Py_XNewRef(evaluate_bound); tvt->covariant = covariant; tvt->contravariant = contravariant; tvt->infer_variance = infer_variance; @@ -1626,12 +1668,16 @@ typevartuple_impl(PyTypeObject *type, PyObject *name, PyObject *bound, PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); return NULL; } + if (Py_IsNone(bound)) { + bound = NULL; + } PyObject *module = caller(); if (module == NULL) { return NULL; } PyObject *result = (PyObject *)typevartuple_alloc( - name, bound, default_value, covariant, contravariant, infer_variance, module); + name, bound, NULL, default_value, covariant, contravariant, + infer_variance, module); Py_DECREF(module); return result; } @@ -1716,6 +1762,7 @@ typevartuple_traverse(PyObject *self, visitproc visit, void *arg) typevartupleobject *tvt = typevartupleobject_CAST(self); Py_VISIT(tvt->name); Py_VISIT(tvt->bound); + Py_VISIT(tvt->evaluate_bound); Py_VISIT(tvt->default_value); Py_VISIT(tvt->evaluate_default); return PyObject_VisitManagedDict(self, visit, arg); @@ -1727,12 +1774,41 @@ typevartuple_clear(PyObject *self) typevartupleobject *tvt = typevartupleobject_CAST(self); Py_CLEAR(tvt->name); Py_CLEAR(tvt->bound); + Py_CLEAR(tvt->evaluate_bound); Py_CLEAR(tvt->default_value); Py_CLEAR(tvt->evaluate_default); PyObject_ClearManagedDict(self); return 0; } +static PyObject * +typevartuple_bound(PyObject *op, void *Py_UNUSED(closure)) +{ + typevartupleobject *self = typevartupleobject_CAST(op); + if (self->bound != NULL) { + return Py_NewRef(self->bound); + } + if (self->evaluate_bound == NULL) { + Py_RETURN_NONE; + } + PyObject *bound = PyObject_CallNoArgs(self->evaluate_bound); + self->bound = Py_XNewRef(bound); + return bound; +} + +static PyObject * +typevartuple_evaluate_bound(PyObject *op, void *Py_UNUSED(closure)) +{ + typevartupleobject *self = typevartupleobject_CAST(op); + if (self->evaluate_bound != NULL) { + return Py_NewRef(self->evaluate_bound); + } + if (self->bound != NULL) { + return constevaluator_alloc(self->bound); + } + Py_RETURN_NONE; +} + static PyObject * typevartuple_default(PyObject *op, void *Py_UNUSED(closure)) { @@ -1762,7 +1838,9 @@ typevartuple_evaluate_default(PyObject *op, void *Py_UNUSED(closure)) } static PyGetSetDef typevartuple_getset[] = { + {"__bound__", typevartuple_bound, NULL, "The bound for this TypeVarTuple.", NULL}, {"__default__", typevartuple_default, NULL, "The default value for this TypeVarTuple.", NULL}, + {"evaluate_bound", typevartuple_evaluate_bound, NULL, NULL, NULL}, {"evaluate_default", typevartuple_evaluate_default, NULL, NULL, NULL}, {0}, }; @@ -1851,14 +1929,32 @@ PyObject * _Py_make_paramspec(PyThreadState *Py_UNUSED(ignored), PyObject *v) { assert(PyUnicode_Check(v)); - return (PyObject *)paramspec_alloc(v, NULL, NULL, false, false, true, NULL); + return (PyObject *)paramspec_alloc(v, NULL, NULL, NULL, false, false, true, + NULL); +} + +PyObject * +_Py_make_paramspec_with_bound(PyObject *name, PyObject *evaluate_bound) +{ + assert(PyUnicode_Check(name)); + return (PyObject *)paramspec_alloc(name, NULL, evaluate_bound, NULL, + false, false, true, NULL); } PyObject * _Py_make_typevartuple(PyThreadState *Py_UNUSED(ignored), PyObject *v) { assert(PyUnicode_Check(v)); - return (PyObject *)typevartuple_alloc(v, NULL, NULL, false, false, true, NULL); + return (PyObject *)typevartuple_alloc(v, NULL, NULL, NULL, false, false, + true, NULL); +} + +PyObject * +_Py_make_typevartuple_with_bound(PyObject *name, PyObject *evaluate_bound) +{ + assert(PyUnicode_Check(name)); + return (PyObject *)typevartuple_alloc(name, NULL, evaluate_bound, NULL, + false, false, true, NULL); } static PyObject * diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 2f0b123858f8d18..034ab5447683c2f 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -148,7 +148,7 @@ module Python type_ignore = TypeIgnore(int lineno, string tag) type_param = TypeVar(identifier name, expr? bound, expr? default_value) - | ParamSpec(identifier name, expr? default_value) - | TypeVarTuple(identifier name, expr? default_value) + | ParamSpec(identifier name, expr? bound, expr? default_value) + | TypeVarTuple(identifier name, expr? bound, expr? default_value) attributes (int lineno, int col_offset, int end_lineno, int end_col_offset) } diff --git a/Parser/parser.c b/Parser/parser.c index 800db5b490fea98..b2bab9a64de90a0 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -192,359 +192,360 @@ static char *soft_keywords[] = { #define type_param_seq_type 1103 #define type_param_type 1104 #define type_param_bound_type 1105 -#define type_param_default_type 1106 -#define type_param_starred_default_type 1107 -#define expressions_type 1108 -#define expression_type 1109 -#define if_expression_type 1110 -#define yield_expr_type 1111 -#define star_expressions_type 1112 -#define star_expression_type 1113 -#define star_named_expressions_type 1114 -#define star_named_expressions_sequence_type 1115 -#define star_named_expression_type 1116 -#define star_named_expression_sequence_type 1117 -#define assignment_expression_type 1118 -#define named_expression_type 1119 -#define disjunction_type 1120 -#define conjunction_type 1121 -#define inversion_type 1122 -#define comparison_type 1123 -#define compare_op_bitwise_or_pair_type 1124 -#define eq_bitwise_or_type 1125 -#define noteq_bitwise_or_type 1126 -#define lte_bitwise_or_type 1127 -#define lt_bitwise_or_type 1128 -#define gte_bitwise_or_type 1129 -#define gt_bitwise_or_type 1130 -#define notin_bitwise_or_type 1131 -#define in_bitwise_or_type 1132 -#define isnot_bitwise_or_type 1133 -#define is_bitwise_or_type 1134 -#define bitwise_or_type 1135 // Left-recursive -#define bitwise_xor_type 1136 // Left-recursive -#define bitwise_and_type 1137 // Left-recursive -#define shift_expr_type 1138 // Left-recursive -#define sum_type 1139 // Left-recursive -#define term_type 1140 // Left-recursive -#define factor_type 1141 -#define power_type 1142 -#define await_primary_type 1143 -#define primary_type 1144 // Left-recursive -#define slices_type 1145 -#define slice_type 1146 -#define atom_type 1147 -#define group_type 1148 -#define lambdef_type 1149 -#define lambda_params_type 1150 -#define lambda_parameters_type 1151 -#define lambda_slash_no_default_type 1152 -#define lambda_slash_with_default_type 1153 -#define lambda_star_etc_type 1154 -#define lambda_kwds_type 1155 -#define lambda_param_no_default_type 1156 -#define lambda_param_with_default_type 1157 -#define lambda_param_maybe_default_type 1158 -#define lambda_param_type 1159 -#define fstring_middle_type 1160 -#define fstring_replacement_field_type 1161 -#define fstring_conversion_type 1162 -#define fstring_full_format_spec_type 1163 -#define fstring_format_spec_type 1164 -#define fstring_type 1165 -#define tstring_format_spec_replacement_field_type 1166 -#define tstring_format_spec_type 1167 -#define tstring_full_format_spec_type 1168 -#define tstring_replacement_field_type 1169 -#define tstring_middle_type 1170 -#define tstring_type 1171 -#define string_type 1172 -#define strings_type 1173 -#define list_type 1174 -#define tuple_type 1175 -#define set_type 1176 -#define dict_type 1177 -#define double_starred_kvpairs_type 1178 -#define double_starred_kvpair_type 1179 -#define kvpair_type 1180 -#define for_if_clauses_type 1181 -#define for_if_clause_type 1182 -#define listcomp_type 1183 -#define setcomp_type 1184 -#define genexp_type 1185 -#define dictcomp_type 1186 -#define arguments_type 1187 -#define args_type 1188 -#define kwargs_type 1189 -#define starred_expression_type 1190 -#define kwarg_or_starred_type 1191 -#define kwarg_or_double_starred_type 1192 -#define star_targets_type 1193 -#define star_targets_list_seq_type 1194 -#define star_targets_tuple_seq_type 1195 -#define star_target_type 1196 -#define target_with_star_atom_type 1197 -#define star_atom_type 1198 -#define single_target_type 1199 -#define single_subscript_attribute_target_type 1200 -#define t_primary_type 1201 // Left-recursive -#define t_lookahead_type 1202 -#define del_targets_type 1203 -#define del_target_type 1204 -#define del_t_atom_type 1205 -#define type_expressions_type 1206 -#define func_type_comment_type 1207 -#define invalid_arguments_type 1208 -#define invalid_kwarg_type 1209 -#define expression_without_invalid_type 1210 -#define invalid_legacy_expression_type 1211 -#define invalid_type_param_type 1212 -#define invalid_expression_type 1213 -#define invalid_if_expression_type 1214 -#define invalid_named_expression_type 1215 -#define invalid_assignment_type 1216 -#define invalid_ann_assign_target_type 1217 -#define invalid_raise_stmt_type 1218 -#define invalid_del_stmt_type 1219 -#define invalid_assert_stmt_type 1220 -#define invalid_block_type 1221 -#define invalid_comprehension_type 1222 -#define invalid_parameters_type 1223 -#define invalid_default_type 1224 -#define invalid_star_etc_type 1225 -#define invalid_kwds_type 1226 -#define invalid_parameters_helper_type 1227 -#define invalid_lambda_parameters_type 1228 -#define invalid_lambda_parameters_helper_type 1229 -#define invalid_lambda_star_etc_type 1230 -#define invalid_lambda_kwds_type 1231 -#define invalid_double_type_comments_type 1232 -#define invalid_with_item_type 1233 -#define invalid_for_if_clause_type 1234 -#define invalid_for_target_type 1235 -#define invalid_group_type 1236 -#define invalid_import_type 1237 -#define invalid_dotted_as_name_type 1238 -#define invalid_import_from_as_name_type 1239 -#define invalid_import_from_type 1240 -#define invalid_import_from_targets_type 1241 -#define invalid_with_stmt_type 1242 -#define invalid_with_stmt_indent_type 1243 -#define invalid_try_stmt_type 1244 -#define invalid_except_stmt_type 1245 -#define invalid_except_star_stmt_type 1246 -#define invalid_finally_stmt_type 1247 -#define invalid_except_stmt_indent_type 1248 -#define invalid_except_star_stmt_indent_type 1249 -#define invalid_match_stmt_type 1250 -#define invalid_case_block_type 1251 -#define invalid_as_pattern_type 1252 -#define invalid_class_pattern_type 1253 -#define invalid_mapping_pattern_type 1254 -#define invalid_class_argument_pattern_type 1255 -#define invalid_if_stmt_type 1256 -#define invalid_elif_stmt_type 1257 -#define invalid_else_stmt_type 1258 -#define invalid_while_stmt_type 1259 -#define invalid_for_stmt_type 1260 -#define invalid_def_raw_type 1261 -#define invalid_class_def_raw_type 1262 -#define invalid_double_starred_kvpairs_type 1263 -#define invalid_kvpair_unpacking_type 1264 -#define invalid_kvpair_type 1265 -#define invalid_starred_expression_unpacking_type 1266 -#define invalid_starred_expression_unpacking_sequence_type 1267 -#define invalid_starred_expression_type 1268 -#define invalid_fstring_replacement_field_type 1269 -#define invalid_fstring_conversion_character_type 1270 -#define invalid_tstring_replacement_field_type 1271 -#define invalid_tstring_conversion_character_type 1272 -#define invalid_string_tstring_concat_type 1273 -#define invalid_arithmetic_type 1274 // Left-recursive -#define invalid_factor_type 1275 -#define invalid_type_params_type 1276 -#define invalid_bitwise_and_type 1277 // Left-recursive -#define invalid_bitwise_or_type 1278 // Left-recursive -#define _loop0_1_type 1279 -#define _loop1_2_type 1280 -#define _loop0_3_type 1281 -#define _gather_4_type 1282 -#define _tmp_5_type 1283 -#define _tmp_6_type 1284 -#define _tmp_7_type 1285 -#define _tmp_8_type 1286 -#define _tmp_9_type 1287 -#define _tmp_10_type 1288 -#define _tmp_11_type 1289 -#define _loop1_12_type 1290 -#define _loop0_13_type 1291 -#define _gather_14_type 1292 -#define _tmp_15_type 1293 -#define _tmp_16_type 1294 -#define _loop0_17_type 1295 -#define _loop1_18_type 1296 -#define _loop0_19_type 1297 -#define _gather_20_type 1298 -#define _tmp_21_type 1299 -#define _loop0_22_type 1300 -#define _gather_23_type 1301 -#define _loop1_24_type 1302 -#define _tmp_25_type 1303 -#define _tmp_26_type 1304 -#define _loop0_27_type 1305 -#define _loop0_28_type 1306 -#define _loop1_29_type 1307 -#define _loop1_30_type 1308 -#define _loop0_31_type 1309 -#define _loop1_32_type 1310 -#define _loop0_33_type 1311 -#define _gather_34_type 1312 -#define _tmp_35_type 1313 -#define _loop1_36_type 1314 -#define _loop1_37_type 1315 -#define _loop1_38_type 1316 -#define _loop0_39_type 1317 -#define _gather_40_type 1318 -#define _tmp_41_type 1319 -#define _tmp_42_type 1320 -#define _tmp_43_type 1321 -#define _loop0_44_type 1322 -#define _gather_45_type 1323 -#define _loop0_46_type 1324 -#define _gather_47_type 1325 -#define _tmp_48_type 1326 -#define _loop0_49_type 1327 -#define _gather_50_type 1328 -#define _loop0_51_type 1329 -#define _gather_52_type 1330 -#define _loop0_53_type 1331 -#define _gather_54_type 1332 -#define _loop1_55_type 1333 -#define _loop1_56_type 1334 -#define _loop0_57_type 1335 -#define _gather_58_type 1336 -#define _loop0_59_type 1337 -#define _gather_60_type 1338 -#define _loop1_61_type 1339 -#define _loop1_62_type 1340 -#define _loop1_63_type 1341 -#define _tmp_64_type 1342 -#define _loop0_65_type 1343 -#define _gather_66_type 1344 -#define _tmp_67_type 1345 -#define _tmp_68_type 1346 -#define _tmp_69_type 1347 -#define _tmp_70_type 1348 -#define _tmp_71_type 1349 -#define _loop0_72_type 1350 -#define _loop0_73_type 1351 -#define _loop1_74_type 1352 -#define _loop1_75_type 1353 -#define _loop0_76_type 1354 -#define _loop1_77_type 1355 -#define _loop0_78_type 1356 -#define _loop0_79_type 1357 -#define _loop0_80_type 1358 -#define _loop0_81_type 1359 -#define _loop1_82_type 1360 -#define _loop1_83_type 1361 -#define _tmp_84_type 1362 -#define _loop0_85_type 1363 -#define _gather_86_type 1364 -#define _loop1_87_type 1365 -#define _loop0_88_type 1366 -#define _tmp_89_type 1367 -#define _loop0_90_type 1368 -#define _gather_91_type 1369 -#define _tmp_92_type 1370 -#define _loop0_93_type 1371 -#define _gather_94_type 1372 -#define _loop0_95_type 1373 -#define _gather_96_type 1374 -#define _loop0_97_type 1375 -#define _loop0_98_type 1376 -#define _gather_99_type 1377 -#define _loop1_100_type 1378 -#define _tmp_101_type 1379 -#define _loop0_102_type 1380 -#define _gather_103_type 1381 -#define _loop0_104_type 1382 -#define _gather_105_type 1383 -#define _tmp_106_type 1384 -#define _tmp_107_type 1385 -#define _loop0_108_type 1386 -#define _gather_109_type 1387 -#define _tmp_110_type 1388 -#define _tmp_111_type 1389 -#define _tmp_112_type 1390 -#define _tmp_113_type 1391 -#define _tmp_114_type 1392 -#define _loop1_115_type 1393 -#define _tmp_116_type 1394 -#define _tmp_117_type 1395 -#define _tmp_118_type 1396 -#define _tmp_119_type 1397 -#define _tmp_120_type 1398 -#define _loop0_121_type 1399 -#define _loop0_122_type 1400 -#define _tmp_123_type 1401 -#define _tmp_124_type 1402 -#define _tmp_125_type 1403 -#define _tmp_126_type 1404 -#define _tmp_127_type 1405 -#define _tmp_128_type 1406 -#define _tmp_129_type 1407 -#define _tmp_130_type 1408 -#define _loop0_131_type 1409 -#define _gather_132_type 1410 -#define _tmp_133_type 1411 -#define _tmp_134_type 1412 -#define _tmp_135_type 1413 -#define _tmp_136_type 1414 -#define _loop0_137_type 1415 -#define _gather_138_type 1416 -#define _tmp_139_type 1417 -#define _loop0_140_type 1418 -#define _gather_141_type 1419 -#define _loop0_142_type 1420 -#define _gather_143_type 1421 -#define _tmp_144_type 1422 -#define _loop0_145_type 1423 -#define _tmp_146_type 1424 -#define _tmp_147_type 1425 -#define _tmp_148_type 1426 -#define _tmp_149_type 1427 -#define _tmp_150_type 1428 -#define _tmp_151_type 1429 -#define _tmp_152_type 1430 -#define _tmp_153_type 1431 -#define _tmp_154_type 1432 -#define _tmp_155_type 1433 -#define _tmp_156_type 1434 -#define _tmp_157_type 1435 -#define _tmp_158_type 1436 -#define _tmp_159_type 1437 -#define _tmp_160_type 1438 -#define _tmp_161_type 1439 -#define _tmp_162_type 1440 -#define _tmp_163_type 1441 -#define _tmp_164_type 1442 -#define _tmp_165_type 1443 -#define _tmp_166_type 1444 -#define _tmp_167_type 1445 -#define _tmp_168_type 1446 -#define _tmp_169_type 1447 -#define _tmp_170_type 1448 -#define _tmp_171_type 1449 -#define _tmp_172_type 1450 -#define _tmp_173_type 1451 -#define _loop0_174_type 1452 -#define _tmp_175_type 1453 -#define _tmp_176_type 1454 -#define _tmp_177_type 1455 -#define _tmp_178_type 1456 -#define _tmp_179_type 1457 -#define _tmp_180_type 1458 +#define type_param_starred_bound_type 1106 +#define type_param_paramspec_bound_type 1107 +#define type_param_default_type 1108 +#define type_param_starred_default_type 1109 +#define expressions_type 1110 +#define expression_type 1111 +#define if_expression_type 1112 +#define yield_expr_type 1113 +#define star_expressions_type 1114 +#define star_expression_type 1115 +#define star_named_expressions_type 1116 +#define star_named_expressions_sequence_type 1117 +#define star_named_expression_type 1118 +#define star_named_expression_sequence_type 1119 +#define assignment_expression_type 1120 +#define named_expression_type 1121 +#define disjunction_type 1122 +#define conjunction_type 1123 +#define inversion_type 1124 +#define comparison_type 1125 +#define compare_op_bitwise_or_pair_type 1126 +#define eq_bitwise_or_type 1127 +#define noteq_bitwise_or_type 1128 +#define lte_bitwise_or_type 1129 +#define lt_bitwise_or_type 1130 +#define gte_bitwise_or_type 1131 +#define gt_bitwise_or_type 1132 +#define notin_bitwise_or_type 1133 +#define in_bitwise_or_type 1134 +#define isnot_bitwise_or_type 1135 +#define is_bitwise_or_type 1136 +#define bitwise_or_type 1137 // Left-recursive +#define bitwise_xor_type 1138 // Left-recursive +#define bitwise_and_type 1139 // Left-recursive +#define shift_expr_type 1140 // Left-recursive +#define sum_type 1141 // Left-recursive +#define term_type 1142 // Left-recursive +#define factor_type 1143 +#define power_type 1144 +#define await_primary_type 1145 +#define primary_type 1146 // Left-recursive +#define slices_type 1147 +#define slice_type 1148 +#define atom_type 1149 +#define group_type 1150 +#define lambdef_type 1151 +#define lambda_params_type 1152 +#define lambda_parameters_type 1153 +#define lambda_slash_no_default_type 1154 +#define lambda_slash_with_default_type 1155 +#define lambda_star_etc_type 1156 +#define lambda_kwds_type 1157 +#define lambda_param_no_default_type 1158 +#define lambda_param_with_default_type 1159 +#define lambda_param_maybe_default_type 1160 +#define lambda_param_type 1161 +#define fstring_middle_type 1162 +#define fstring_replacement_field_type 1163 +#define fstring_conversion_type 1164 +#define fstring_full_format_spec_type 1165 +#define fstring_format_spec_type 1166 +#define fstring_type 1167 +#define tstring_format_spec_replacement_field_type 1168 +#define tstring_format_spec_type 1169 +#define tstring_full_format_spec_type 1170 +#define tstring_replacement_field_type 1171 +#define tstring_middle_type 1172 +#define tstring_type 1173 +#define string_type 1174 +#define strings_type 1175 +#define list_type 1176 +#define tuple_type 1177 +#define set_type 1178 +#define dict_type 1179 +#define double_starred_kvpairs_type 1180 +#define double_starred_kvpair_type 1181 +#define kvpair_type 1182 +#define for_if_clauses_type 1183 +#define for_if_clause_type 1184 +#define listcomp_type 1185 +#define setcomp_type 1186 +#define genexp_type 1187 +#define dictcomp_type 1188 +#define arguments_type 1189 +#define args_type 1190 +#define kwargs_type 1191 +#define starred_expression_type 1192 +#define kwarg_or_starred_type 1193 +#define kwarg_or_double_starred_type 1194 +#define star_targets_type 1195 +#define star_targets_list_seq_type 1196 +#define star_targets_tuple_seq_type 1197 +#define star_target_type 1198 +#define target_with_star_atom_type 1199 +#define star_atom_type 1200 +#define single_target_type 1201 +#define single_subscript_attribute_target_type 1202 +#define t_primary_type 1203 // Left-recursive +#define t_lookahead_type 1204 +#define del_targets_type 1205 +#define del_target_type 1206 +#define del_t_atom_type 1207 +#define type_expressions_type 1208 +#define func_type_comment_type 1209 +#define invalid_arguments_type 1210 +#define invalid_kwarg_type 1211 +#define expression_without_invalid_type 1212 +#define invalid_legacy_expression_type 1213 +#define invalid_expression_type 1214 +#define invalid_if_expression_type 1215 +#define invalid_named_expression_type 1216 +#define invalid_assignment_type 1217 +#define invalid_ann_assign_target_type 1218 +#define invalid_raise_stmt_type 1219 +#define invalid_del_stmt_type 1220 +#define invalid_assert_stmt_type 1221 +#define invalid_block_type 1222 +#define invalid_comprehension_type 1223 +#define invalid_parameters_type 1224 +#define invalid_default_type 1225 +#define invalid_star_etc_type 1226 +#define invalid_kwds_type 1227 +#define invalid_parameters_helper_type 1228 +#define invalid_lambda_parameters_type 1229 +#define invalid_lambda_parameters_helper_type 1230 +#define invalid_lambda_star_etc_type 1231 +#define invalid_lambda_kwds_type 1232 +#define invalid_double_type_comments_type 1233 +#define invalid_with_item_type 1234 +#define invalid_for_if_clause_type 1235 +#define invalid_for_target_type 1236 +#define invalid_group_type 1237 +#define invalid_import_type 1238 +#define invalid_dotted_as_name_type 1239 +#define invalid_import_from_as_name_type 1240 +#define invalid_import_from_type 1241 +#define invalid_import_from_targets_type 1242 +#define invalid_with_stmt_type 1243 +#define invalid_with_stmt_indent_type 1244 +#define invalid_try_stmt_type 1245 +#define invalid_except_stmt_type 1246 +#define invalid_except_star_stmt_type 1247 +#define invalid_finally_stmt_type 1248 +#define invalid_except_stmt_indent_type 1249 +#define invalid_except_star_stmt_indent_type 1250 +#define invalid_match_stmt_type 1251 +#define invalid_case_block_type 1252 +#define invalid_as_pattern_type 1253 +#define invalid_class_pattern_type 1254 +#define invalid_mapping_pattern_type 1255 +#define invalid_class_argument_pattern_type 1256 +#define invalid_if_stmt_type 1257 +#define invalid_elif_stmt_type 1258 +#define invalid_else_stmt_type 1259 +#define invalid_while_stmt_type 1260 +#define invalid_for_stmt_type 1261 +#define invalid_def_raw_type 1262 +#define invalid_class_def_raw_type 1263 +#define invalid_double_starred_kvpairs_type 1264 +#define invalid_kvpair_unpacking_type 1265 +#define invalid_kvpair_type 1266 +#define invalid_starred_expression_unpacking_type 1267 +#define invalid_starred_expression_unpacking_sequence_type 1268 +#define invalid_starred_expression_type 1269 +#define invalid_fstring_replacement_field_type 1270 +#define invalid_fstring_conversion_character_type 1271 +#define invalid_tstring_replacement_field_type 1272 +#define invalid_tstring_conversion_character_type 1273 +#define invalid_string_tstring_concat_type 1274 +#define invalid_arithmetic_type 1275 // Left-recursive +#define invalid_factor_type 1276 +#define invalid_type_params_type 1277 +#define invalid_bitwise_and_type 1278 // Left-recursive +#define invalid_bitwise_or_type 1279 // Left-recursive +#define _loop0_1_type 1280 +#define _loop1_2_type 1281 +#define _loop0_3_type 1282 +#define _gather_4_type 1283 +#define _tmp_5_type 1284 +#define _tmp_6_type 1285 +#define _tmp_7_type 1286 +#define _tmp_8_type 1287 +#define _tmp_9_type 1288 +#define _tmp_10_type 1289 +#define _tmp_11_type 1290 +#define _loop1_12_type 1291 +#define _loop0_13_type 1292 +#define _gather_14_type 1293 +#define _tmp_15_type 1294 +#define _tmp_16_type 1295 +#define _loop0_17_type 1296 +#define _loop1_18_type 1297 +#define _loop0_19_type 1298 +#define _gather_20_type 1299 +#define _tmp_21_type 1300 +#define _loop0_22_type 1301 +#define _gather_23_type 1302 +#define _loop1_24_type 1303 +#define _tmp_25_type 1304 +#define _tmp_26_type 1305 +#define _loop0_27_type 1306 +#define _loop0_28_type 1307 +#define _loop1_29_type 1308 +#define _loop1_30_type 1309 +#define _loop0_31_type 1310 +#define _loop1_32_type 1311 +#define _loop0_33_type 1312 +#define _gather_34_type 1313 +#define _tmp_35_type 1314 +#define _loop1_36_type 1315 +#define _loop1_37_type 1316 +#define _loop1_38_type 1317 +#define _loop0_39_type 1318 +#define _gather_40_type 1319 +#define _tmp_41_type 1320 +#define _tmp_42_type 1321 +#define _tmp_43_type 1322 +#define _loop0_44_type 1323 +#define _gather_45_type 1324 +#define _loop0_46_type 1325 +#define _gather_47_type 1326 +#define _tmp_48_type 1327 +#define _loop0_49_type 1328 +#define _gather_50_type 1329 +#define _loop0_51_type 1330 +#define _gather_52_type 1331 +#define _loop0_53_type 1332 +#define _gather_54_type 1333 +#define _loop1_55_type 1334 +#define _loop1_56_type 1335 +#define _loop0_57_type 1336 +#define _gather_58_type 1337 +#define _loop0_59_type 1338 +#define _gather_60_type 1339 +#define _loop1_61_type 1340 +#define _loop1_62_type 1341 +#define _loop1_63_type 1342 +#define _tmp_64_type 1343 +#define _loop0_65_type 1344 +#define _gather_66_type 1345 +#define _tmp_67_type 1346 +#define _tmp_68_type 1347 +#define _tmp_69_type 1348 +#define _tmp_70_type 1349 +#define _tmp_71_type 1350 +#define _loop0_72_type 1351 +#define _loop0_73_type 1352 +#define _loop1_74_type 1353 +#define _loop1_75_type 1354 +#define _loop0_76_type 1355 +#define _loop1_77_type 1356 +#define _loop0_78_type 1357 +#define _loop0_79_type 1358 +#define _loop0_80_type 1359 +#define _loop0_81_type 1360 +#define _loop1_82_type 1361 +#define _loop1_83_type 1362 +#define _tmp_84_type 1363 +#define _loop0_85_type 1364 +#define _gather_86_type 1365 +#define _loop1_87_type 1366 +#define _loop0_88_type 1367 +#define _tmp_89_type 1368 +#define _loop0_90_type 1369 +#define _gather_91_type 1370 +#define _tmp_92_type 1371 +#define _loop0_93_type 1372 +#define _gather_94_type 1373 +#define _loop0_95_type 1374 +#define _gather_96_type 1375 +#define _loop0_97_type 1376 +#define _loop0_98_type 1377 +#define _gather_99_type 1378 +#define _loop1_100_type 1379 +#define _tmp_101_type 1380 +#define _loop0_102_type 1381 +#define _gather_103_type 1382 +#define _loop0_104_type 1383 +#define _gather_105_type 1384 +#define _tmp_106_type 1385 +#define _tmp_107_type 1386 +#define _loop0_108_type 1387 +#define _gather_109_type 1388 +#define _tmp_110_type 1389 +#define _tmp_111_type 1390 +#define _tmp_112_type 1391 +#define _tmp_113_type 1392 +#define _tmp_114_type 1393 +#define _loop1_115_type 1394 +#define _tmp_116_type 1395 +#define _tmp_117_type 1396 +#define _tmp_118_type 1397 +#define _tmp_119_type 1398 +#define _tmp_120_type 1399 +#define _loop0_121_type 1400 +#define _loop0_122_type 1401 +#define _tmp_123_type 1402 +#define _tmp_124_type 1403 +#define _tmp_125_type 1404 +#define _tmp_126_type 1405 +#define _tmp_127_type 1406 +#define _tmp_128_type 1407 +#define _tmp_129_type 1408 +#define _tmp_130_type 1409 +#define _loop0_131_type 1410 +#define _gather_132_type 1411 +#define _tmp_133_type 1412 +#define _tmp_134_type 1413 +#define _tmp_135_type 1414 +#define _tmp_136_type 1415 +#define _loop0_137_type 1416 +#define _gather_138_type 1417 +#define _tmp_139_type 1418 +#define _loop0_140_type 1419 +#define _gather_141_type 1420 +#define _loop0_142_type 1421 +#define _gather_143_type 1422 +#define _tmp_144_type 1423 +#define _loop0_145_type 1424 +#define _tmp_146_type 1425 +#define _tmp_147_type 1426 +#define _tmp_148_type 1427 +#define _tmp_149_type 1428 +#define _tmp_150_type 1429 +#define _tmp_151_type 1430 +#define _tmp_152_type 1431 +#define _tmp_153_type 1432 +#define _tmp_154_type 1433 +#define _tmp_155_type 1434 +#define _tmp_156_type 1435 +#define _tmp_157_type 1436 +#define _tmp_158_type 1437 +#define _tmp_159_type 1438 +#define _tmp_160_type 1439 +#define _tmp_161_type 1440 +#define _tmp_162_type 1441 +#define _tmp_163_type 1442 +#define _tmp_164_type 1443 +#define _tmp_165_type 1444 +#define _tmp_166_type 1445 +#define _tmp_167_type 1446 +#define _tmp_168_type 1447 +#define _tmp_169_type 1448 +#define _tmp_170_type 1449 +#define _tmp_171_type 1450 +#define _tmp_172_type 1451 +#define _tmp_173_type 1452 +#define _loop0_174_type 1453 +#define _tmp_175_type 1454 +#define _tmp_176_type 1455 +#define _tmp_177_type 1456 +#define _tmp_178_type 1457 +#define _tmp_179_type 1458 +#define _tmp_180_type 1459 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -652,6 +653,8 @@ static asdl_type_param_seq* type_params_rule(Parser *p); static asdl_type_param_seq* type_param_seq_rule(Parser *p); static type_param_ty type_param_rule(Parser *p); static expr_ty type_param_bound_rule(Parser *p); +static expr_ty type_param_starred_bound_rule(Parser *p); +static expr_ty type_param_paramspec_bound_rule(Parser *p); static expr_ty type_param_default_rule(Parser *p); static expr_ty type_param_starred_default_rule(Parser *p); static expr_ty expressions_rule(Parser *p); @@ -758,7 +761,6 @@ static void *invalid_arguments_rule(Parser *p); static void *invalid_kwarg_rule(Parser *p); static expr_ty expression_without_invalid_rule(Parser *p); static void *invalid_legacy_expression_rule(Parser *p); -static void *invalid_type_param_rule(Parser *p); static void *invalid_expression_rule(Parser *p); static void *invalid_if_expression_rule(Parser *p); static void *invalid_named_expression_rule(Parser *p); @@ -11115,9 +11117,8 @@ type_param_seq_rule(Parser *p) // type_param: // | NAME type_param_bound? type_param_default? -// | invalid_type_param -// | '*' NAME type_param_starred_default? -// | '**' NAME type_param_default? +// | '*' NAME type_param_starred_bound? type_param_starred_default? +// | '**' NAME type_param_paramspec_bound? type_param_default? static type_param_ty type_param_rule(Parser *p) { @@ -11182,43 +11183,27 @@ type_param_rule(Parser *p) D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME type_param_bound? type_param_default?")); } - if (p->call_invalid_rules) { // invalid_type_param + { // '*' NAME type_param_starred_bound? type_param_starred_default? if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_type_param")); - void *invalid_type_param_var; - if ( - (invalid_type_param_var = invalid_type_param_rule(p)) // invalid_type_param - ) - { - D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_type_param")); - _res = invalid_type_param_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_type_param")); - } - { // '*' NAME type_param_starred_default? - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME type_param_starred_default?")); + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME type_param_starred_bound? type_param_starred_default?")); Token * _literal; expr_ty a; void *b; + void *c; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && (a = _PyPegen_name_token(p)) // NAME && - (b = type_param_starred_default_rule(p), !p->error_indicator) // type_param_starred_default? + (b = type_param_starred_bound_rule(p), !p->error_indicator) // type_param_starred_bound? + && + (c = type_param_starred_default_rule(p), !p->error_indicator) // type_param_starred_default? ) { - D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME type_param_starred_default?")); + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME type_param_starred_bound? type_param_starred_default?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -11228,7 +11213,7 @@ type_param_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_TypeVarTuple ( a -> v . Name . id , b , EXTRA ); + _res = _PyAST_TypeVarTuple ( a -> v . Name . id , b , c , EXTRA ); if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -11238,26 +11223,29 @@ type_param_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME type_param_starred_default?")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME type_param_starred_bound? type_param_starred_default?")); } - { // '**' NAME type_param_default? + { // '**' NAME type_param_paramspec_bound? type_param_default? if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME type_param_default?")); + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME type_param_paramspec_bound? type_param_default?")); Token * _literal; expr_ty a; void *b; + void *c; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' && (a = _PyPegen_name_token(p)) // NAME && - (b = type_param_default_rule(p), !p->error_indicator) // type_param_default? + (b = type_param_paramspec_bound_rule(p), !p->error_indicator) // type_param_paramspec_bound? + && + (c = type_param_default_rule(p), !p->error_indicator) // type_param_default? ) { - D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME type_param_default?")); + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME type_param_paramspec_bound? type_param_default?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -11267,7 +11255,7 @@ type_param_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_ParamSpec ( a -> v . Name . id , b , EXTRA ); + _res = _PyAST_ParamSpec ( a -> v . Name . id , b , c , EXTRA ); if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -11277,7 +11265,7 @@ type_param_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME type_param_default?")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME type_param_paramspec_bound? type_param_default?")); } _res = NULL; done: @@ -11332,6 +11320,98 @@ type_param_bound_rule(Parser *p) return _res; } +// type_param_starred_bound: ':' star_expression +static expr_ty +type_param_starred_bound_rule(Parser *p) +{ + if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + expr_ty _res = NULL; + int _mark = p->mark; + { // ':' star_expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param_starred_bound[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' star_expression")); + Token * _literal; + expr_ty e; + if ( + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + && + (e = star_expression_rule(p)) // star_expression + ) + { + D(fprintf(stderr, "%*c+ type_param_starred_bound[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' star_expression")); + _res = CHECK_VERSION ( expr_ty , 16 , "Type variable tuple bounds are" , e ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param_starred_bound[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' star_expression")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// type_param_paramspec_bound: ':' expression +static expr_ty +type_param_paramspec_bound_rule(Parser *p) +{ + if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + expr_ty _res = NULL; + int _mark = p->mark; + { // ':' expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param_paramspec_bound[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression")); + Token * _literal; + expr_ty e; + if ( + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + && + (e = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ type_param_paramspec_bound[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression")); + _res = CHECK_VERSION ( expr_ty , 16 , "Parameter specification bounds are" , e ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param_paramspec_bound[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression")); + } + _res = NULL; + done: + p->level--; + return _res; +} + // type_param_default: '=' expression static expr_ty type_param_default_rule(Parser *p) @@ -21631,91 +21711,6 @@ invalid_legacy_expression_rule(Parser *p) return _res; } -// invalid_type_param: '*' NAME ':' expression | '**' NAME ':' expression -static void * -invalid_type_param_rule(Parser *p) -{ - if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '*' NAME ':' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> invalid_type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME ':' expression")); - Token * _literal; - expr_ty a; - Token * colon; - expr_ty e; - if ( - (_literal = _PyPegen_expect_token(p, 16)) // token='*' - && - (a = _PyPegen_name_token(p)) // NAME - && - (colon = _PyPegen_expect_token(p, 11)) // token=':' - && - (e = expression_rule(p)) // expression - ) - { - D(fprintf(stderr, "%*c+ invalid_type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME ':' expression")); - _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with TypeVarTuple" : "cannot use bound with TypeVarTuple" ); - if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME ':' expression")); - } - { // '**' NAME ':' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> invalid_type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME ':' expression")); - Token * _literal; - expr_ty a; - Token * colon; - expr_ty e; - if ( - (_literal = _PyPegen_expect_token(p, 35)) // token='**' - && - (a = _PyPegen_name_token(p)) // NAME - && - (colon = _PyPegen_expect_token(p, 11)) // token=':' - && - (e = expression_rule(p)) // expression - ) - { - D(fprintf(stderr, "%*c+ invalid_type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME ':' expression")); - _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with ParamSpec" : "cannot use bound with ParamSpec" ); - if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME ':' expression")); - } - _res = NULL; - done: - p->level--; - return _res; -} - // invalid_expression: // | STRING ((!STRING expression_without_invalid))+ STRING // | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f36072dfce098c6..b2b7f827d96b516 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -810,10 +810,12 @@ static const char * const TypeVar_fields[]={ }; static const char * const ParamSpec_fields[]={ "name", + "bound", "default_value", }; static const char * const TypeVarTuple_fields[]={ "name", + "bound", "default_value", }; @@ -5085,6 +5087,21 @@ add_ast_annotations(struct ast_state *state) return 0; } } + { + PyObject *type = state->expr_type; + type = _Py_union_type_or(type, Py_None); + cond = type != NULL; + if (!cond) { + Py_DECREF(ParamSpec_annotations); + return 0; + } + cond = PyDict_SetItemString(ParamSpec_annotations, "bound", type) == 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(ParamSpec_annotations); + return 0; + } + } { PyObject *type = state->expr_type; type = _Py_union_type_or(type, Py_None); @@ -5127,6 +5144,22 @@ add_ast_annotations(struct ast_state *state) return 0; } } + { + PyObject *type = state->expr_type; + type = _Py_union_type_or(type, Py_None); + cond = type != NULL; + if (!cond) { + Py_DECREF(TypeVarTuple_annotations); + return 0; + } + cond = PyDict_SetItemString(TypeVarTuple_annotations, "bound", type) == + 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(TypeVarTuple_annotations); + return 0; + } + } { PyObject *type = state->expr_type; type = _Py_union_type_or(type, Py_None); @@ -6918,8 +6951,8 @@ init_types(void *arg) state->type_param_type = make_type(state, "type_param", state->AST_type, NULL, 0, "type_param = TypeVar(identifier name, expr? bound, expr? default_value)\n" - " | ParamSpec(identifier name, expr? default_value)\n" - " | TypeVarTuple(identifier name, expr? default_value)"); + " | ParamSpec(identifier name, expr? bound, expr? default_value)\n" + " | TypeVarTuple(identifier name, expr? bound, expr? default_value)"); if (!state->type_param_type) return -1; if (add_attributes(state, state->type_param_type, type_param_attributes, 4) < 0) return -1; @@ -6935,17 +6968,21 @@ init_types(void *arg) return -1; state->ParamSpec_type = make_type(state, "ParamSpec", state->type_param_type, ParamSpec_fields, - 2, - "ParamSpec(identifier name, expr? default_value)"); + 3, + "ParamSpec(identifier name, expr? bound, expr? default_value)"); if (!state->ParamSpec_type) return -1; + if (PyObject_SetAttr(state->ParamSpec_type, state->bound, Py_None) == -1) + return -1; if (PyObject_SetAttr(state->ParamSpec_type, state->default_value, Py_None) == -1) return -1; state->TypeVarTuple_type = make_type(state, "TypeVarTuple", state->type_param_type, - TypeVarTuple_fields, 2, - "TypeVarTuple(identifier name, expr? default_value)"); + TypeVarTuple_fields, 3, + "TypeVarTuple(identifier name, expr? bound, expr? default_value)"); if (!state->TypeVarTuple_type) return -1; + if (PyObject_SetAttr(state->TypeVarTuple_type, state->bound, Py_None) == -1) + return -1; if (PyObject_SetAttr(state->TypeVarTuple_type, state->default_value, Py_None) == -1) return -1; @@ -8818,8 +8855,9 @@ _PyAST_TypeVar(identifier name, expr_ty bound, expr_ty default_value, int } type_param_ty -_PyAST_ParamSpec(identifier name, expr_ty default_value, int lineno, int - col_offset, int end_lineno, int end_col_offset, PyArena *arena) +_PyAST_ParamSpec(identifier name, expr_ty bound, expr_ty default_value, int + lineno, int col_offset, int end_lineno, int end_col_offset, + PyArena *arena) { type_param_ty p; if (!name) { @@ -8832,6 +8870,7 @@ _PyAST_ParamSpec(identifier name, expr_ty default_value, int lineno, int return NULL; p->kind = ParamSpec_kind; p->v.ParamSpec.name = name; + p->v.ParamSpec.bound = bound; p->v.ParamSpec.default_value = default_value; p->lineno = lineno; p->col_offset = col_offset; @@ -8841,9 +8880,9 @@ _PyAST_ParamSpec(identifier name, expr_ty default_value, int lineno, int } type_param_ty -_PyAST_TypeVarTuple(identifier name, expr_ty default_value, int lineno, int - col_offset, int end_lineno, int end_col_offset, PyArena - *arena) +_PyAST_TypeVarTuple(identifier name, expr_ty bound, expr_ty default_value, int + lineno, int col_offset, int end_lineno, int end_col_offset, + PyArena *arena) { type_param_ty p; if (!name) { @@ -8856,6 +8895,7 @@ _PyAST_TypeVarTuple(identifier name, expr_ty default_value, int lineno, int return NULL; p->kind = TypeVarTuple_kind; p->v.TypeVarTuple.name = name; + p->v.TypeVarTuple.bound = bound; p->v.TypeVarTuple.default_value = default_value; p->lineno = lineno; p->col_offset = col_offset; @@ -10814,6 +10854,11 @@ ast2obj_type_param(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_expr(state, o->v.ParamSpec.bound); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->bound, value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_expr(state, o->v.ParamSpec.default_value); if (!value) goto failed; if (PyObject_SetAttr(result, state->default_value, value) == -1) @@ -10829,6 +10874,11 @@ ast2obj_type_param(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_expr(state, o->v.TypeVarTuple.bound); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->bound, value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_expr(state, o->v.TypeVarTuple.default_value); if (!value) goto failed; if (PyObject_SetAttr(result, state->default_value, value) == -1) @@ -17980,6 +18030,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, } if (isinstance) { identifier name; + expr_ty bound; expr_ty default_value; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { @@ -17999,6 +18050,23 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (res != 0) goto failed; Py_CLEAR(tmp); } + if (PyObject_GetOptionalAttr(obj, state->bound, &tmp) < 0) { + return -1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + bound = NULL; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'ParamSpec' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &bound, "bound", arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } if (PyObject_GetOptionalAttr(obj, state->default_value, &tmp) < 0) { return -1; } @@ -18017,7 +18085,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (res != 0) goto failed; Py_CLEAR(tmp); } - *out = _PyAST_ParamSpec(name, default_value, lineno, col_offset, + *out = _PyAST_ParamSpec(name, bound, default_value, lineno, col_offset, end_lineno, end_col_offset, arena); if (*out == NULL) goto failed; return 0; @@ -18029,6 +18097,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, } if (isinstance) { identifier name; + expr_ty bound; expr_ty default_value; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { @@ -18048,6 +18117,23 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (res != 0) goto failed; Py_CLEAR(tmp); } + if (PyObject_GetOptionalAttr(obj, state->bound, &tmp) < 0) { + return -1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + bound = NULL; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'TypeVarTuple' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &bound, "bound", arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } if (PyObject_GetOptionalAttr(obj, state->default_value, &tmp) < 0) { return -1; } @@ -18066,8 +18152,9 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (res != 0) goto failed; Py_CLEAR(tmp); } - *out = _PyAST_TypeVarTuple(name, default_value, lineno, col_offset, - end_lineno, end_col_offset, arena); + *out = _PyAST_TypeVarTuple(name, bound, default_value, lineno, + col_offset, end_lineno, end_col_offset, + arena); if (*out == NULL) goto failed; return 0; } diff --git a/Python/ast.c b/Python/ast.c index 4cfa2ff559a5f7d..9e2e5abebd366b5 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1019,11 +1019,15 @@ validate_typeparam(type_param_ty tp) break; case ParamSpec_kind: ret = validate_name(tp->v.ParamSpec.name) && + (!tp->v.ParamSpec.bound || + validate_expr(tp->v.ParamSpec.bound, Load)) && (!tp->v.ParamSpec.default_value || validate_expr(tp->v.ParamSpec.default_value, Load)); break; case TypeVarTuple_kind: ret = validate_name(tp->v.TypeVarTuple.name) && + (!tp->v.TypeVarTuple.bound || + validate_expr(tp->v.TypeVarTuple.bound, Load)) && (!tp->v.TypeVarTuple.default_value || validate_expr(tp->v.TypeVarTuple.default_value, Load)); break; diff --git a/Python/ast_preprocess.c b/Python/ast_preprocess.c index 54dec3dfe042686..f4e8c5eac516b1b 100644 --- a/Python/ast_preprocess.c +++ b/Python/ast_preprocess.c @@ -958,9 +958,11 @@ astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTPreprocessState *st CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.default_value); break; case ParamSpec_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.ParamSpec.bound); CALL_OPT(astfold_expr, expr_ty, node_->v.ParamSpec.default_value); break; case TypeVarTuple_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVarTuple.bound); CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVarTuple.default_value); break; } diff --git a/Python/codegen.c b/Python/codegen.c index bedf3b17c52ce44..86094eb095eb5d8 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -1337,12 +1337,21 @@ codegen_type_params(compiler *c, asdl_type_param_seq *type_params) break; case TypeVarTuple_kind: ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVarTuple.name); - ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVARTUPLE); + if (typeparam->v.TypeVarTuple.bound) { + expr_ty bound = typeparam->v.TypeVarTuple.bound; + RETURN_IF_ERROR( + codegen_type_param_bound_or_default(c, bound, typeparam->v.TypeVarTuple.name, + (void *)typeparam, true)); + ADDOP_I(c, loc, CALL_INTRINSIC_2, INTRINSIC_TYPEVARTUPLE_WITH_BOUND); + } + else { + ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVARTUPLE); + } if (typeparam->v.TypeVarTuple.default_value) { expr_ty default_ = typeparam->v.TypeVarTuple.default_value; RETURN_IF_ERROR( codegen_type_param_bound_or_default(c, default_, typeparam->v.TypeVarTuple.name, - (void *)typeparam, true)); + (void *)((uintptr_t)typeparam + 1), true)); ADDOP_I(c, loc, CALL_INTRINSIC_2, INTRINSIC_SET_TYPEPARAM_DEFAULT); seen_default = true; } @@ -1356,12 +1365,21 @@ codegen_type_params(compiler *c, asdl_type_param_seq *type_params) break; case ParamSpec_kind: ADDOP_LOAD_CONST(c, loc, typeparam->v.ParamSpec.name); - ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PARAMSPEC); + if (typeparam->v.ParamSpec.bound) { + expr_ty bound = typeparam->v.ParamSpec.bound; + RETURN_IF_ERROR( + codegen_type_param_bound_or_default(c, bound, typeparam->v.ParamSpec.name, + (void *)typeparam, false)); + ADDOP_I(c, loc, CALL_INTRINSIC_2, INTRINSIC_PARAMSPEC_WITH_BOUND); + } + else { + ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PARAMSPEC); + } if (typeparam->v.ParamSpec.default_value) { expr_ty default_ = typeparam->v.ParamSpec.default_value; RETURN_IF_ERROR( codegen_type_param_bound_or_default(c, default_, typeparam->v.ParamSpec.name, - (void *)typeparam, false)); + (void *)((uintptr_t)typeparam + 1), false)); ADDOP_I(c, loc, CALL_INTRINSIC_2, INTRINSIC_SET_TYPEPARAM_DEFAULT); seen_default = true; } diff --git a/Python/intrinsics.c b/Python/intrinsics.c index 52e2dc8a99d8640..d89ae6347e90430 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -270,6 +270,22 @@ make_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name, return _Py_make_typevar(name, NULL, evaluate_constraints); } +static PyObject * +make_typevartuple_with_bound(PyThreadState* Py_UNUSED(ignored), PyObject *name, + PyObject *evaluate_bound) +{ + assert(PyUnicode_Check(name)); + return _Py_make_typevartuple_with_bound(name, evaluate_bound); +} + +static PyObject * +make_paramspec_with_bound(PyThreadState* Py_UNUSED(ignored), PyObject *name, + PyObject *evaluate_bound) +{ + assert(PyUnicode_Check(name)); + return _Py_make_paramspec_with_bound(name, evaluate_bound); +} + static PyObject * add_conditional_annotation(PyThreadState* tstate, PyObject *conditional_annotations, PyObject *index) @@ -296,6 +312,8 @@ _PyIntrinsics_BinaryFunctions[] = { INTRINSIC_FUNC_ENTRY(INTRINSIC_SET_FUNCTION_TYPE_PARAMS, _Py_set_function_type_params) INTRINSIC_FUNC_ENTRY(INTRINSIC_SET_TYPEPARAM_DEFAULT, _Py_set_typeparam_default) INTRINSIC_FUNC_ENTRY(INTRINSIC_ADD_CONDITIONAL_ANNOTATION, add_conditional_annotation) + INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVARTUPLE_WITH_BOUND, make_typevartuple_with_bound) + INTRINSIC_FUNC_ENTRY(INTRINSIC_PARAMSPEC_WITH_BOUND, make_paramspec_with_bound) }; #undef INTRINSIC_FUNC_ENTRY diff --git a/Python/symtable.c b/Python/symtable.c index e3e89ab403a607e..551bbd98f4eddcd 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -2745,8 +2745,13 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp) return 0; } + if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVarTuple.bound, tp->v.TypeVarTuple.name, + tp, "a TypeVarTuple bound")) { + return 0; + } + if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVarTuple.default_value, tp->v.TypeVarTuple.name, - tp, "a TypeVarTuple default")) { + (type_param_ty)((uintptr_t)tp + 1), "a TypeVarTuple default")) { return 0; } break; @@ -2755,8 +2760,13 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp) return 0; } + if (!symtable_visit_type_param_bound_or_default(st, tp->v.ParamSpec.bound, tp->v.ParamSpec.name, + tp, "a ParamSpec bound")) { + return 0; + } + if (!symtable_visit_type_param_bound_or_default(st, tp->v.ParamSpec.default_value, tp->v.ParamSpec.name, - tp, "a ParamSpec default")) { + (type_param_ty)((uintptr_t)tp + 1), "a ParamSpec default")) { return 0; } break;