gh-103763: Implement PEP 695 (#103764)

This implements PEP 695, Type Parameter Syntax. It adds support for:

- Generic functions (def func[T](): ...)
- Generic classes (class X[T](): ...)
- Type aliases (type X = ...)
- New scoping when the new syntax is used within a class body
- Compiler and interpreter changes to support the new syntax and scoping rules 

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Co-authored-by: Eric Traut <eric@traut.com>
Co-authored-by: Larry Hastings <larry@hastings.org>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Jelle Zijlstra 2023-05-15 20:36:23 -07:00 committed by GitHub
parent fdafdc235e
commit 24d8b88420
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 11405 additions and 5469 deletions

View File

@ -1724,6 +1724,7 @@ Function and class definitions
body=[
FunctionDef(
name='f',
typeparams=[],
args=arguments(
posonlyargs=[],
args=[
@ -1847,6 +1848,7 @@ Function and class definitions
body=[
ClassDef(
name='Foo',
typeparams=[],
bases=[
Name(id='base1', ctx=Load()),
Name(id='base2', ctx=Load())],
@ -1885,6 +1887,7 @@ Async and await
body=[
AsyncFunctionDef(
name='f',
typeparams=[],
args=arguments(
posonlyargs=[],
args=[],

View File

@ -112,6 +112,7 @@ simple_stmts[asdl_stmt_seq*]:
# will throw a SyntaxError.
simple_stmt[stmt_ty] (memo):
| assignment
| &"type" type_alias
| e=star_expressions { _PyAST_Expr(e, EXTRA) }
| &'return' return_stmt
| &('import' | 'from') import_stmt
@ -252,8 +253,8 @@ class_def[stmt_ty]:
class_def_raw[stmt_ty]:
| invalid_class_def_raw
| 'class' a=NAME b=['(' z=[arguments] ')' { z }] ':' c=block {
_PyAST_ClassDef(a->v.Name.id,
| 'class' a=NAME t=[type_params] b=['(' z=[arguments] ')' { z }] ':' c=block {
_PyAST_ClassDef(a->v.Name.id, t,
(b) ? ((expr_ty) b)->v.Call.args : NULL,
(b) ? ((expr_ty) b)->v.Call.keywords : NULL,
c, NULL, EXTRA) }
@ -267,16 +268,16 @@ function_def[stmt_ty]:
function_def_raw[stmt_ty]:
| invalid_def_raw
| 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
_PyAST_FunctionDef(n->v.Name.id,
| 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
_PyAST_FunctionDef(n->v.Name.id, t,
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) }
| ASYNC 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
| ASYNC 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
CHECK_VERSION(
stmt_ty,
5,
"Async functions are",
_PyAST_AsyncFunctionDef(n->v.Name.id,
_PyAST_AsyncFunctionDef(n->v.Name.id, t,
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA)
) }
@ -628,6 +629,39 @@ keyword_patterns[asdl_seq*]:
keyword_pattern[KeyPatternPair*]:
| arg=NAME '=' value=pattern { _PyPegen_key_pattern_pair(p, arg, value) }
# Type statement
# ---------------
type_alias[stmt_ty]:
| "type" n=NAME t=[type_params] '=' b=expression {
CHECK_VERSION(stmt_ty, 12, "Type statement is",
_PyAST_TypeAlias(CHECK(expr_ty, _PyPegen_set_expr_context(p, n, Store)), t, b, EXTRA)) }
# Type parameter declaration
# --------------------------
type_params[asdl_typeparam_seq*]: '[' t=type_param_seq ']' {
CHECK_VERSION(asdl_typeparam_seq *, 12, "Type parameter lists are", t) }
type_param_seq[asdl_typeparam_seq*]: a[asdl_typeparam_seq*]=','.type_param+ [','] { a }
type_param[typeparam_ty] (memo):
| a=NAME b=[type_param_bound] { _PyAST_TypeVar(a->v.Name.id, b, EXTRA) }
| '*' 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 { _PyAST_TypeVarTuple(a->v.Name.id, EXTRA) }
| '**' 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")
}
| '**' a=NAME { _PyAST_ParamSpec(a->v.Name.id, EXTRA) }
type_param_bound[expr_ty]: ":" e=expression { e }
# EXPRESSIONS
# -----------

View File

@ -41,6 +41,7 @@ typedef struct {
PyObject *func_weakreflist; /* List of weak references */
PyObject *func_module; /* The __module__ attribute, can be anything */
PyObject *func_annotations; /* Annotations, a dict or NULL */
PyObject *func_typeparams; /* Tuple of active type variables or NULL */
vectorcallfunc vectorcall;
/* Version number for use by specializer.
* Can set to non-zero when we want to specialize.

View File

@ -51,6 +51,8 @@ typedef struct _pattern *pattern_ty;
typedef struct _type_ignore *type_ignore_ty;
typedef struct _typeparam *typeparam_ty;
typedef struct {
_ASDL_SEQ_HEAD
@ -147,6 +149,13 @@ typedef struct {
asdl_type_ignore_seq *_Py_asdl_type_ignore_seq_new(Py_ssize_t size, PyArena
*arena);
typedef struct {
_ASDL_SEQ_HEAD
typeparam_ty typed_elements[1];
} asdl_typeparam_seq;
asdl_typeparam_seq *_Py_asdl_typeparam_seq_new(Py_ssize_t size, PyArena *arena);
enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3,
FunctionType_kind=4};
@ -176,17 +185,19 @@ struct _mod {
enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3,
Return_kind=4, Delete_kind=5, Assign_kind=6,
AugAssign_kind=7, AnnAssign_kind=8, For_kind=9,
AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13,
AsyncWith_kind=14, Match_kind=15, Raise_kind=16, Try_kind=17,
TryStar_kind=18, Assert_kind=19, Import_kind=20,
ImportFrom_kind=21, Global_kind=22, Nonlocal_kind=23,
Expr_kind=24, Pass_kind=25, Break_kind=26, Continue_kind=27};
TypeAlias_kind=7, AugAssign_kind=8, AnnAssign_kind=9,
For_kind=10, AsyncFor_kind=11, While_kind=12, If_kind=13,
With_kind=14, AsyncWith_kind=15, Match_kind=16,
Raise_kind=17, Try_kind=18, TryStar_kind=19, Assert_kind=20,
Import_kind=21, ImportFrom_kind=22, Global_kind=23,
Nonlocal_kind=24, Expr_kind=25, Pass_kind=26, Break_kind=27,
Continue_kind=28};
struct _stmt {
enum _stmt_kind kind;
union {
struct {
identifier name;
asdl_typeparam_seq *typeparams;
arguments_ty args;
asdl_stmt_seq *body;
asdl_expr_seq *decorator_list;
@ -196,6 +207,7 @@ struct _stmt {
struct {
identifier name;
asdl_typeparam_seq *typeparams;
arguments_ty args;
asdl_stmt_seq *body;
asdl_expr_seq *decorator_list;
@ -205,6 +217,7 @@ struct _stmt {
struct {
identifier name;
asdl_typeparam_seq *typeparams;
asdl_expr_seq *bases;
asdl_keyword_seq *keywords;
asdl_stmt_seq *body;
@ -225,6 +238,12 @@ struct _stmt {
string type_comment;
} Assign;
struct {
expr_ty name;
asdl_typeparam_seq *typeparams;
expr_ty value;
} TypeAlias;
struct {
expr_ty target;
operator_ty op;
@ -630,6 +649,30 @@ struct _type_ignore {
} v;
};
enum _typeparam_kind {TypeVar_kind=1, ParamSpec_kind=2, TypeVarTuple_kind=3};
struct _typeparam {
enum _typeparam_kind kind;
union {
struct {
identifier name;
expr_ty bound;
} TypeVar;
struct {
identifier name;
} ParamSpec;
struct {
identifier name;
} TypeVarTuple;
} v;
int lineno;
int col_offset;
int end_lineno;
int end_col_offset;
};
// Note: these macros affect function definitions, not only call sites.
mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores,
@ -638,21 +681,22 @@ mod_ty _PyAST_Interactive(asdl_stmt_seq * body, PyArena *arena);
mod_ty _PyAST_Expression(expr_ty body, PyArena *arena);
mod_ty _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena
*arena);
stmt_ty _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq *
body, asdl_expr_seq * decorator_list, expr_ty
returns, string type_comment, int lineno, int
col_offset, int end_lineno, int end_col_offset,
PyArena *arena);
stmt_ty _PyAST_AsyncFunctionDef(identifier name, arguments_ty args,
asdl_stmt_seq * body, asdl_expr_seq *
decorator_list, expr_ty returns, string
type_comment, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
stmt_ty _PyAST_ClassDef(identifier name, asdl_expr_seq * bases,
asdl_keyword_seq * keywords, asdl_stmt_seq * body,
asdl_expr_seq * decorator_list, int lineno, int
col_offset, int end_lineno, int end_col_offset, PyArena
*arena);
stmt_ty _PyAST_FunctionDef(identifier name, asdl_typeparam_seq * typeparams,
arguments_ty args, asdl_stmt_seq * body,
asdl_expr_seq * decorator_list, expr_ty returns,
string type_comment, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
stmt_ty _PyAST_AsyncFunctionDef(identifier name, asdl_typeparam_seq *
typeparams, arguments_ty args, asdl_stmt_seq *
body, asdl_expr_seq * decorator_list, expr_ty
returns, string type_comment, int lineno, int
col_offset, int end_lineno, int end_col_offset,
PyArena *arena);
stmt_ty _PyAST_ClassDef(identifier name, asdl_typeparam_seq * typeparams,
asdl_expr_seq * bases, asdl_keyword_seq * keywords,
asdl_stmt_seq * body, asdl_expr_seq * decorator_list,
int lineno, int col_offset, int end_lineno, int
end_col_offset, PyArena *arena);
stmt_ty _PyAST_Return(expr_ty value, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int
@ -660,6 +704,9 @@ stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int
stmt_ty _PyAST_Assign(asdl_expr_seq * targets, expr_ty value, string
type_comment, int lineno, int col_offset, int end_lineno,
int end_col_offset, PyArena *arena);
stmt_ty _PyAST_TypeAlias(expr_ty name, asdl_typeparam_seq * typeparams, expr_ty
value, int lineno, int col_offset, int end_lineno, int
end_col_offset, PyArena *arena);
stmt_ty _PyAST_AugAssign(expr_ty target, operator_ty op, expr_ty value, int
lineno, int col_offset, int end_lineno, int
end_col_offset, PyArena *arena);
@ -844,6 +891,14 @@ pattern_ty _PyAST_MatchOr(asdl_pattern_seq * patterns, int lineno, int
col_offset, int end_lineno, int end_col_offset,
PyArena *arena);
type_ignore_ty _PyAST_TypeIgnore(int lineno, string tag, PyArena *arena);
typeparam_ty _PyAST_TypeVar(identifier name, expr_ty bound, int lineno, int
col_offset, int end_lineno, int end_col_offset,
PyArena *arena);
typeparam_ty _PyAST_ParamSpec(identifier name, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
typeparam_ty _PyAST_TypeVarTuple(identifier name, int lineno, int col_offset,
int end_lineno, int end_col_offset, PyArena
*arena);
PyObject* PyAST_mod2obj(mod_ty t);

View File

@ -118,6 +118,7 @@ struct ast_state {
PyObject *Not_type;
PyObject *Or_singleton;
PyObject *Or_type;
PyObject *ParamSpec_type;
PyObject *Pass_type;
PyObject *Pow_singleton;
PyObject *Pow_type;
@ -137,7 +138,10 @@ struct ast_state {
PyObject *TryStar_type;
PyObject *Try_type;
PyObject *Tuple_type;
PyObject *TypeAlias_type;
PyObject *TypeIgnore_type;
PyObject *TypeVarTuple_type;
PyObject *TypeVar_type;
PyObject *UAdd_singleton;
PyObject *UAdd_type;
PyObject *USub_singleton;
@ -166,6 +170,7 @@ struct ast_state {
PyObject *bases;
PyObject *body;
PyObject *boolop_type;
PyObject *bound;
PyObject *cases;
PyObject *cause;
PyObject *cls;
@ -243,6 +248,8 @@ struct ast_state {
PyObject *type_comment;
PyObject *type_ignore_type;
PyObject *type_ignores;
PyObject *typeparam_type;
PyObject *typeparams;
PyObject *unaryop_type;
PyObject *upper;
PyObject *value;

View File

@ -17,6 +17,8 @@ struct _py_func_state {
extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr);
extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func);
extern PyObject *_Py_set_function_type_params(
PyThreadState* unused, PyObject *func, PyObject *type_params);
#ifdef __cplusplus
}

View File

@ -68,6 +68,14 @@ struct _Py_interp_cached_objects {
PyObject *type_slots_pname;
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
/* TypeVar and related types */
PyTypeObject *generic_type;
PyTypeObject *typevar_type;
PyTypeObject *typevartuple_type;
PyTypeObject *paramspec_type;
PyTypeObject *paramspecargs_type;
PyTypeObject *paramspeckwargs_type;
PyTypeObject *typealias_type;
};
#define _Py_INTERP_STATIC_OBJECT(interp, NAME) \

View File

@ -555,15 +555,19 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_close_br));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_open_br));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_percent));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(defaults));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot_locals));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(empty));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(generic_base));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(json_decoder));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(kwdefaults));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(list_err));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(newline));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(open_br));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(percent));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(shim_name));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(type_params));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(utf_8));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(CANCELLED));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(FINISHED));
@ -602,6 +606,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__class__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__class_getitem__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classcell__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classdict__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classdictcell__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__complex__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__contains__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__copy__));
@ -724,6 +730,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__subclasshook__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__truediv__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__trunc__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__type_params__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_is_unpacked_typevartuple__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_prepare_subst__));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_subst__));
@ -779,8 +786,11 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_child));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_parent));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(aggregate_class));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alias));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(append));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arg));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argdefs));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(args));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arguments));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argv));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(as_integer_ratio));
@ -795,6 +805,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(big));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(binary_form));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(block));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(bound));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer_callback));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer_size));
@ -850,11 +861,13 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compile_mode));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(consts));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(context));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(contravariant));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cookie));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(copy));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(copyreg));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(coro));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(count));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(covariant));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cwd));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data));
@ -964,6 +977,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(incoming));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(indexgroup));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(inf));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(infer_variance));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(inheritable));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(initial));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(initial_bytes));
@ -1080,6 +1094,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(optimize));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(options));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(order));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(origin));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(out_fd));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(outgoing));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(overlapped));
@ -1213,6 +1228,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(twice));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(txt));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type_params));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tz));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tzname));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uid));

View File

@ -40,15 +40,19 @@ struct _Py_global_strings {
STRUCT_FOR_STR(dbl_close_br, "}}")
STRUCT_FOR_STR(dbl_open_br, "{{")
STRUCT_FOR_STR(dbl_percent, "%%")
STRUCT_FOR_STR(defaults, ".defaults")
STRUCT_FOR_STR(dot, ".")
STRUCT_FOR_STR(dot_locals, ".<locals>")
STRUCT_FOR_STR(empty, "")
STRUCT_FOR_STR(generic_base, ".generic_base")
STRUCT_FOR_STR(json_decoder, "json.decoder")
STRUCT_FOR_STR(kwdefaults, ".kwdefaults")
STRUCT_FOR_STR(list_err, "list index out of range")
STRUCT_FOR_STR(newline, "\n")
STRUCT_FOR_STR(open_br, "{")
STRUCT_FOR_STR(percent, "%")
STRUCT_FOR_STR(shim_name, "<shim>")
STRUCT_FOR_STR(type_params, ".type_params")
STRUCT_FOR_STR(utf_8, "utf-8")
} literals;
@ -90,6 +94,8 @@ struct _Py_global_strings {
STRUCT_FOR_ID(__class__)
STRUCT_FOR_ID(__class_getitem__)
STRUCT_FOR_ID(__classcell__)
STRUCT_FOR_ID(__classdict__)
STRUCT_FOR_ID(__classdictcell__)
STRUCT_FOR_ID(__complex__)
STRUCT_FOR_ID(__contains__)
STRUCT_FOR_ID(__copy__)
@ -212,6 +218,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(__subclasshook__)
STRUCT_FOR_ID(__truediv__)
STRUCT_FOR_ID(__trunc__)
STRUCT_FOR_ID(__type_params__)
STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__)
STRUCT_FOR_ID(__typing_prepare_subst__)
STRUCT_FOR_ID(__typing_subst__)
@ -267,8 +274,11 @@ struct _Py_global_strings {
STRUCT_FOR_ID(after_in_child)
STRUCT_FOR_ID(after_in_parent)
STRUCT_FOR_ID(aggregate_class)
STRUCT_FOR_ID(alias)
STRUCT_FOR_ID(append)
STRUCT_FOR_ID(arg)
STRUCT_FOR_ID(argdefs)
STRUCT_FOR_ID(args)
STRUCT_FOR_ID(arguments)
STRUCT_FOR_ID(argv)
STRUCT_FOR_ID(as_integer_ratio)
@ -283,6 +293,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(big)
STRUCT_FOR_ID(binary_form)
STRUCT_FOR_ID(block)
STRUCT_FOR_ID(bound)
STRUCT_FOR_ID(buffer)
STRUCT_FOR_ID(buffer_callback)
STRUCT_FOR_ID(buffer_size)
@ -338,11 +349,13 @@ struct _Py_global_strings {
STRUCT_FOR_ID(compile_mode)
STRUCT_FOR_ID(consts)
STRUCT_FOR_ID(context)
STRUCT_FOR_ID(contravariant)
STRUCT_FOR_ID(cookie)
STRUCT_FOR_ID(copy)
STRUCT_FOR_ID(copyreg)
STRUCT_FOR_ID(coro)
STRUCT_FOR_ID(count)
STRUCT_FOR_ID(covariant)
STRUCT_FOR_ID(cwd)
STRUCT_FOR_ID(d)
STRUCT_FOR_ID(data)
@ -452,6 +465,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(incoming)
STRUCT_FOR_ID(indexgroup)
STRUCT_FOR_ID(inf)
STRUCT_FOR_ID(infer_variance)
STRUCT_FOR_ID(inheritable)
STRUCT_FOR_ID(initial)
STRUCT_FOR_ID(initial_bytes)
@ -568,6 +582,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(optimize)
STRUCT_FOR_ID(options)
STRUCT_FOR_ID(order)
STRUCT_FOR_ID(origin)
STRUCT_FOR_ID(out_fd)
STRUCT_FOR_ID(outgoing)
STRUCT_FOR_ID(overlapped)
@ -701,6 +716,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(twice)
STRUCT_FOR_ID(txt)
STRUCT_FOR_ID(type)
STRUCT_FOR_ID(type_params)
STRUCT_FOR_ID(tz)
STRUCT_FOR_ID(tzname)
STRUCT_FOR_ID(uid)

View File

@ -8,15 +8,23 @@
#define INTRINSIC_ASYNC_GEN_WRAP 4
#define INTRINSIC_UNARY_POSITIVE 5
#define INTRINSIC_LIST_TO_TUPLE 6
#define INTRINSIC_TYPEVAR 7
#define INTRINSIC_PARAMSPEC 8
#define INTRINSIC_TYPEVARTUPLE 9
#define INTRINSIC_SUBSCRIPT_GENERIC 10
#define INTRINSIC_TYPEALIAS 11
#define MAX_INTRINSIC_1 6
#define MAX_INTRINSIC_1 11
/* Binary Functions: */
#define INTRINSIC_2_INVALID 0
#define INTRINSIC_PREP_RERAISE_STAR 1
#define INTRINSIC_TYPEVAR_WITH_BOUND 2
#define INTRINSIC_TYPEVAR_WITH_CONSTRAINTS 3
#define INTRINSIC_SET_FUNCTION_TYPE_PARAMS 4
#define MAX_INTRINSIC_2 1
#define MAX_INTRINSIC_2 4
typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);

View File

@ -167,7 +167,6 @@ const uint8_t _PyOpcode_Deopt[256] = {
[LOAD_ATTR_SLOT] = LOAD_ATTR,
[LOAD_ATTR_WITH_HINT] = LOAD_ATTR,
[LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS,
[LOAD_CLASSDEREF] = LOAD_CLASSDEREF,
[LOAD_CLOSURE] = LOAD_CLOSURE,
[LOAD_CONST] = LOAD_CONST,
[LOAD_CONST__LOAD_FAST] = LOAD_CONST,
@ -177,9 +176,12 @@ const uint8_t _PyOpcode_Deopt[256] = {
[LOAD_FAST_CHECK] = LOAD_FAST_CHECK,
[LOAD_FAST__LOAD_CONST] = LOAD_FAST,
[LOAD_FAST__LOAD_FAST] = LOAD_FAST,
[LOAD_FROM_DICT_OR_DEREF] = LOAD_FROM_DICT_OR_DEREF,
[LOAD_FROM_DICT_OR_GLOBALS] = LOAD_FROM_DICT_OR_GLOBALS,
[LOAD_GLOBAL] = LOAD_GLOBAL,
[LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL,
[LOAD_GLOBAL_MODULE] = LOAD_GLOBAL,
[LOAD_LOCALS] = LOAD_LOCALS,
[LOAD_NAME] = LOAD_NAME,
[LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,
[LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR,
@ -329,8 +331,8 @@ static const char *const _PyOpcode_OpName[267] = {
[LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST",
[SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS",
[LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST",
[LOAD_LOCALS] = "LOAD_LOCALS",
[LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST",
[LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN",
[POP_EXCEPT] = "POP_EXCEPT",
[STORE_NAME] = "STORE_NAME",
[DELETE_NAME] = "DELETE_NAME",
@ -353,9 +355,9 @@ static const char *const _PyOpcode_OpName[267] = {
[IMPORT_NAME] = "IMPORT_NAME",
[IMPORT_FROM] = "IMPORT_FROM",
[JUMP_FORWARD] = "JUMP_FORWARD",
[LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN",
[LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE",
[STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE",
[STORE_ATTR_SLOT] = "STORE_ATTR_SLOT",
[POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE",
[POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE",
[LOAD_GLOBAL] = "LOAD_GLOBAL",
@ -390,7 +392,7 @@ static const char *const _PyOpcode_OpName[267] = {
[LIST_APPEND] = "LIST_APPEND",
[SET_ADD] = "SET_ADD",
[MAP_ADD] = "MAP_ADD",
[LOAD_CLASSDEREF] = "LOAD_CLASSDEREF",
[STORE_ATTR_SLOT] = "STORE_ATTR_SLOT",
[COPY_FREE_VARS] = "COPY_FREE_VARS",
[YIELD_VALUE] = "YIELD_VALUE",
[RESUME] = "RESUME",
@ -417,8 +419,8 @@ static const char *const _PyOpcode_OpName[267] = {
[KW_NAMES] = "KW_NAMES",
[CALL_INTRINSIC_1] = "CALL_INTRINSIC_1",
[CALL_INTRINSIC_2] = "CALL_INTRINSIC_2",
[175] = "<175>",
[176] = "<176>",
[LOAD_FROM_DICT_OR_GLOBALS] = "LOAD_FROM_DICT_OR_GLOBALS",
[LOAD_FROM_DICT_OR_DEREF] = "LOAD_FROM_DICT_OR_DEREF",
[177] = "<177>",
[178] = "<178>",
[179] = "<179>",
@ -515,8 +517,6 @@ static const char *const _PyOpcode_OpName[267] = {
#define EXTRA_CASES \
case 169: \
case 170: \
case 175: \
case 176: \
case 177: \
case 178: \
case 179: \

View File

@ -546,15 +546,19 @@ extern "C" {
INIT_STR(dbl_close_br, "}}"), \
INIT_STR(dbl_open_br, "{{"), \
INIT_STR(dbl_percent, "%%"), \
INIT_STR(defaults, ".defaults"), \
INIT_STR(dot, "."), \
INIT_STR(dot_locals, ".<locals>"), \
INIT_STR(empty, ""), \
INIT_STR(generic_base, ".generic_base"), \
INIT_STR(json_decoder, "json.decoder"), \
INIT_STR(kwdefaults, ".kwdefaults"), \
INIT_STR(list_err, "list index out of range"), \
INIT_STR(newline, "\n"), \
INIT_STR(open_br, "{"), \
INIT_STR(percent, "%"), \
INIT_STR(shim_name, "<shim>"), \
INIT_STR(type_params, ".type_params"), \
INIT_STR(utf_8, "utf-8"), \
}
@ -596,6 +600,8 @@ extern "C" {
INIT_ID(__class__), \
INIT_ID(__class_getitem__), \
INIT_ID(__classcell__), \
INIT_ID(__classdict__), \
INIT_ID(__classdictcell__), \
INIT_ID(__complex__), \
INIT_ID(__contains__), \
INIT_ID(__copy__), \
@ -718,6 +724,7 @@ extern "C" {
INIT_ID(__subclasshook__), \
INIT_ID(__truediv__), \
INIT_ID(__trunc__), \
INIT_ID(__type_params__), \
INIT_ID(__typing_is_unpacked_typevartuple__), \
INIT_ID(__typing_prepare_subst__), \
INIT_ID(__typing_subst__), \
@ -773,8 +780,11 @@ extern "C" {
INIT_ID(after_in_child), \
INIT_ID(after_in_parent), \
INIT_ID(aggregate_class), \
INIT_ID(alias), \
INIT_ID(append), \
INIT_ID(arg), \
INIT_ID(argdefs), \
INIT_ID(args), \
INIT_ID(arguments), \
INIT_ID(argv), \
INIT_ID(as_integer_ratio), \
@ -789,6 +799,7 @@ extern "C" {
INIT_ID(big), \
INIT_ID(binary_form), \
INIT_ID(block), \
INIT_ID(bound), \
INIT_ID(buffer), \
INIT_ID(buffer_callback), \
INIT_ID(buffer_size), \
@ -844,11 +855,13 @@ extern "C" {
INIT_ID(compile_mode), \
INIT_ID(consts), \
INIT_ID(context), \
INIT_ID(contravariant), \
INIT_ID(cookie), \
INIT_ID(copy), \
INIT_ID(copyreg), \
INIT_ID(coro), \
INIT_ID(count), \
INIT_ID(covariant), \
INIT_ID(cwd), \
INIT_ID(d), \
INIT_ID(data), \
@ -958,6 +971,7 @@ extern "C" {
INIT_ID(incoming), \
INIT_ID(indexgroup), \
INIT_ID(inf), \
INIT_ID(infer_variance), \
INIT_ID(inheritable), \
INIT_ID(initial), \
INIT_ID(initial_bytes), \
@ -1074,6 +1088,7 @@ extern "C" {
INIT_ID(optimize), \
INIT_ID(options), \
INIT_ID(order), \
INIT_ID(origin), \
INIT_ID(out_fd), \
INIT_ID(outgoing), \
INIT_ID(overlapped), \
@ -1207,6 +1222,7 @@ extern "C" {
INIT_ID(twice), \
INIT_ID(txt), \
INIT_ID(type), \
INIT_ID(type_params), \
INIT_ID(tz), \
INIT_ID(tzname), \
INIT_ID(uid), \

View File

@ -10,8 +10,17 @@ extern "C" {
struct _mod; // Type defined in pycore_ast.h
typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock }
_Py_block_ty;
typedef enum _block_type {
FunctionBlock, ClassBlock, ModuleBlock,
// Used for annotations if 'from __future__ import annotations' is active.
// Annotation blocks cannot bind names and are not evaluated.
AnnotationBlock,
// Used for generics and type aliases. These work mostly like functions
// (see PEP 695 for details). The three different blocks function identically;
// they are different enum entries only so that error messages can be more
// precise.
TypeVarBoundBlock, TypeAliasBlock, TypeParamBlock
} _Py_block_ty;
typedef enum _comprehension_type {
NoComprehension = 0,
@ -49,7 +58,7 @@ typedef struct _symtable_entry {
PyObject *ste_varnames; /* list of function parameters */
PyObject *ste_children; /* list of child blocks */
PyObject *ste_directives;/* locations of global and nonlocal statements */
_Py_block_ty ste_type; /* module, class, function or annotation */
_Py_block_ty ste_type;
int ste_nested; /* true if block is nested */
unsigned ste_free : 1; /* true if block has free variables */
unsigned ste_child_free : 1; /* true if a child block has free vars,
@ -64,8 +73,12 @@ typedef struct _symtable_entry {
unsigned ste_needs_class_closure : 1; /* for class scopes, true if a
closure over __class__
should be created */
unsigned ste_needs_classdict : 1; /* for class scopes, true if a closure
over the class dict should be created */
unsigned ste_comp_inlined : 1; /* true if this comprehension is inlined */
unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */
unsigned ste_can_see_class_scope : 1; /* true if this block can see names bound in an
enclosing class scope */
int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */
int ste_lineno; /* first line of block */
int ste_col_offset; /* offset of first line of block */
@ -82,6 +95,7 @@ extern PyTypeObject PySTEntry_Type;
extern long _PyST_GetSymbol(PySTEntryObject *, PyObject *);
extern int _PyST_GetScope(PySTEntryObject *, PyObject *);
extern int _PyST_IsFunctionLike(PySTEntryObject *);
extern struct symtable* _PySymtable_Build(
struct _mod *mod,
@ -105,6 +119,7 @@ extern PyObject* _Py_Mangle(PyObject *p, PyObject *name);
#define DEF_IMPORT 2<<6 /* assignment occurred via import */
#define DEF_ANNOT 2<<7 /* this name is annotated */
#define DEF_COMP_ITER 2<<8 /* this name is a comprehension iteration variable */
#define DEF_TYPE_PARAM 2<<9 /* this name is a type parameter */
#define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)

View File

@ -0,0 +1,22 @@
#ifndef Py_INTERNAL_TYPEVAROBJECT_H
#define Py_INTERNAL_TYPEVAROBJECT_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
extern PyObject *_Py_make_typevar(PyObject *, PyObject *, PyObject *);
extern PyObject *_Py_make_paramspec(PyThreadState *, PyObject *);
extern PyObject *_Py_make_typevartuple(PyThreadState *, PyObject *);
extern PyObject *_Py_make_typealias(PyThreadState *, PyObject *);
extern PyObject *_Py_subscript_generic(PyThreadState *, PyObject *);
extern int _Py_initialize_generic(PyInterpreterState *);
extern void _Py_clear_generic_types(PyInterpreterState *);
#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_TYPEVAROBJECT_H */

View File

@ -123,6 +123,12 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(__classcell__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(__classdict__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(__classdictcell__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(__complex__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -489,6 +495,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(__trunc__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(__type_params__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(__typing_is_unpacked_typevartuple__);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -654,12 +663,21 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(aggregate_class);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(alias);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(append);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(arg);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(argdefs);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(args);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(arguments);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -702,6 +720,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(block);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(bound);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(buffer);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -867,6 +888,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(context);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(contravariant);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(cookie);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -882,6 +906,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(count);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(covariant);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(cwd);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -1209,6 +1236,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(inf);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(infer_variance);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(inheritable);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -1557,6 +1587,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(order);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(origin);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(out_fd);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@ -1956,6 +1989,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(type);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(type_params);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(tz);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);

14
Include/opcode.h generated
View File

@ -45,6 +45,7 @@ extern "C" {
#define RETURN_GENERATOR 75
#define RETURN_VALUE 83
#define SETUP_ANNOTATIONS 85
#define LOAD_LOCALS 87
#define POP_EXCEPT 89
#define HAVE_ARGUMENT 90
#define STORE_NAME 90
@ -102,7 +103,6 @@ extern "C" {
#define LIST_APPEND 145
#define SET_ADD 146
#define MAP_ADD 147
#define LOAD_CLASSDEREF 148
#define COPY_FREE_VARS 149
#define YIELD_VALUE 150
#define RESUME 151
@ -118,6 +118,8 @@ extern "C" {
#define KW_NAMES 172
#define CALL_INTRINSIC_1 173
#define CALL_INTRINSIC_2 174
#define LOAD_FROM_DICT_OR_GLOBALS 175
#define LOAD_FROM_DICT_OR_DEREF 176
#define MIN_INSTRUMENTED_OPCODE 238
#define INSTRUMENTED_POP_JUMP_IF_NONE 238
#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 239
@ -199,11 +201,11 @@ extern "C" {
#define LOAD_ATTR_METHOD_WITH_VALUES 82
#define LOAD_CONST__LOAD_FAST 84
#define LOAD_FAST__LOAD_CONST 86
#define LOAD_FAST__LOAD_FAST 87
#define LOAD_GLOBAL_BUILTIN 88
#define LOAD_GLOBAL_MODULE 111
#define STORE_ATTR_INSTANCE_VALUE 112
#define STORE_ATTR_SLOT 113
#define LOAD_FAST__LOAD_FAST 88
#define LOAD_GLOBAL_BUILTIN 111
#define LOAD_GLOBAL_MODULE 112
#define STORE_ATTR_INSTANCE_VALUE 113
#define STORE_ATTR_SLOT 148
#define STORE_ATTR_WITH_HINT 153
#define STORE_FAST__LOAD_FAST 154
#define STORE_FAST__STORE_FAST 158

View File

@ -1051,6 +1051,7 @@ class _Unparser(NodeVisitor):
self.fill("@")
self.traverse(deco)
self.fill("class " + node.name)
self._typeparams_helper(node.typeparams)
with self.delimit_if("(", ")", condition = node.bases or node.keywords):
comma = False
for e in node.bases:
@ -1082,6 +1083,7 @@ class _Unparser(NodeVisitor):
self.traverse(deco)
def_str = fill_suffix + " " + node.name
self.fill(def_str)
self._typeparams_helper(node.typeparams)
with self.delimit("(", ")"):
self.traverse(node.args)
if node.returns:
@ -1090,6 +1092,30 @@ class _Unparser(NodeVisitor):
with self.block(extra=self.get_type_comment(node)):
self._write_docstring_and_traverse_body(node)
def _typeparams_helper(self, typeparams):
if typeparams is not None and len(typeparams) > 0:
with self.delimit("[", "]"):
self.interleave(lambda: self.write(", "), self.traverse, typeparams)
def visit_TypeVar(self, node):
self.write(node.name)
if node.bound:
self.write(": ")
self.traverse(node.bound)
def visit_TypeVarTuple(self, node):
self.write("*" + node.name)
def visit_ParamSpec(self, node):
self.write("**" + node.name)
def visit_TypeAlias(self, node):
self.fill("type ")
self.traverse(node.name)
self._typeparams_helper(node.typeparams)
self.write(" = ")
self.traverse(node.value)
def visit_For(self, node):
self._for_helper("for ", node)

View File

@ -444,6 +444,7 @@ _code_type = type(_write_atomic.__code__)
# Python 3.12b1 3528 (Add LOAD_SUPER_ATTR_METHOD specialization)
# Python 3.12b1 3529 (Inline list/dict/set comprehensions)
# Python 3.12b1 3530 (Shrink the LOAD_SUPER_ATTR caches)
# Python 3.12b1 3531 (Add PEP 695 changes)
# Python 3.13 will start with 3550
@ -460,7 +461,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3530).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3531).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

3
Lib/keyword.py generated
View File

@ -56,7 +56,8 @@ kwlist = [
softkwlist = [
'_',
'case',
'match'
'match',
'type'
]
iskeyword = frozenset(kwlist).__contains__

View File

@ -131,6 +131,7 @@ def_op('RETURN_GENERATOR', 75)
def_op('RETURN_VALUE', 83)
def_op('SETUP_ANNOTATIONS', 85)
def_op('LOAD_LOCALS', 87)
def_op('POP_EXCEPT', 89)
@ -206,7 +207,6 @@ EXTENDED_ARG = 144
def_op('LIST_APPEND', 145)
def_op('SET_ADD', 146)
def_op('MAP_ADD', 147)
def_op('LOAD_CLASSDEREF', 148)
hasfree.append(148)
def_op('COPY_FREE_VARS', 149)
def_op('YIELD_VALUE', 150)
@ -228,6 +228,10 @@ hasconst.append(172)
def_op('CALL_INTRINSIC_1', 173)
def_op('CALL_INTRINSIC_2', 174)
name_op('LOAD_FROM_DICT_OR_GLOBALS', 175)
def_op('LOAD_FROM_DICT_OR_DEREF', 176)
hasfree.append(176)
# Instrumented instructions
MIN_INSTRUMENTED_OPCODE = 238
@ -318,12 +322,20 @@ _intrinsic_1_descs = [
"INTRINSIC_ASYNC_GEN_WRAP",
"INTRINSIC_UNARY_POSITIVE",
"INTRINSIC_LIST_TO_TUPLE",
"INTRINSIC_TYPEVAR",
"INTRINSIC_PARAMSPEC",
"INTRINSIC_TYPEVARTUPLE",
"INTRINSIC_SUBSCRIPT_GENERIC",
"INTRINSIC_TYPEALIAS",
]
_intrinsic_2_descs = [
'INTRINSIC_2_INVALID',
'INTRINSIC_PREP_RERAISE_STAR',
]
"INTRINSIC_2_INVALID",
"INTRINSIC_PREP_RERAISE_STAR",
"INTRINSIC_TYPEVAR_WITH_BOUND",
"INTRINSIC_TYPEVAR_WITH_CONSTRAINTS",
"INTRINSIC_SET_FUNCTION_TYPE_PARAMS",
]
_specializations = {
"BINARY_OP": [

View File

@ -12,6 +12,7 @@ import re
import stat
import sys
import sysconfig
import textwrap
import time
import types
import unittest
@ -619,6 +620,14 @@ def sortdict(dict):
withcommas = ", ".join(reprpairs)
return "{%s}" % withcommas
def run_code(code: str) -> dict[str, object]:
"""Run a piece of code after dedenting it, and return its global namespace."""
ns = {}
exec(textwrap.dedent(code), ns)
return ns
def check_syntax_error(testcase, statement, errtext='', *, lineno=None, offset=None):
with testcase.assertRaisesRegex(SyntaxError, errtext) as cm:
compile(statement, '<test string>', 'exec')

View File

@ -181,7 +181,22 @@ exec_tests = [
"def f(a=1, /, b=2, *, c): pass",
"def f(a=1, /, b=2, *, c=4, **kwargs): pass",
"def f(a=1, /, b=2, *, c, **kwargs): pass",
# Type aliases
"type X = int",
"type X[T] = int",
"type X[T, *Ts, **P] = (T, Ts, P)",
"type X[T: int, *Ts, **P] = (T, Ts, P)",
"type X[T: (int, str), *Ts, **P] = (T, Ts, P)",
# Generic classes
"class X[T]: pass",
"class X[T, *Ts, **P]: pass",
"class X[T: int, *Ts, **P]: pass",
"class X[T: (int, str), *Ts, **P]: pass",
# Generic functions
"def f[T](): pass",
"def f[T, *Ts, **P](): pass",
"def f[T: int, *Ts, **P](): pass",
"def f[T: (int, str), *Ts, **P](): pass",
]
# These are compiled through "single"
@ -262,7 +277,6 @@ eval_tests = [
"()",
# Combination
"a.b.c.d(a.b[1:2])",
]
# TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension
@ -1013,6 +1027,18 @@ class AST_Tests(unittest.TestCase):
with self.assertRaises(SyntaxError):
ast.parse(code, feature_version=(3, 10))
def test_type_params_feature_version(self):
samples = [
"type X = int",
"class X[T]: pass",
"def f[T](): pass",
]
for sample in samples:
with self.subTest(sample):
ast.parse(sample)
with self.assertRaises(SyntaxError):
ast.parse(sample, feature_version=(3, 11))
def test_invalid_major_feature_version(self):
with self.assertRaises(ValueError):
ast.parse('pass', feature_version=(2, 7))
@ -1557,16 +1583,16 @@ class ASTValidatorTests(unittest.TestCase):
def test_funcdef(self):
a = ast.arguments([], [], None, [], [], None, [])
f = ast.FunctionDef("x", a, [], [], None)
f = ast.FunctionDef("x", [], a, [], [], None)
self.stmt(f, "empty body on FunctionDef")
f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())],
f = ast.FunctionDef("x", [], a, [ast.Pass()], [ast.Name("x", ast.Store())],
None)
self.stmt(f, "must have Load context")
f = ast.FunctionDef("x", a, [ast.Pass()], [],
f = ast.FunctionDef("x", [], a, [ast.Pass()], [],
ast.Name("x", ast.Store()))
self.stmt(f, "must have Load context")
def fac(args):
return ast.FunctionDef("x", args, [ast.Pass()], [], None)
return ast.FunctionDef("x", [], args, [ast.Pass()], [], None)
self._check_arguments(fac, self.stmt)
def test_classdef(self):
@ -1579,7 +1605,7 @@ class ASTValidatorTests(unittest.TestCase):
body = [ast.Pass()]
if decorator_list is None:
decorator_list = []
return ast.ClassDef("myclass", bases, keywords,
return ast.ClassDef("myclass", [], bases, keywords,
body, decorator_list)
self.stmt(cls(bases=[ast.Name("x", ast.Store())]),
"must have Load context")
@ -2869,23 +2895,23 @@ def main():
exec_results = [
('Module', [('Expr', (1, 0, 1, 4), ('Constant', (1, 0, 1, 4), None, None))], []),
('Module', [('Expr', (1, 0, 1, 18), ('Constant', (1, 0, 1, 18), 'module docstring', None))], []),
('Module', [('FunctionDef', (1, 0, 1, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 14), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 23), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 21), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 71), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 27), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
('Module', [('FunctionDef', (1, 0, 1, 45), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [('Pass', (1, 8, 1, 12))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 21), 'C', [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 14), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 23), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 21), 'f', [], ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 71), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 27), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
('Module', [('FunctionDef', (1, 0, 1, 45), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [], [('Pass', (1, 8, 1, 12))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 21), 'C', [], [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []),
('Module', [('Delete', (1, 0, 1, 5), [('Name', (1, 4, 1, 5), 'v', ('Del',))])], []),
('Module', [('Assign', (1, 0, 1, 5), [('Name', (1, 0, 1, 1), 'v', ('Store',))], ('Constant', (1, 4, 1, 5), 1, None), None)], []),
('Module', [('Assign', (1, 0, 1, 7), [('Tuple', (1, 0, 1, 3), [('Name', (1, 0, 1, 1), 'a', ('Store',)), ('Name', (1, 2, 1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 6, 1, 7), 'c', ('Load',)), None)], []),
@ -2922,28 +2948,41 @@ exec_results = [
('Module', [('Expr', (1, 0, 1, 20), ('DictComp', (1, 0, 1, 20), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'v', ('Store',)), ('Name', (1, 13, 1, 14), 'w', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'x', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 19), ('SetComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 12, 1, 13), 'x', ('Load',)), [('Name', (1, 17, 1, 18), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 16), ('SetComp', (1, 0, 1, 16), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7, 1, 10), [('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 9, 1, 10), 'm', ('Store',))], ('Store',)), ('Name', (1, 14, 1, 15), 'x', ('Load',)), [], 0)]))], []),
('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []),
('Module', [('Expr', (1, 0, 1, 14), ('Dict', (1, 0, 1, 14), [None, ('Constant', (1, 10, 1, 11), 2, None)], [('Dict', (1, 3, 1, 8), [('Constant', (1, 4, 1, 5), 1, None)], [('Constant', (1, 6, 1, 7), 2, None)]), ('Constant', (1, 12, 1, 13), 3, None)]))], []),
('Module', [('Expr', (1, 0, 1, 12), ('Set', (1, 0, 1, 12), [('Starred', (1, 1, 1, 8), ('Set', (1, 2, 1, 8), [('Constant', (1, 3, 1, 4), 1, None), ('Constant', (1, 6, 1, 7), 2, None)]), ('Load',)), ('Constant', (1, 10, 1, 11), 3, None)]))], []),
('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
('Module', [('FunctionDef', (4, 0, 4, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []),
('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
('Module', [('FunctionDef', (4, 0, 4, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []),
('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
('Module', [('Expr', (1, 0, 1, 8), ('NamedExpr', (1, 1, 1, 7), ('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Constant', (1, 6, 1, 7), 1, None)))], []),
('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 39), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 20), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 30), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 42), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 40), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 39), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 20), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 30), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 42), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 40), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []),
('Module', [('TypeAlias', (1, 0, 1, 12), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [], ('Name', (1, 9, 1, 12), 'int', ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 15), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None)], ('Name', (1, 12, 1, 15), 'int', ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 32), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts'), ('ParamSpec', (1, 15, 1, 18), 'P')], ('Tuple', (1, 22, 1, 32), [('Name', (1, 23, 1, 24), 'T', ('Load',)), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Name', (1, 30, 1, 31), 'P', ('Load',))], ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 37), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 13), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',))), ('TypeVarTuple', (1, 15, 1, 18), 'Ts'), ('ParamSpec', (1, 20, 1, 23), 'P')], ('Tuple', (1, 27, 1, 37), [('Name', (1, 28, 1, 29), 'T', ('Load',)), ('Name', (1, 31, 1, 33), 'Ts', ('Load',)), ('Name', (1, 35, 1, 36), 'P', ('Load',))], ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 44), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 20), 'T', ('Tuple', (1, 10, 1, 20), [('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Name', (1, 16, 1, 19), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 22, 1, 25), 'Ts'), ('ParamSpec', (1, 27, 1, 30), 'P')], ('Tuple', (1, 34, 1, 44), [('Name', (1, 35, 1, 36), 'T', ('Load',)), ('Name', (1, 38, 1, 40), 'Ts', ('Load',)), ('Name', (1, 42, 1, 43), 'P', ('Load',))], ('Load',)))], []),
('Module', [('ClassDef', (1, 0, 1, 16), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None)], [], [], [('Pass', (1, 12, 1, 16))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 26), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts'), ('ParamSpec', (1, 16, 1, 19), 'P')], [], [], [('Pass', (1, 22, 1, 26))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 31), 'X', [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',))), ('TypeVarTuple', (1, 16, 1, 19), 'Ts'), ('ParamSpec', (1, 21, 1, 24), 'P')], [], [], [('Pass', (1, 27, 1, 31))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 38), 'X', [('TypeVar', (1, 8, 1, 21), 'T', ('Tuple', (1, 11, 1, 21), [('Name', (1, 12, 1, 15), 'int', ('Load',)), ('Name', (1, 17, 1, 20), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 23, 1, 26), 'Ts'), ('ParamSpec', (1, 28, 1, 31), 'P')], [], [], [('Pass', (1, 34, 1, 38))], [])], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None)], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts'), ('ParamSpec', (1, 14, 1, 17), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 31), 'f', [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',))), ('TypeVarTuple', (1, 14, 1, 17), 'Ts'), ('ParamSpec', (1, 19, 1, 22), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 38), 'f', [('TypeVar', (1, 6, 1, 19), 'T', ('Tuple', (1, 9, 1, 19), [('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Name', (1, 15, 1, 18), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 21, 1, 24), 'Ts'), ('ParamSpec', (1, 26, 1, 29), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None)], []),
]
single_results = [
('Interactive', [('Expr', (1, 0, 1, 3), ('BinOp', (1, 0, 1, 3), ('Constant', (1, 0, 1, 1), 1, None), ('Add',), ('Constant', (1, 2, 1, 3), 2, None)))]),

View File

@ -39,7 +39,8 @@ class Test_iskeyword(unittest.TestCase):
self.assertIn("async", keyword.kwlist)
self.assertIn("await", keyword.kwlist)
def test_match_and_case_are_soft_keywords(self):
def test_soft_keywords(self):
self.assertIn("type", keyword.softkwlist)
self.assertIn("match", keyword.softkwlist)
self.assertIn("case", keyword.softkwlist)
self.assertIn("_", keyword.softkwlist)

View File

@ -1449,7 +1449,7 @@ class SizeofTest(unittest.TestCase):
check(x, size('3Pi3c7P2ic??2P'))
# function
def func(): pass
check(func, size('14Pi'))
check(func, size('15Pi'))
class c():
@staticmethod
def foo():

View File

@ -0,0 +1,204 @@
import types
import unittest
from test.support import check_syntax_error, run_code
from typing import Callable, TypeAliasType, TypeVar, get_args
class TypeParamsInvalidTest(unittest.TestCase):
def test_name_collision_01(self):
check_syntax_error(self, """type TA1[A, **A] = None""", "duplicate type parameter 'A'")
def test_name_non_collision_02(self):
ns = run_code("""type TA1[A] = lambda A: A""")
self.assertIsInstance(ns["TA1"], TypeAliasType)
self.assertTrue(callable(ns["TA1"].__value__))
self.assertEqual("arg", ns["TA1"].__value__("arg"))
def test_name_non_collision_03(self):
ns = run_code("""
class Outer[A]:
type TA1[A] = None
"""
)
outer_A, = ns["Outer"].__type_params__
inner_A, = ns["Outer"].TA1.__type_params__
self.assertIsNot(outer_A, inner_A)
class TypeParamsAccessTest(unittest.TestCase):
def test_alias_access_01(self):
ns = run_code("type TA1[A, B] = dict[A, B]")
alias = ns["TA1"]
self.assertIsInstance(alias, TypeAliasType)
self.assertEqual(alias.__type_params__, get_args(alias.__value__))
def test_alias_access_02(self):
ns = run_code("""
type TA1[A, B] = TA1[A, B] | int
"""
)
alias = ns["TA1"]
self.assertIsInstance(alias, TypeAliasType)
A, B = alias.__type_params__
self.assertEqual(alias.__value__, alias[A, B] | int)
def test_alias_access_03(self):
ns = run_code("""
class Outer[A]:
def inner[B](self):
type TA1[C] = TA1[A, B] | int
return TA1
"""
)
cls = ns["Outer"]
A, = cls.__type_params__
B, = cls.inner.__type_params__
alias = cls.inner(None)
self.assertIsInstance(alias, TypeAliasType)
alias2 = cls.inner(None)
self.assertIsNot(alias, alias2)
self.assertEqual(len(alias.__type_params__), 1)
self.assertEqual(alias.__value__, alias[A, B] | int)
class TypeParamsAliasValueTest(unittest.TestCase):
def test_alias_value_01(self):
type TA1 = int
self.assertIsInstance(TA1, TypeAliasType)
self.assertEqual(TA1.__value__, int)
self.assertEqual(TA1.__parameters__, ())
self.assertEqual(TA1.__type_params__, ())
type TA2 = TA1 | str
self.assertIsInstance(TA2, TypeAliasType)
a, b = TA2.__value__.__args__
self.assertEqual(a, TA1)
self.assertEqual(b, str)
self.assertEqual(TA2.__parameters__, ())
self.assertEqual(TA2.__type_params__, ())
def test_alias_value_02(self):
class Parent[A]:
type TA1[B] = dict[A, B]
self.assertIsInstance(Parent.TA1, TypeAliasType)
self.assertEqual(len(Parent.TA1.__parameters__), 1)
self.assertEqual(len(Parent.__parameters__), 1)
a, = Parent.__parameters__
b, = Parent.TA1.__parameters__
self.assertEqual(Parent.__type_params__, (a,))
self.assertEqual(Parent.TA1.__type_params__, (b,))
self.assertEqual(Parent.TA1.__value__, dict[a, b])
def test_alias_value_03(self):
def outer[A]():
type TA1[B] = dict[A, B]
return TA1
o = outer()
self.assertIsInstance(o, TypeAliasType)
self.assertEqual(len(o.__parameters__), 1)
self.assertEqual(len(outer.__type_params__), 1)
b = o.__parameters__[0]
self.assertEqual(o.__type_params__, (b,))
def test_alias_value_04(self):
def more_generic[T, *Ts, **P]():
type TA[T2, *Ts2, **P2] = tuple[Callable[P, tuple[T, *Ts]], Callable[P2, tuple[T2, *Ts2]]]
return TA
alias = more_generic()
self.assertIsInstance(alias, TypeAliasType)
T2, Ts2, P2 = alias.__type_params__
self.assertEqual(alias.__parameters__, (T2, *Ts2, P2))
T, Ts, P = more_generic.__type_params__
self.assertEqual(alias.__value__, tuple[Callable[P, tuple[T, *Ts]], Callable[P2, tuple[T2, *Ts2]]])
def test_subscripting(self):
type NonGeneric = int
type Generic[A] = dict[A, A]
type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
with self.assertRaises(TypeError):
NonGeneric[int]
specialized = Generic[int]
self.assertIsInstance(specialized, types.GenericAlias)
self.assertIs(specialized.__origin__, Generic)
self.assertEqual(specialized.__args__, (int,))
specialized2 = VeryGeneric[int, str, float, [bool, range]]
self.assertIsInstance(specialized2, types.GenericAlias)
self.assertIs(specialized2.__origin__, VeryGeneric)
self.assertEqual(specialized2.__args__, (int, str, float, [bool, range]))
def test_repr(self):
type Simple = int
self.assertEqual(repr(Simple), "Simple")
def test_recursive_repr(self):
type Recursive = Recursive
self.assertEqual(repr(Recursive), "Recursive")
type X = list[Y]
type Y = list[X]
self.assertEqual(repr(X), "X")
class TypeAliasConstructorTest(unittest.TestCase):
def test_basic(self):
TA = TypeAliasType("TA", int)
self.assertEqual(TA.__name__, "TA")
self.assertIs(TA.__value__, int)
self.assertEqual(TA.__type_params__, ())
def test_generic(self):
T = TypeVar("T")
TA = TypeAliasType("TA", list[T], type_params=(T,))
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__value__, list[T])
self.assertEqual(TA.__type_params__, (T,))
def test_keywords(self):
TA = TypeAliasType(name="TA", value=int)
self.assertEqual(TA.__name__, "TA")
self.assertIs(TA.__value__, int)
self.assertEqual(TA.__type_params__, ())
def test_errors(self):
with self.assertRaises(TypeError):
TypeAliasType()
with self.assertRaises(TypeError):
TypeAliasType("TA")
with self.assertRaises(TypeError):
TypeAliasType("TA", list, ())
with self.assertRaises(TypeError):
TypeAliasType("TA", list, type_params=42)
class TypeAliasTypeTest(unittest.TestCase):
def test_immutable(self):
with self.assertRaises(TypeError):
TypeAliasType.whatever = "not allowed"
def test_no_subclassing(self):
with self.assertRaisesRegex(TypeError, "not an acceptable base type"):
class MyAlias(TypeAliasType):
pass
def test_union(self):
type Alias1 = int
type Alias2 = str
union = Alias1 | Alias2
self.assertIsInstance(union, types.UnionType)
self.assertEqual(get_args(union), (Alias1, Alias2))
union2 = Alias1 | list[float]
self.assertIsInstance(union2, types.UnionType)
self.assertEqual(get_args(union2), (Alias1, list[float]))
union3 = list[range] | Alias1
self.assertIsInstance(union3, types.UnionType)
self.assertEqual(get_args(union3), (list[range], Alias1))

View File

@ -0,0 +1,847 @@
import asyncio
import textwrap
import types
import unittest
from test.support import requires_working_socket, check_syntax_error, run_code
from typing import Generic, Sequence, TypeVar, TypeVarTuple, ParamSpec, get_args
class TypeParamsInvalidTest(unittest.TestCase):
def test_name_collision_01(self):
check_syntax_error(self, """def func[**A, A](): ...""")
def test_name_non_collision_02(self):
ns = run_code("""def func[A](A): return A""")
func = ns["func"]
self.assertEqual(func(1), 1)
A, = func.__type_params__
self.assertEqual(A.__name__, "A")
def test_name_non_collision_03(self):
ns = run_code("""def func[A](*A): return A""")
func = ns["func"]
self.assertEqual(func(1), (1,))
A, = func.__type_params__
self.assertEqual(A.__name__, "A")
def test_name_non_collision_04(self):
# Mangled names should not cause a conflict.
ns = run_code("""
class ClassA:
def func[__A](self, __A): return __A
"""
)
cls = ns["ClassA"]
self.assertEqual(cls().func(1), 1)
A, = cls.func.__type_params__
self.assertEqual(A.__name__, "__A")
def test_name_non_collision_05(self):
ns = run_code("""
class ClassA:
def func[_ClassA__A](self, __A): return __A
"""
)
cls = ns["ClassA"]
self.assertEqual(cls().func(1), 1)
A, = cls.func.__type_params__
self.assertEqual(A.__name__, "_ClassA__A")
def test_name_non_collision_06(self):
ns = run_code("""
class ClassA[X]:
def func(self, X): return X
"""
)
cls = ns["ClassA"]
self.assertEqual(cls().func(1), 1)
X, = cls.__type_params__
self.assertEqual(X.__name__, "X")
def test_name_non_collision_07(self):
ns = run_code("""
class ClassA[X]:
def func(self):
X = 1
return X
"""
)
cls = ns["ClassA"]
self.assertEqual(cls().func(), 1)
X, = cls.__type_params__
self.assertEqual(X.__name__, "X")
def test_name_non_collision_08(self):
ns = run_code("""
class ClassA[X]:
def func(self):
return [X for X in [1, 2]]
"""
)
cls = ns["ClassA"]
self.assertEqual(cls().func(), [1, 2])
X, = cls.__type_params__
self.assertEqual(X.__name__, "X")
def test_name_non_collision_9(self):
ns = run_code("""
class ClassA[X]:
def func[X](self):
...
"""
)
cls = ns["ClassA"]
outer_X, = cls.__type_params__
inner_X, = cls.func.__type_params__
self.assertEqual(outer_X.__name__, "X")
self.assertEqual(inner_X.__name__, "X")
self.assertIsNot(outer_X, inner_X)
def test_name_non_collision_10(self):
ns = run_code("""
class ClassA[X]:
X: int
"""
)
cls = ns["ClassA"]
X, = cls.__type_params__
self.assertEqual(X.__name__, "X")
self.assertIs(cls.__annotations__["X"], int)
def test_name_non_collision_13(self):
ns = run_code("""
X = 1
def outer():
def inner[X]():
global X
X = 2
return inner
"""
)
self.assertEqual(ns["X"], 1)
outer = ns["outer"]
outer()()
self.assertEqual(ns["X"], 2)
def test_disallowed_expressions(self):
check_syntax_error(self, "type X = (yield)")
check_syntax_error(self, "type X = (yield from x)")
check_syntax_error(self, "type X = (await 42)")
check_syntax_error(self, "async def f(): type X = (yield)")
check_syntax_error(self, "type X = (y := 3)")
check_syntax_error(self, "class X[T: (yield)]: pass")
check_syntax_error(self, "class X[T: (yield from x)]: pass")
check_syntax_error(self, "class X[T: (await 42)]: pass")
check_syntax_error(self, "class X[T: (y := 3)]: pass")
check_syntax_error(self, "class X[T](y := Sequence[T]): pass")
check_syntax_error(self, "def f[T](y: (x := Sequence[T])): pass")
class TypeParamsNonlocalTest(unittest.TestCase):
def test_nonlocal_disallowed_01(self):
code = """
def outer():
X = 1
def inner[X]():
nonlocal X
return X
"""
check_syntax_error(self, code)
def test_nonlocal_disallowed_02(self):
code = """
def outer2[T]():
def inner1():
nonlocal T
"""
check_syntax_error(self, textwrap.dedent(code))
def test_nonlocal_disallowed_03(self):
code = """
class Cls[T]:
nonlocal T
"""
check_syntax_error(self, textwrap.dedent(code))
def test_nonlocal_allowed(self):
code = """
def func[T]():
T = "func"
def inner():
nonlocal T
T = "inner"
inner()
assert T == "inner"
"""
ns = run_code(code)
func = ns["func"]
T, = func.__type_params__
self.assertEqual(T.__name__, "T")
class TypeParamsAccessTest(unittest.TestCase):
def test_class_access_01(self):
ns = run_code("""
class ClassA[A, B](dict[A, B]):
...
"""
)
cls = ns["ClassA"]
A, B = cls.__type_params__
self.assertEqual(types.get_original_bases(cls), (dict[A, B], Generic[A, B]))
def test_class_access_02(self):
ns = run_code("""
class MyMeta[A, B](type): ...
class ClassA[A, B](metaclass=MyMeta[A, B]):
...
"""
)
meta = ns["MyMeta"]
cls = ns["ClassA"]
A1, B1 = meta.__type_params__
A2, B2 = cls.__type_params__
self.assertIsNot(A1, A2)
self.assertIsNot(B1, B2)
self.assertIs(type(cls), meta)
def test_class_access_03(self):
code = """
def my_decorator(a):
...
@my_decorator(A)
class ClassA[A, B]():
...
"""
with self.assertRaisesRegex(NameError, "name 'A' is not defined"):
run_code(code)
def test_function_access_01(self):
ns = run_code("""
def func[A, B](a: dict[A, B]):
...
"""
)
func = ns["func"]
A, B = func.__type_params__
self.assertEqual(func.__annotations__["a"], dict[A, B])
def test_function_access_02(self):
code = """
def func[A](a = list[A]()):
...
"""
with self.assertRaisesRegex(NameError, "name 'A' is not defined"):
run_code(code)
def test_function_access_03(self):
code = """
def my_decorator(a):
...
@my_decorator(A)
def func[A]():
...
"""
with self.assertRaisesRegex(NameError, "name 'A' is not defined"):
run_code(code)
def test_method_access_01(self):
ns = run_code("""
class ClassA:
x = int
def func[T](self, a: x, b: T):
...
"""
)
cls = ns["ClassA"]
self.assertIs(cls.func.__annotations__["a"], int)
T, = cls.func.__type_params__
self.assertIs(cls.func.__annotations__["b"], T)
def test_nested_access_01(self):
ns = run_code("""
class ClassA[A]:
def funcB[B](self):
class ClassC[C]:
def funcD[D](self):
return lambda: (A, B, C, D)
return ClassC
"""
)
cls = ns["ClassA"]
A, = cls.__type_params__
B, = cls.funcB.__type_params__
classC = cls().funcB()
C, = classC.__type_params__
D, = classC.funcD.__type_params__
self.assertEqual(classC().funcD()(), (A, B, C, D))
def test_out_of_scope_01(self):
code = """
class ClassA[T]: ...
x = T
"""
with self.assertRaisesRegex(NameError, "name 'T' is not defined"):
run_code(code)
def test_out_of_scope_02(self):
code = """
class ClassA[A]:
def funcB[B](self): ...
x = B
"""
with self.assertRaisesRegex(NameError, "name 'B' is not defined"):
run_code(code)
def test_class_scope_interaction_01(self):
ns = run_code("""
class C:
x = 1
def method[T](self, arg: x): pass
""")
cls = ns["C"]
self.assertEqual(cls.method.__annotations__["arg"], 1)
def test_class_scope_interaction_02(self):
ns = run_code("""
class C:
class Base: pass
class Child[T](Base): pass
""")
cls = ns["C"]
self.assertEqual(cls.Child.__bases__, (cls.Base, Generic))
T, = cls.Child.__type_params__
self.assertEqual(types.get_original_bases(cls.Child), (cls.Base, Generic[T]))
def test_class_deref(self):
ns = run_code("""
class C[T]:
T = "class"
type Alias = T
""")
cls = ns["C"]
self.assertEqual(cls.Alias.__value__, "class")
def test_shadowing_nonlocal(self):
ns = run_code("""
def outer[T]():
T = "outer"
def inner():
nonlocal T
T = "inner"
return T
return lambda: T, inner
""")
outer = ns["outer"]
T, = outer.__type_params__
self.assertEqual(T.__name__, "T")
getter, inner = outer()
self.assertEqual(getter(), "outer")
self.assertEqual(inner(), "inner")
self.assertEqual(getter(), "inner")
def test_reference_previous_typevar(self):
def func[S, T: Sequence[S]]():
pass
S, T = func.__type_params__
self.assertEqual(T.__bound__, Sequence[S])
def test_super(self):
class Base:
def meth(self):
return "base"
class Child(Base):
# Having int in the annotation ensures the class gets cells for both
# __class__ and __classdict__
def meth[T](self, arg: int) -> T:
return super().meth() + "child"
c = Child()
self.assertEqual(c.meth(1), "basechild")
def test_type_alias_containing_lambda(self):
type Alias[T] = lambda: T
T, = Alias.__type_params__
self.assertIs(Alias.__value__(), T)
def test_class_base_containing_lambda(self):
# Test that scopes nested inside hidden functions work correctly
outer_var = "outer"
class Base[T]: ...
class Child[T](Base[lambda: (int, outer_var, T)]): ...
base, _ = types.get_original_bases(Child)
func, = get_args(base)
T, = Child.__type_params__
self.assertEqual(func(), (int, "outer", T))
def test_comprehension_01(self):
type Alias[T: ([T for T in (T, [1])[1]], T)] = [T for T in T.__name__]
self.assertEqual(Alias.__value__, ["T"])
T, = Alias.__type_params__
self.assertEqual(T.__constraints__, ([1], T))
def test_comprehension_02(self):
type Alias[T: [lambda: T for T in (T, [1])[1]]] = [lambda: T for T in T.__name__]
func, = Alias.__value__
self.assertEqual(func(), "T")
T, = Alias.__type_params__
func, = T.__bound__
self.assertEqual(func(), 1)
def global_generic_func[T]():
pass
class GlobalGenericClass[T]:
pass
class TypeParamsLazyEvaluationTest(unittest.TestCase):
def test_qualname(self):
class Foo[T]:
pass
def func[T]():
pass
self.assertEqual(Foo.__qualname__, "TypeParamsLazyEvaluationTest.test_qualname.<locals>.Foo")
self.assertEqual(func.__qualname__, "TypeParamsLazyEvaluationTest.test_qualname.<locals>.func")
self.assertEqual(global_generic_func.__qualname__, "global_generic_func")
self.assertEqual(GlobalGenericClass.__qualname__, "GlobalGenericClass")
def test_recursive_class(self):
class Foo[T: Foo, U: (Foo, Foo)]:
pass
type_params = Foo.__type_params__
self.assertEqual(len(type_params), 2)
self.assertEqual(type_params[0].__name__, "T")
self.assertEqual(type_params[0].__bound__, Foo)
self.assertEqual(type_params[0].__constraints__, None)
self.assertEqual(type_params[1].__name__, "U")
self.assertEqual(type_params[1].__bound__, None)
self.assertEqual(type_params[1].__constraints__, (Foo, Foo))
def test_evaluation_error(self):
class Foo[T: Undefined, U: (Undefined,)]:
pass
type_params = Foo.__type_params__
with self.assertRaises(NameError):
type_params[0].__bound__
self.assertEqual(type_params[0].__constraints__, None)
self.assertEqual(type_params[1].__bound__, None)
with self.assertRaises(NameError):
type_params[1].__constraints__
Undefined = "defined"
self.assertEqual(type_params[0].__bound__, "defined")
self.assertEqual(type_params[0].__constraints__, None)
self.assertEqual(type_params[1].__bound__, None)
self.assertEqual(type_params[1].__constraints__, ("defined",))
class TypeParamsClassScopeTest(unittest.TestCase):
def test_alias(self):
class X:
T = int
type U = T
self.assertIs(X.U.__value__, int)
ns = run_code("""
glb = "global"
class X:
cls = "class"
type U = (glb, cls)
""")
cls = ns["X"]
self.assertEqual(cls.U.__value__, ("global", "class"))
def test_bound(self):
class X:
T = int
def foo[U: T](self): ...
self.assertIs(X.foo.__type_params__[0].__bound__, int)
ns = run_code("""
glb = "global"
class X:
cls = "class"
def foo[T: glb, U: cls](self): ...
""")
cls = ns["X"]
T, U = cls.foo.__type_params__
self.assertEqual(T.__bound__, "global")
self.assertEqual(U.__bound__, "class")
def test_modified_later(self):
class X:
T = int
def foo[U: T](self): ...
type Alias = T
X.T = float
self.assertIs(X.foo.__type_params__[0].__bound__, float)
self.assertIs(X.Alias.__value__, float)
def test_binding_uses_global(self):
ns = run_code("""
x = "global"
def outer():
x = "nonlocal"
class Cls:
type Alias = x
val = Alias.__value__
def meth[T: x](self, arg: x): ...
bound = meth.__type_params__[0].__bound__
annotation = meth.__annotations__["arg"]
x = "class"
return Cls
""")
cls = ns["outer"]()
self.assertEqual(cls.val, "global")
self.assertEqual(cls.bound, "global")
self.assertEqual(cls.annotation, "global")
def test_no_binding_uses_nonlocal(self):
ns = run_code("""
x = "global"
def outer():
x = "nonlocal"
class Cls:
type Alias = x
val = Alias.__value__
def meth[T: x](self, arg: x): ...
bound = meth.__type_params__[0].__bound__
return Cls
""")
cls = ns["outer"]()
self.assertEqual(cls.val, "nonlocal")
self.assertEqual(cls.bound, "nonlocal")
self.assertEqual(cls.meth.__annotations__["arg"], "nonlocal")
def test_explicit_global(self):
ns = run_code("""
x = "global"
def outer():
x = "nonlocal"
class Cls:
global x
type Alias = x
Cls.x = "class"
return Cls
""")
cls = ns["outer"]()
self.assertEqual(cls.Alias.__value__, "global")
def test_explicit_global_with_no_static_bound(self):
ns = run_code("""
def outer():
class Cls:
global x
type Alias = x
Cls.x = "class"
return Cls
""")
ns["x"] = "global"
cls = ns["outer"]()
self.assertEqual(cls.Alias.__value__, "global")
def test_explicit_global_with_assignment(self):
ns = run_code("""
x = "global"
def outer():
x = "nonlocal"
class Cls:
global x
type Alias = x
x = "global from class"
Cls.x = "class"
return Cls
""")
cls = ns["outer"]()
self.assertEqual(cls.Alias.__value__, "global from class")
def test_explicit_nonlocal(self):
ns = run_code("""
x = "global"
def outer():
x = "nonlocal"
class Cls:
nonlocal x
type Alias = x
x = "class"
return Cls
""")
cls = ns["outer"]()
self.assertEqual(cls.Alias.__value__, "class")
class TypeParamsManglingTest(unittest.TestCase):
def test_mangling(self):
class Foo[__T]:
param = __T
def meth[__U](self, arg: __T, arg2: __U):
return (__T, __U)
type Alias[__V] = (__T, __V)
T = Foo.__type_params__[0]
self.assertEqual(T.__name__, "__T")
U = Foo.meth.__type_params__[0]
self.assertEqual(U.__name__, "__U")
V = Foo.Alias.__type_params__[0]
self.assertEqual(V.__name__, "__V")
anno = Foo.meth.__annotations__
self.assertIs(anno["arg"], T)
self.assertIs(anno["arg2"], U)
self.assertEqual(Foo().meth(1, 2), (T, U))
self.assertEqual(Foo.Alias.__value__, (T, V))
class TypeParamsComplexCallsTest(unittest.TestCase):
def test_defaults(self):
# Generic functions with both defaults and kwdefaults trigger a specific code path
# in the compiler.
def func[T](a: T = "a", *, b: T = "b"):
return (a, b)
T, = func.__type_params__
self.assertIs(func.__annotations__["a"], T)
self.assertIs(func.__annotations__["b"], T)
self.assertEqual(func(), ("a", "b"))
self.assertEqual(func(1), (1, "b"))
self.assertEqual(func(b=2), ("a", 2))
def test_complex_base(self):
class Base:
def __init_subclass__(cls, **kwargs) -> None:
cls.kwargs = kwargs
kwargs = {"c": 3}
# Base classes with **kwargs trigger a different code path in the compiler.
class C[T](Base, a=1, b=2, **kwargs):
pass
T, = C.__type_params__
self.assertEqual(T.__name__, "T")
self.assertEqual(C.kwargs, {"a": 1, "b": 2, "c": 3})
bases = (Base,)
class C2[T](*bases, **kwargs):
pass
T, = C2.__type_params__
self.assertEqual(T.__name__, "T")
self.assertEqual(C2.kwargs, {"c": 3})
class TypeParamsTraditionalTypeVarsTest(unittest.TestCase):
def test_traditional_01(self):
code = """
from typing import Generic
class ClassA[T](Generic[T]): ...
"""
with self.assertRaisesRegex(TypeError, r"Cannot inherit from Generic\[...\] multiple times."):
run_code(code)
def test_traditional_02(self):
from typing import TypeVar
S = TypeVar("S")
with self.assertRaises(TypeError):
class ClassA[T](dict[T, S]): ...
def test_traditional_03(self):
# This does not generate a runtime error, but it should be
# flagged as an error by type checkers.
from typing import TypeVar
S = TypeVar("S")
def func[T](a: T, b: S) -> T | S:
return a
class TypeParamsTypeVarTest(unittest.TestCase):
def test_typevar_01(self):
def func1[A: str, B: str | int, C: (int, str)]():
return (A, B, C)
a, b, c = func1()
self.assertIsInstance(a, TypeVar)
self.assertEqual(a.__bound__, str)
self.assertTrue(a.__infer_variance__)
self.assertFalse(a.__covariant__)
self.assertFalse(a.__contravariant__)
self.assertIsInstance(b, TypeVar)
self.assertEqual(b.__bound__, str | int)
self.assertTrue(b.__infer_variance__)
self.assertFalse(b.__covariant__)
self.assertFalse(b.__contravariant__)
self.assertIsInstance(c, TypeVar)
self.assertEqual(c.__bound__, None)
self.assertEqual(c.__constraints__, (int, str))
self.assertTrue(c.__infer_variance__)
self.assertFalse(c.__covariant__)
self.assertFalse(c.__contravariant__)
def test_typevar_generator(self):
def get_generator[A]():
def generator1[C]():
yield C
def generator2[B]():
yield A
yield B
yield from generator1()
return generator2
gen = get_generator()
a, b, c = [x for x in gen()]
self.assertIsInstance(a, TypeVar)
self.assertEqual(a.__name__, "A")
self.assertIsInstance(b, TypeVar)
self.assertEqual(b.__name__, "B")
self.assertIsInstance(c, TypeVar)
self.assertEqual(c.__name__, "C")
@requires_working_socket()
def test_typevar_coroutine(self):
def get_coroutine[A]():
async def coroutine[B]():
return (A, B)
return coroutine
co = get_coroutine()
self.addCleanup(asyncio.set_event_loop_policy, None)
a, b = asyncio.run(co())
self.assertIsInstance(a, TypeVar)
self.assertEqual(a.__name__, "A")
self.assertIsInstance(b, TypeVar)
self.assertEqual(b.__name__, "B")
class TypeParamsTypeVarTupleTest(unittest.TestCase):
def test_typevartuple_01(self):
code = """def func1[*A: str](): pass"""
check_syntax_error(self, code, "cannot use bound with TypeVarTuple")
code = """def func1[*A: (int, str)](): pass"""
check_syntax_error(self, code, "cannot use constraints with TypeVarTuple")
code = """class X[*A: str]: pass"""
check_syntax_error(self, code, "cannot use bound with TypeVarTuple")
code = """class X[*A: (int, str)]: pass"""
check_syntax_error(self, code, "cannot use constraints with TypeVarTuple")
code = """type X[*A: str] = int"""
check_syntax_error(self, code, "cannot use bound with TypeVarTuple")
code = """type X[*A: (int, str)] = int"""
check_syntax_error(self, code, "cannot use constraints with TypeVarTuple")
def test_typevartuple_02(self):
def func1[*A]():
return A
a = func1()
self.assertIsInstance(a, TypeVarTuple)
class TypeParamsTypeVarParamSpecTest(unittest.TestCase):
def test_paramspec_01(self):
code = """def func1[**A: str](): pass"""
check_syntax_error(self, code, "cannot use bound with ParamSpec")
code = """def func1[**A: (int, str)](): pass"""
check_syntax_error(self, code, "cannot use constraints with ParamSpec")
code = """class X[**A: str]: pass"""
check_syntax_error(self, code, "cannot use bound with ParamSpec")
code = """class X[**A: (int, str)]: pass"""
check_syntax_error(self, code, "cannot use constraints with ParamSpec")
code = """type X[**A: str] = int"""
check_syntax_error(self, code, "cannot use bound with ParamSpec")
code = """type X[**A: (int, str)] = int"""
check_syntax_error(self, code, "cannot use constraints with ParamSpec")
def test_paramspec_02(self):
def func1[**A]():
return A
a = func1()
self.assertIsInstance(a, ParamSpec)
self.assertTrue(a.__infer_variance__)
self.assertFalse(a.__covariant__)
self.assertFalse(a.__contravariant__)
class TypeParamsTypeParamsDunder(unittest.TestCase):
def test_typeparams_dunder_class_01(self):
class Outer[A, B]:
class Inner[C, D]:
@staticmethod
def get_typeparams():
return A, B, C, D
a, b, c, d = Outer.Inner.get_typeparams()
self.assertEqual(Outer.__type_params__, (a, b))
self.assertEqual(Outer.Inner.__type_params__, (c, d))
self.assertEqual(Outer.__parameters__, (a, b))
self.assertEqual(Outer.Inner.__parameters__, (c, d))
def test_typeparams_dunder_class_02(self):
class ClassA:
pass
self.assertEqual(ClassA.__type_params__, ())
def test_typeparams_dunder_class_03(self):
code = """
class ClassA[A]():
pass
ClassA.__type_params__ = ()
"""
with self.assertRaisesRegex(AttributeError, "attribute '__type_params__' of 'type' objects is not writable"):
run_code(code)
def test_typeparams_dunder_function_01(self):
def outer[A, B]():
def inner[C, D]():
return A, B, C, D
return inner
inner = outer()
a, b, c, d = inner()
self.assertEqual(outer.__type_params__, (a, b))
self.assertEqual(inner.__type_params__, (c, d))
def test_typeparams_dunder_function_02(self):
def func1():
pass
self.assertEqual(func1.__type_params__, ())
def test_typeparams_dunder_function_03(self):
code = """
def func[A]():
pass
func.__type_params__ = ()
"""
with self.assertRaisesRegex(AttributeError, "attribute '__type_params__' of 'function' objects is not writable"):
run_code(code)

View File

@ -48,11 +48,8 @@ from test import mod_generics_cache
from test import _typed_dict_helper
py_typing = import_helper.import_fresh_module('typing', blocked=['_typing'])
c_typing = import_helper.import_fresh_module('typing', fresh=['_typing'])
CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes'
NOT_A_BASE_TYPE = "type 'typing.%s' is not an acceptable base type"
CANNOT_SUBCLASS_INSTANCE = 'Cannot subclass an instance of %s'
@ -430,7 +427,7 @@ class TypeVarTests(BaseTestCase):
self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str))
def test_cannot_subclass(self):
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVar'):
class V(TypeVar): pass
T = TypeVar("T")
with self.assertRaisesRegex(TypeError,
@ -446,6 +443,9 @@ class TypeVarTests(BaseTestCase):
TypeVar('X', bound=Union)
with self.assertRaises(TypeError):
TypeVar('X', str, float, bound=Employee)
with self.assertRaisesRegex(TypeError,
r"Bound must be a type\. Got \(1, 2\)\."):
TypeVar('X', bound=(1, 2))
def test_missing__name__(self):
# See bpo-39942
@ -1161,7 +1161,7 @@ class TypeVarTupleTests(BaseTestCase):
self.assertEndsWith(repr(K[float, str]), 'A[float, str, typing.Unpack[typing.Tuple[str, ...]]]')
def test_cannot_subclass(self):
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVarTuple'):
class C(TypeVarTuple): pass
Ts = TypeVarTuple('Ts')
with self.assertRaisesRegex(TypeError,
@ -6444,34 +6444,27 @@ class TypeTests(BaseTestCase):
class TestModules(TestCase):
func_names = ['_idfunc']
def test_py_functions(self):
for fname in self.func_names:
self.assertEqual(getattr(py_typing, fname).__module__, 'typing')
@skipUnless(c_typing, 'requires _typing')
def test_c_functions(self):
for fname in self.func_names:
self.assertEqual(getattr(c_typing, fname).__module__, '_typing')
self.assertEqual(getattr(typing, fname).__module__, '_typing')
class NewTypeTests:
class NewTypeTests(BaseTestCase):
def cleanup(self):
for f in self.module._cleanups:
for f in typing._cleanups:
f()
@classmethod
def setUpClass(cls):
sys.modules['typing'] = cls.module
global UserId
UserId = cls.module.NewType('UserId', int)
cls.UserName = cls.module.NewType(cls.__qualname__ + '.UserName', str)
UserId = typing.NewType('UserId', int)
cls.UserName = typing.NewType(cls.__qualname__ + '.UserName', str)
@classmethod
def tearDownClass(cls):
global UserId
del UserId
del cls.UserName
sys.modules['typing'] = typing
def tearDown(self):
self.cleanup()
@ -6491,11 +6484,11 @@ class NewTypeTests:
def test_or(self):
for cls in (int, self.UserName):
with self.subTest(cls=cls):
self.assertEqual(UserId | cls, self.module.Union[UserId, cls])
self.assertEqual(cls | UserId, self.module.Union[cls, UserId])
self.assertEqual(UserId | cls, typing.Union[UserId, cls])
self.assertEqual(cls | UserId, typing.Union[cls, UserId])
self.assertEqual(self.module.get_args(UserId | cls), (UserId, cls))
self.assertEqual(self.module.get_args(cls | UserId), (cls, UserId))
self.assertEqual(typing.get_args(UserId | cls), (UserId, cls))
self.assertEqual(typing.get_args(cls | UserId), (cls, UserId))
def test_special_attrs(self):
self.assertEqual(UserId.__name__, 'UserId')
@ -6516,7 +6509,7 @@ class NewTypeTests:
f'{__name__}.{self.__class__.__qualname__}.UserName')
def test_pickle(self):
UserAge = self.module.NewType('UserAge', float)
UserAge = typing.NewType('UserAge', float)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(proto=proto):
pickled = pickle.dumps(UserId, proto)
@ -6548,15 +6541,6 @@ class NewTypeTests:
...
class NewTypePythonTests(NewTypeTests, BaseTestCase):
module = py_typing
@skipUnless(c_typing, 'requires _typing')
class NewTypeCTests(NewTypeTests, BaseTestCase):
module = c_typing
class NamedTupleTests(BaseTestCase):
class NestedEmployee(NamedTuple):
name: str
@ -8170,11 +8154,11 @@ class ParamSpecTests(BaseTestCase):
self.assertEqual(C2[Concatenate[T, P2]].__parameters__, (T, P2))
def test_cannot_subclass(self):
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpec'):
class C(ParamSpec): pass
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecArgs'):
class C(ParamSpecArgs): pass
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecKwargs'):
class C(ParamSpecKwargs): pass
P = ParamSpec('P')
with self.assertRaisesRegex(TypeError,

View File

@ -23,6 +23,7 @@ from abc import abstractmethod, ABCMeta
import collections
from collections import defaultdict
import collections.abc
import copyreg
import contextlib
import functools
import operator
@ -32,12 +33,16 @@ import types
import warnings
from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias
try:
from _typing import _idfunc
except ImportError:
def _idfunc(_, x):
return x
from _typing import (
_idfunc,
TypeVar,
ParamSpec,
TypeVarTuple,
ParamSpecArgs,
ParamSpecKwargs,
TypeAliasType,
Generic,
)
# Please keep __all__ alphabetized within each category.
__all__ = [
@ -149,6 +154,7 @@ __all__ = [
'TYPE_CHECKING',
'TypeAlias',
'TypeGuard',
'TypeAliasType',
'Unpack',
]
@ -695,6 +701,15 @@ def Union(self, parameters):
return _UnionGenericAlias(self, parameters, name="Optional")
return _UnionGenericAlias(self, parameters)
def _make_union(left, right):
"""Used from the C implementation of TypeVar.
TypeVar.__or__ calls this instead of returning types.UnionType
because we want to allow unions between TypeVars and strings
(forward references.)
"""
return Union[left, right]
@_SpecialForm
def Optional(self, parameters):
"""Optional type.
@ -926,333 +941,162 @@ class _PickleUsingNameMixin:
return self.__name__
class _BoundVarianceMixin:
"""Mixin giving __init__ bound and variance arguments.
def _typevar_subst(self, arg):
msg = "Parameters to generic types must be types."
arg = _type_check(arg, msg, is_argument=True)
if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or
(isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))):
raise TypeError(f"{arg} is not valid as type argument")
return arg
This is used by TypeVar and ParamSpec, which both employ the notions of
a type 'bound' (restricting type arguments to be a subtype of some
specified type) and type 'variance' (determining subtype relations between
generic types).
def _typevartuple_prepare_subst(self, alias, args):
params = alias.__parameters__
typevartuple_index = params.index(self)
for param in params[typevartuple_index + 1:]:
if isinstance(param, TypeVarTuple):
raise TypeError(f"More than one TypeVarTuple parameter in {alias}")
alen = len(args)
plen = len(params)
left = typevartuple_index
right = plen - typevartuple_index - 1
var_tuple_index = None
fillarg = None
for k, arg in enumerate(args):
if not isinstance(arg, type):
subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
if subargs and len(subargs) == 2 and subargs[-1] is ...:
if var_tuple_index is not None:
raise TypeError("More than one unpacked arbitrary-length tuple argument")
var_tuple_index = k
fillarg = subargs[0]
if var_tuple_index is not None:
left = min(left, var_tuple_index)
right = min(right, alen - var_tuple_index - 1)
elif left + right > alen:
raise TypeError(f"Too few arguments for {alias};"
f" actual {alen}, expected at least {plen-1}")
return (
*args[:left],
*([fillarg]*(typevartuple_index - left)),
tuple(args[left: alen - right]),
*([fillarg]*(plen - right - left - typevartuple_index - 1)),
*args[alen - right:],
)
def _paramspec_subst(self, arg):
if isinstance(arg, (list, tuple)):
arg = tuple(_type_check(a, "Expected a type.") for a in arg)
elif not _is_param_expr(arg):
raise TypeError(f"Expected a list of types, an ellipsis, "
f"ParamSpec, or Concatenate. Got {arg}")
return arg
def _paramspec_prepare_subst(self, alias, args):
params = alias.__parameters__
i = params.index(self)
if i >= len(args):
raise TypeError(f"Too few arguments for {alias}")
# Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612.
if len(params) == 1 and not _is_param_expr(args[0]):
assert i == 0
args = (args,)
# Convert lists to tuples to help other libraries cache the results.
elif isinstance(args[i], list):
args = (*args[:i], tuple(args[i]), *args[i+1:])
return args
@_tp_cache
def _generic_class_getitem(cls, params):
"""Parameterizes a generic class.
At least, parameterizing a generic class is the *main* thing this method
does. For example, for some generic class `Foo`, this is called when we
do `Foo[int]` - there, with `cls=Foo` and `params=int`.
However, note that this method is also called when defining generic
classes in the first place with `class Foo(Generic[T]): ...`.
"""
def __init__(self, bound, covariant, contravariant):
"""Used to setup TypeVars and ParamSpec's bound, covariant and
contravariant attributes.
"""
if covariant and contravariant:
raise ValueError("Bivariant types are not supported.")
self.__covariant__ = bool(covariant)
self.__contravariant__ = bool(contravariant)
if bound:
self.__bound__ = _type_check(bound, "Bound must be a type.")
else:
self.__bound__ = None
if not isinstance(params, tuple):
params = (params,)
def __or__(self, right):
return Union[self, right]
params = tuple(_type_convert(p) for p in params)
is_generic_or_protocol = cls in (Generic, Protocol)
def __ror__(self, left):
return Union[left, self]
if is_generic_or_protocol:
# Generic and Protocol can only be subscripted with unique type variables.
if not params:
raise TypeError(
f"Parameter list to {cls.__qualname__}[...] cannot be empty"
)
if not all(_is_typevar_like(p) for p in params):
raise TypeError(
f"Parameters to {cls.__name__}[...] must all be type variables "
f"or parameter specification variables.")
if len(set(params)) != len(params):
raise TypeError(
f"Parameters to {cls.__name__}[...] must all be unique")
else:
# Subscripting a regular Generic subclass.
for param in cls.__parameters__:
prepare = getattr(param, '__typing_prepare_subst__', None)
if prepare is not None:
params = prepare(cls, params)
_check_generic(cls, params, len(cls.__parameters__))
def __repr__(self):
if self.__covariant__:
prefix = '+'
elif self.__contravariant__:
prefix = '-'
else:
prefix = '~'
return prefix + self.__name__
def __mro_entries__(self, bases):
raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
class TypeVar(_Final, _Immutable, _BoundVarianceMixin, _PickleUsingNameMixin,
_root=True):
"""Type variable.
Usage::
T = TypeVar('T') # Can be anything
A = TypeVar('A', str, bytes) # Must be str or bytes
Type variables exist primarily for the benefit of static type
checkers. They serve as the parameters for generic types as well
as for generic function definitions. See class Generic for more
information on generic types. Generic functions work as follows:
def repeat(x: T, n: int) -> List[T]:
'''Return a list containing n references to x.'''
return [x]*n
def longest(x: A, y: A) -> A:
'''Return the longest of two strings.'''
return x if len(x) >= len(y) else y
The latter example's signature is essentially the overloading
of (str, str) -> str and (bytes, bytes) -> bytes. Also note
that if the arguments are instances of some subclass of str,
the return type is still plain str.
At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError.
Type variables defined with covariant=True or contravariant=True
can be used to declare covariant or contravariant generic types.
See PEP 484 for more details. By default generic types are invariant
in all type variables.
Type variables can be introspected. e.g.:
T.__name__ == 'T'
T.__constraints__ == ()
T.__covariant__ == False
T.__contravariant__ = False
A.__constraints__ == (str, bytes)
Note that only type variables defined in global scope can be pickled.
"""
def __init__(self, name, *constraints, bound=None,
covariant=False, contravariant=False):
self.__name__ = name
super().__init__(bound, covariant, contravariant)
if constraints and bound is not None:
raise TypeError("Constraints cannot be combined with bound=...")
if constraints and len(constraints) == 1:
raise TypeError("A single constraint is not allowed")
msg = "TypeVar(name, constraint, ...): constraints must be types."
self.__constraints__ = tuple(_type_check(t, msg) for t in constraints)
def_mod = _caller()
if def_mod != 'typing':
self.__module__ = def_mod
def __typing_subst__(self, arg):
msg = "Parameters to generic types must be types."
arg = _type_check(arg, msg, is_argument=True)
if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or
(isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))):
raise TypeError(f"{arg} is not valid as type argument")
return arg
class TypeVarTuple(_Final, _Immutable, _PickleUsingNameMixin, _root=True):
"""Type variable tuple.
Usage:
Ts = TypeVarTuple('Ts') # Can be given any name
Just as a TypeVar (type variable) is a placeholder for a single type,
a TypeVarTuple is a placeholder for an *arbitrary* number of types. For
example, if we define a generic class using a TypeVarTuple:
class C(Generic[*Ts]): ...
Then we can parameterize that class with an arbitrary number of type
arguments:
C[int] # Fine
C[int, str] # Also fine
C[()] # Even this is fine
For more details, see PEP 646.
Note that only TypeVarTuples defined in global scope can be pickled.
"""
def __init__(self, name):
self.__name__ = name
# Used for pickling.
def_mod = _caller()
if def_mod != 'typing':
self.__module__ = def_mod
def __iter__(self):
yield Unpack[self]
def __repr__(self):
return self.__name__
def __typing_subst__(self, arg):
raise TypeError("Substitution of bare TypeVarTuple is not supported")
def __typing_prepare_subst__(self, alias, args):
params = alias.__parameters__
typevartuple_index = params.index(self)
for param in params[typevartuple_index + 1:]:
new_args = []
for param, new_arg in zip(cls.__parameters__, params):
if isinstance(param, TypeVarTuple):
raise TypeError(f"More than one TypeVarTuple parameter in {alias}")
new_args.extend(new_arg)
else:
new_args.append(new_arg)
params = tuple(new_args)
alen = len(args)
plen = len(params)
left = typevartuple_index
right = plen - typevartuple_index - 1
var_tuple_index = None
fillarg = None
for k, arg in enumerate(args):
if not isinstance(arg, type):
subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
if subargs and len(subargs) == 2 and subargs[-1] is ...:
if var_tuple_index is not None:
raise TypeError("More than one unpacked arbitrary-length tuple argument")
var_tuple_index = k
fillarg = subargs[0]
if var_tuple_index is not None:
left = min(left, var_tuple_index)
right = min(right, alen - var_tuple_index - 1)
elif left + right > alen:
raise TypeError(f"Too few arguments for {alias};"
f" actual {alen}, expected at least {plen-1}")
return (
*args[:left],
*([fillarg]*(typevartuple_index - left)),
tuple(args[left: alen - right]),
*([fillarg]*(plen - right - left - typevartuple_index - 1)),
*args[alen - right:],
)
def __mro_entries__(self, bases):
raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
return _GenericAlias(cls, params)
class ParamSpecArgs(_Final, _Immutable, _root=True):
"""The args for a ParamSpec object.
def _generic_init_subclass(cls, *args, **kwargs):
super(Generic, cls).__init_subclass__(*args, **kwargs)
tvars = []
if '__orig_bases__' in cls.__dict__:
error = Generic in cls.__orig_bases__
else:
error = (Generic in cls.__bases__ and
cls.__name__ != 'Protocol' and
type(cls) != _TypedDictMeta)
if error:
raise TypeError("Cannot inherit from plain Generic")
if '__orig_bases__' in cls.__dict__:
tvars = _collect_parameters(cls.__orig_bases__)
# Look for Generic[T1, ..., Tn].
# If found, tvars must be a subset of it.
# If not found, tvars is it.
# Also check for and reject plain Generic,
# and reject multiple Generic[...].
gvars = None
for base in cls.__orig_bases__:
if (isinstance(base, _GenericAlias) and
base.__origin__ is Generic):
if gvars is not None:
raise TypeError(
"Cannot inherit from Generic[...] multiple times.")
gvars = base.__parameters__
if gvars is not None:
tvarset = set(tvars)
gvarset = set(gvars)
if not tvarset <= gvarset:
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
s_args = ', '.join(str(g) for g in gvars)
raise TypeError(f"Some type variables ({s_vars}) are"
f" not listed in Generic[{s_args}]")
tvars = gvars
cls.__parameters__ = tuple(tvars)
Given a ParamSpec object P, P.args is an instance of ParamSpecArgs.
ParamSpecArgs objects have a reference back to their ParamSpec:
P.args.__origin__ is P
This type is meant for runtime introspection and has no special meaning to
static type checkers.
"""
def __init__(self, origin):
self.__origin__ = origin
def __repr__(self):
return f"{self.__origin__.__name__}.args"
def __eq__(self, other):
if not isinstance(other, ParamSpecArgs):
return NotImplemented
return self.__origin__ == other.__origin__
def __mro_entries__(self, bases):
raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
class ParamSpecKwargs(_Final, _Immutable, _root=True):
"""The kwargs for a ParamSpec object.
Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs.
ParamSpecKwargs objects have a reference back to their ParamSpec:
P.kwargs.__origin__ is P
This type is meant for runtime introspection and has no special meaning to
static type checkers.
"""
def __init__(self, origin):
self.__origin__ = origin
def __repr__(self):
return f"{self.__origin__.__name__}.kwargs"
def __eq__(self, other):
if not isinstance(other, ParamSpecKwargs):
return NotImplemented
return self.__origin__ == other.__origin__
def __mro_entries__(self, bases):
raise TypeError(f"Cannot subclass an instance of {type(self).__name__}")
class ParamSpec(_Final, _Immutable, _BoundVarianceMixin, _PickleUsingNameMixin,
_root=True):
"""Parameter specification variable.
Usage::
P = ParamSpec('P')
Parameter specification variables exist primarily for the benefit of static
type checkers. They are used to forward the parameter types of one
callable to another callable, a pattern commonly found in higher order
functions and decorators. They are only valid when used in ``Concatenate``,
or as the first argument to ``Callable``, or as parameters for user-defined
Generics. See class Generic for more information on generic types. An
example for annotating a decorator::
T = TypeVar('T')
P = ParamSpec('P')
def add_logging(f: Callable[P, T]) -> Callable[P, T]:
'''A type-safe decorator to add logging to a function.'''
def inner(*args: P.args, **kwargs: P.kwargs) -> T:
logging.info(f'{f.__name__} was called')
return f(*args, **kwargs)
return inner
@add_logging
def add_two(x: float, y: float) -> float:
'''Add two numbers together.'''
return x + y
Parameter specification variables defined with covariant=True or
contravariant=True can be used to declare covariant or contravariant
generic types. These keyword arguments are valid, but their actual semantics
are yet to be decided. See PEP 612 for details.
Parameter specification variables can be introspected. e.g.:
P.__name__ == 'P'
P.__bound__ == None
P.__covariant__ == False
P.__contravariant__ == False
Note that only parameter specification variables defined in global scope can
be pickled.
"""
@property
def args(self):
return ParamSpecArgs(self)
@property
def kwargs(self):
return ParamSpecKwargs(self)
def __init__(self, name, *, bound=None, covariant=False, contravariant=False):
self.__name__ = name
super().__init__(bound, covariant, contravariant)
def_mod = _caller()
if def_mod != 'typing':
self.__module__ = def_mod
def __typing_subst__(self, arg):
if isinstance(arg, (list, tuple)):
arg = tuple(_type_check(a, "Expected a type.") for a in arg)
elif not _is_param_expr(arg):
raise TypeError(f"Expected a list of types, an ellipsis, "
f"ParamSpec, or Concatenate. Got {arg}")
return arg
def __typing_prepare_subst__(self, alias, args):
params = alias.__parameters__
i = params.index(self)
if i >= len(args):
raise TypeError(f"Too few arguments for {alias}")
# Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612.
if len(params) == 1 and not _is_param_expr(args[0]):
assert i == 0
args = (args,)
# Convert lists to tuples to help other libraries cache the results.
elif isinstance(args[i], list):
args = (*args[:i], tuple(args[i]), *args[i+1:])
return args
def _is_dunder(attr):
return attr.startswith('__') and attr.endswith('__')
@ -1812,113 +1656,6 @@ class _UnpackGenericAlias(_GenericAlias, _root=True):
return isinstance(self.__args__[0], TypeVarTuple)
class Generic:
"""Abstract base class for generic types.
A generic type is typically declared by inheriting from
this class parameterized with one or more type variables.
For example, a generic mapping type might be defined as::
class Mapping(Generic[KT, VT]):
def __getitem__(self, key: KT) -> VT:
...
# Etc.
This class can then be used as follows::
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
try:
return mapping[key]
except KeyError:
return default
"""
__slots__ = ()
_is_protocol = False
@_tp_cache
def __class_getitem__(cls, params):
"""Parameterizes a generic class.
At least, parameterizing a generic class is the *main* thing this method
does. For example, for some generic class `Foo`, this is called when we
do `Foo[int]` - there, with `cls=Foo` and `params=int`.
However, note that this method is also called when defining generic
classes in the first place with `class Foo(Generic[T]): ...`.
"""
if not isinstance(params, tuple):
params = (params,)
params = tuple(_type_convert(p) for p in params)
if cls in (Generic, Protocol):
# Generic and Protocol can only be subscripted with unique type variables.
if not params:
raise TypeError(
f"Parameter list to {cls.__qualname__}[...] cannot be empty"
)
if not all(_is_typevar_like(p) for p in params):
raise TypeError(
f"Parameters to {cls.__name__}[...] must all be type variables "
f"or parameter specification variables.")
if len(set(params)) != len(params):
raise TypeError(
f"Parameters to {cls.__name__}[...] must all be unique")
else:
# Subscripting a regular Generic subclass.
for param in cls.__parameters__:
prepare = getattr(param, '__typing_prepare_subst__', None)
if prepare is not None:
params = prepare(cls, params)
_check_generic(cls, params, len(cls.__parameters__))
new_args = []
for param, new_arg in zip(cls.__parameters__, params):
if isinstance(param, TypeVarTuple):
new_args.extend(new_arg)
else:
new_args.append(new_arg)
params = tuple(new_args)
return _GenericAlias(cls, params)
def __init_subclass__(cls, *args, **kwargs):
super().__init_subclass__(*args, **kwargs)
tvars = []
if '__orig_bases__' in cls.__dict__:
error = Generic in cls.__orig_bases__
else:
error = (Generic in cls.__bases__ and
cls.__name__ != 'Protocol' and
type(cls) != _TypedDictMeta)
if error:
raise TypeError("Cannot inherit from plain Generic")
if '__orig_bases__' in cls.__dict__:
tvars = _collect_parameters(cls.__orig_bases__)
# Look for Generic[T1, ..., Tn].
# If found, tvars must be a subset of it.
# If not found, tvars is it.
# Also check for and reject plain Generic,
# and reject multiple Generic[...].
gvars = None
for base in cls.__orig_bases__:
if (isinstance(base, _GenericAlias) and
base.__origin__ is Generic):
if gvars is not None:
raise TypeError(
"Cannot inherit from Generic[...] multiple times.")
gvars = base.__parameters__
if gvars is not None:
tvarset = set(tvars)
gvarset = set(gvars)
if not tvarset <= gvarset:
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
s_args = ', '.join(str(g) for g in gvars)
raise TypeError(f"Some type variables ({s_vars}) are"
f" not listed in Generic[{s_args}]")
tvars = gvars
cls.__parameters__ = tuple(tvars)
class _TypingEllipsis:
"""Internal placeholder for ... (ellipsis)."""
@ -2024,6 +1761,18 @@ def _lazy_load_getattr_static():
_cleanups.append(_lazy_load_getattr_static.cache_clear)
def _pickle_psargs(psargs):
return ParamSpecArgs, (psargs.__origin__,)
copyreg.pickle(ParamSpecArgs, _pickle_psargs)
def _pickle_pskwargs(pskwargs):
return ParamSpecKwargs, (pskwargs.__origin__,)
copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs)
del _pickle_psargs, _pickle_pskwargs
class _ProtocolMeta(ABCMeta):
# This metaclass is really unfortunate and exists only because of
@ -2943,7 +2692,7 @@ class NamedTupleMeta(type):
module=ns['__module__'])
nm_tpl.__bases__ = bases
if Generic in bases:
class_getitem = Generic.__class_getitem__.__func__
class_getitem = _generic_class_getitem
nm_tpl.__class_getitem__ = classmethod(class_getitem)
# update from user namespace without overriding special namedtuple attributes
for key in ns:

View File

@ -479,6 +479,7 @@ OBJECT_OBJS= \
Objects/structseq.o \
Objects/tupleobject.o \
Objects/typeobject.o \
Objects/typevarobject.o \
Objects/unicodeobject.o \
Objects/unicodectype.o \
Objects/unionobject.o \
@ -1767,6 +1768,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_tracemalloc.h \
$(srcdir)/Include/internal/pycore_tuple.h \
$(srcdir)/Include/internal/pycore_typeobject.h \
$(srcdir)/Include/internal/pycore_typevarobject.h \
$(srcdir)/Include/internal/pycore_ucnhash.h \
$(srcdir)/Include/internal/pycore_unionobject.h \
$(srcdir)/Include/internal/pycore_unicodeobject.h \

View File

@ -0,0 +1,23 @@
Implement :pep:`695`, adding syntactic support for generic classes, generic
functions, and type aliases.
A new ``type X = ...`` syntax is added for type aliases, which resolves at
runtime to an instance of the new class ``typing.TypeAliasType``.
The value is lazily evaluated and is accessible through the ``.__value__``
attribute. This is implemented as a new AST node ``ast.TypeAlias``.
New syntax (``class X[T]: ...``, ``def func[T](): ...``) is added for defining
generic functions and classes. This is implemented as a new
``typeparams`` attribute on the AST nodes for classes and functions.
This node holds instances of the new AST classes ``ast.TypeVar``,
``ast.ParamSpec``, and ``ast.TypeVarTuple``.
``typing.TypeVar``, ``typing.ParamSpec``, ``typing.ParamSpecArgs``,
``typing.ParamSpecKwargs``, ``typing.TypeVarTuple``, and
``typing.Generic`` are now implemented in C rather than Python.
There are new bytecode instructions ``LOAD_LOCALS``,
``LOAD_CLASSDICT_OR_GLOBAL``, and ``LOAD_CLASSDICT_OR_DEREF``
to support correct resolution of names in class namespaces.
Patch by Eric Traut, Larry Hastings, and Jelle Zijlstra.

View File

@ -21,6 +21,7 @@ itertools itertoolsmodule.c
_sre _sre/sre.c
_thread _threadmodule.c
time timemodule.c
_typing _typingmodule.c
_weakref _weakref.c
# commonly used core modules

View File

@ -41,7 +41,6 @@
@MODULE__QUEUE_TRUE@_queue _queuemodule.c
@MODULE__RANDOM_TRUE@_random _randommodule.c
@MODULE__STRUCT_TRUE@_struct _struct.c
@MODULE__TYPING_TRUE@_typing _typingmodule.c
@MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c
@MODULE__XXINTERPCHANNELS_TRUE@_xxinterpchannels _xxinterpchannelsmodule.c
@MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c

View File

@ -1,6 +1,11 @@
/* typing accelerator C extension: _typing module. */
#ifndef Py_BUILD_CORE
#define Py_BUILD_CORE
#endif
#include "Python.h"
#include "internal/pycore_interp.h"
#include "clinic/_typingmodule.c.h"
/*[clinic input]
@ -35,7 +40,30 @@ static PyMethodDef typing_methods[] = {
PyDoc_STRVAR(typing_doc,
"Accelerators for the typing module.\n");
static int
_typing_exec(PyObject *m)
{
PyInterpreterState *interp = PyInterpreterState_Get();
#define EXPORT_TYPE(name, typename) \
if (PyModule_AddObjectRef(m, name, \
(PyObject *)interp->cached_objects.typename) < 0) { \
return -1; \
}
EXPORT_TYPE("TypeVar", typevar_type);
EXPORT_TYPE("TypeVarTuple", typevartuple_type);
EXPORT_TYPE("ParamSpec", paramspec_type);
EXPORT_TYPE("ParamSpecArgs", paramspecargs_type);
EXPORT_TYPE("ParamSpecKwargs", paramspeckwargs_type);
EXPORT_TYPE("TypeAliasType", typealias_type);
EXPORT_TYPE("Generic", generic_type);
#undef EXPORT_TYPE
return 0;
}
static struct PyModuleDef_Slot _typingmodule_slots[] = {
{Py_mod_exec, _typing_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{0, NULL}
};

786
Objects/clinic/typevarobject.c.h generated Normal file
View File

@ -0,0 +1,786 @@
/*[clinic input]
preserve
[clinic start generated code]*/
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
PyDoc_STRVAR(typevar_new__doc__,
"typevar(name, *constraints, *, bound=None, covariant=False,\n"
" contravariant=False, infer_variance=False)\n"
"--\n"
"\n"
"Create a TypeVar.");
static PyObject *
typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints,
PyObject *bound, int covariant, int contravariant,
int infer_variance);
static PyObject *
typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 5
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typevar",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[6];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
PyObject *name;
PyObject *constraints = NULL;
PyObject *bound = Py_None;
int covariant = 0;
int contravariant = 0;
int infer_variance = 0;
fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, 1, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("typevar", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
constraints = fastargs[1];
if (!noptargs) {
goto skip_optional_kwonly;
}
if (fastargs[2]) {
bound = fastargs[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[3]) {
covariant = PyObject_IsTrue(fastargs[3]);
if (covariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[4]) {
contravariant = PyObject_IsTrue(fastargs[4]);
if (contravariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
infer_variance = PyObject_IsTrue(fastargs[5]);
if (infer_variance < 0) {
goto exit;
}
skip_optional_kwonly:
return_value = typevar_new_impl(type, name, constraints, bound, covariant, contravariant, infer_variance);
exit:
Py_XDECREF(constraints);
return return_value;
}
PyDoc_STRVAR(typevar_typing_subst__doc__,
"__typing_subst__($self, /, arg)\n"
"--\n"
"\n");
#define TYPEVAR_TYPING_SUBST_METHODDEF \
{"__typing_subst__", _PyCFunction_CAST(typevar_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevar_typing_subst__doc__},
static PyObject *
typevar_typing_subst_impl(typevarobject *self, PyObject *arg);
static PyObject *
typevar_typing_subst(typevarobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(arg), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"arg", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *arg;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
arg = args[0];
return_value = typevar_typing_subst_impl(self, arg);
exit:
return return_value;
}
PyDoc_STRVAR(typevar_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define TYPEVAR_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)typevar_reduce, METH_NOARGS, typevar_reduce__doc__},
static PyObject *
typevar_reduce_impl(typevarobject *self);
static PyObject *
typevar_reduce(typevarobject *self, PyObject *Py_UNUSED(ignored))
{
return typevar_reduce_impl(self);
}
PyDoc_STRVAR(paramspecargs_new__doc__,
"paramspecargs(origin)\n"
"--\n"
"\n"
"Create a ParamSpecArgs object.");
static PyObject *
paramspecargs_new_impl(PyTypeObject *type, PyObject *origin);
static PyObject *
paramspecargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(origin), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"origin", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "paramspecargs",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *origin;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
origin = fastargs[0];
return_value = paramspecargs_new_impl(type, origin);
exit:
return return_value;
}
PyDoc_STRVAR(paramspeckwargs_new__doc__,
"paramspeckwargs(origin)\n"
"--\n"
"\n"
"Create a ParamSpecKwargs object.");
static PyObject *
paramspeckwargs_new_impl(PyTypeObject *type, PyObject *origin);
static PyObject *
paramspeckwargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(origin), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"origin", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "paramspeckwargs",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *origin;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
origin = fastargs[0];
return_value = paramspeckwargs_new_impl(type, origin);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_new__doc__,
"paramspec(name, *, bound=None, covariant=False, contravariant=False,\n"
" infer_variance=False)\n"
"--\n"
"\n"
"Create a ParamSpec object.");
static PyObject *
paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound,
int covariant, int contravariant, int infer_variance);
static PyObject *
paramspec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 5
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "paramspec",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[5];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
PyObject *name;
PyObject *bound = Py_None;
int covariant = 0;
int contravariant = 0;
int infer_variance = 0;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("paramspec", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
if (fastargs[1]) {
bound = fastargs[1];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[2]) {
covariant = PyObject_IsTrue(fastargs[2]);
if (covariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[3]) {
contravariant = PyObject_IsTrue(fastargs[3]);
if (contravariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
infer_variance = PyObject_IsTrue(fastargs[4]);
if (infer_variance < 0) {
goto exit;
}
skip_optional_kwonly:
return_value = paramspec_new_impl(type, name, bound, covariant, contravariant, infer_variance);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_typing_subst__doc__,
"__typing_subst__($self, /, arg)\n"
"--\n"
"\n");
#define PARAMSPEC_TYPING_SUBST_METHODDEF \
{"__typing_subst__", _PyCFunction_CAST(paramspec_typing_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_subst__doc__},
static PyObject *
paramspec_typing_subst_impl(paramspecobject *self, PyObject *arg);
static PyObject *
paramspec_typing_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(arg), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"arg", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *arg;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
arg = args[0];
return_value = paramspec_typing_subst_impl(self, arg);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_typing_prepare_subst__doc__,
"__typing_prepare_subst__($self, /, alias, args)\n"
"--\n"
"\n");
#define PARAMSPEC_TYPING_PREPARE_SUBST_METHODDEF \
{"__typing_prepare_subst__", _PyCFunction_CAST(paramspec_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_prepare_subst__doc__},
static PyObject *
paramspec_typing_prepare_subst_impl(paramspecobject *self, PyObject *alias,
PyObject *args);
static PyObject *
paramspec_typing_prepare_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(alias), &_Py_ID(args), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"alias", "args", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_prepare_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject *alias;
PyObject *__clinic_args;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
if (!args) {
goto exit;
}
alias = args[0];
__clinic_args = args[1];
return_value = paramspec_typing_prepare_subst_impl(self, alias, __clinic_args);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define PARAMSPEC_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)paramspec_reduce, METH_NOARGS, paramspec_reduce__doc__},
static PyObject *
paramspec_reduce_impl(paramspecobject *self);
static PyObject *
paramspec_reduce(paramspecobject *self, PyObject *Py_UNUSED(ignored))
{
return paramspec_reduce_impl(self);
}
PyDoc_STRVAR(typevartuple__doc__,
"typevartuple(name)\n"
"--\n"
"\n"
"Create a new TypeVarTuple with the given name.");
static PyObject *
typevartuple_impl(PyTypeObject *type, PyObject *name);
static PyObject *
typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typevartuple",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *name;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("typevartuple", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
return_value = typevartuple_impl(type, name);
exit:
return return_value;
}
PyDoc_STRVAR(typevartuple_typing_subst__doc__,
"__typing_subst__($self, /, arg)\n"
"--\n"
"\n");
#define TYPEVARTUPLE_TYPING_SUBST_METHODDEF \
{"__typing_subst__", _PyCFunction_CAST(typevartuple_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_subst__doc__},
static PyObject *
typevartuple_typing_subst_impl(typevartupleobject *self, PyObject *arg);
static PyObject *
typevartuple_typing_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(arg), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"arg", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *arg;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
arg = args[0];
return_value = typevartuple_typing_subst_impl(self, arg);
exit:
return return_value;
}
PyDoc_STRVAR(typevartuple_typing_prepare_subst__doc__,
"__typing_prepare_subst__($self, /, alias, args)\n"
"--\n"
"\n");
#define TYPEVARTUPLE_TYPING_PREPARE_SUBST_METHODDEF \
{"__typing_prepare_subst__", _PyCFunction_CAST(typevartuple_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_prepare_subst__doc__},
static PyObject *
typevartuple_typing_prepare_subst_impl(typevartupleobject *self,
PyObject *alias, PyObject *args);
static PyObject *
typevartuple_typing_prepare_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(alias), &_Py_ID(args), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"alias", "args", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_prepare_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject *alias;
PyObject *__clinic_args;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
if (!args) {
goto exit;
}
alias = args[0];
__clinic_args = args[1];
return_value = typevartuple_typing_prepare_subst_impl(self, alias, __clinic_args);
exit:
return return_value;
}
PyDoc_STRVAR(typevartuple_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define TYPEVARTUPLE_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)typevartuple_reduce, METH_NOARGS, typevartuple_reduce__doc__},
static PyObject *
typevartuple_reduce_impl(typevartupleobject *self);
static PyObject *
typevartuple_reduce(typevartupleobject *self, PyObject *Py_UNUSED(ignored))
{
return typevartuple_reduce_impl(self);
}
PyDoc_STRVAR(typealias_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define TYPEALIAS_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)typealias_reduce, METH_NOARGS, typealias_reduce__doc__},
static PyObject *
typealias_reduce_impl(typealiasobject *self);
static PyObject *
typealias_reduce(typealiasobject *self, PyObject *Py_UNUSED(ignored))
{
return typealias_reduce_impl(self);
}
PyDoc_STRVAR(typealias_new__doc__,
"typealias(name, value, *, type_params=<unrepresentable>)\n"
"--\n"
"\n"
"Create a TypeAliasType.");
static PyObject *
typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
PyObject *type_params);
static PyObject *
typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "value", "type_params", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typealias",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[3];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2;
PyObject *name;
PyObject *value;
PyObject *type_params = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("typealias", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
value = fastargs[1];
if (!noptargs) {
goto skip_optional_kwonly;
}
type_params = fastargs[2];
skip_optional_kwonly:
return_value = typealias_new_impl(type, name, value, type_params);
exit:
return return_value;
}
/*[clinic end generated code: output=807bcd30ebd10ac3 input=a9049054013a1b77]*/

View File

@ -127,6 +127,7 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr)
PyErr_Clear();
}
op->func_annotations = NULL;
op->func_typeparams = NULL;
op->vectorcall = _PyFunction_Vectorcall;
op->func_version = 0;
_PyObject_GC_TRACK(op);
@ -202,6 +203,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
op->func_weakreflist = NULL;
op->func_module = module;
op->func_annotations = NULL;
op->func_typeparams = NULL;
op->vectorcall = _PyFunction_Vectorcall;
op->func_version = 0;
_PyObject_GC_TRACK(op);
@ -652,6 +654,28 @@ func_set_annotations(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(igno
return 0;
}
static PyObject *
func_get_type_params(PyFunctionObject *op, void *Py_UNUSED(ignored))
{
if (op->func_typeparams == NULL) {
return PyTuple_New(0);
}
assert(PyTuple_Check(op->func_typeparams));
return Py_NewRef(op->func_typeparams);
}
PyObject *
_Py_set_function_type_params(PyThreadState *Py_UNUSED(ignored), PyObject *func,
PyObject *type_params)
{
assert(PyFunction_Check(func));
assert(PyTuple_Check(type_params));
PyFunctionObject *f = (PyFunctionObject *)func;
Py_XSETREF(f->func_typeparams, Py_NewRef(type_params));
return Py_NewRef(func);
}
static PyGetSetDef func_getsetlist[] = {
{"__code__", (getter)func_get_code, (setter)func_set_code},
{"__defaults__", (getter)func_get_defaults,
@ -663,6 +687,7 @@ static PyGetSetDef func_getsetlist[] = {
{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
{"__name__", (getter)func_get_name, (setter)func_set_name},
{"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname},
{"__type_params__", (getter)func_get_type_params, NULL},
{NULL} /* Sentinel */
};
@ -783,6 +808,7 @@ func_clear(PyFunctionObject *op)
Py_CLEAR(op->func_dict);
Py_CLEAR(op->func_closure);
Py_CLEAR(op->func_annotations);
Py_CLEAR(op->func_typeparams);
// Don't Py_CLEAR(op->func_code), since code is always required
// to be non-NULL. Similarly, name and qualname shouldn't be NULL.
// However, name and qualname could be str subclasses, so they
@ -837,6 +863,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
Py_VISIT(f->func_dict);
Py_VISIT(f->func_closure);
Py_VISIT(f->func_annotations);
Py_VISIT(f->func_typeparams);
Py_VISIT(f->func_qualname);
return 0;
}

View File

@ -14,6 +14,7 @@
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_symtable.h" // PySTEntry_Type
#include "pycore_typevarobject.h" // _PyTypeVar_Type etc., _Py_initialize_generic
#include "pycore_typeobject.h" // _PyBufferWrapper_Type
#include "pycore_unionobject.h" // _PyUnion_Type
#include "pycore_interpreteridobject.h" // _PyInterpreterID_Type
@ -2139,6 +2140,11 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
}
}
// Must be after static types are initialized
if (_Py_initialize_generic(interp) < 0) {
return _PyStatus_ERR("Can't initialize generic types");
}
return _PyStatus_OK();
}

View File

@ -1460,6 +1460,18 @@ type_get_annotations(PyTypeObject *type, void *context)
return annotations;
}
static PyObject *
type_get_type_params(PyTypeObject *type, void *context)
{
PyObject *params = PyDict_GetItem(lookup_tp_dict(type), &_Py_ID(__type_params__));
if (params) {
return Py_NewRef(params);
}
return PyTuple_New(0);
}
static int
type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
{
@ -1536,6 +1548,7 @@ static PyGetSetDef type_getsets[] = {
{"__doc__", (getter)type_get_doc, (setter)type_set_doc, NULL},
{"__text_signature__", (getter)type_get_text_signature, NULL, NULL},
{"__annotations__", (getter)type_get_annotations, (setter)type_set_annotations, NULL},
{"__type_params__", (getter)type_get_type_params, NULL, NULL},
{0}
};
@ -3130,11 +3143,12 @@ type_new_copy_slots(type_new_ctx *ctx, PyObject *dict)
goto error;
}
if (r > 0) {
/* CPython inserts __qualname__ and __classcell__ (when needed)
/* CPython inserts these names (when needed)
into the namespace when creating a class. They will be deleted
below so won't act as class variables. */
if (!_PyUnicode_Equal(slot, &_Py_ID(__qualname__)) &&
!_PyUnicode_Equal(slot, &_Py_ID(__classcell__)))
!_PyUnicode_Equal(slot, &_Py_ID(__classcell__)) &&
!_PyUnicode_Equal(slot, &_Py_ID(__classdictcell__)))
{
PyErr_Format(PyExc_ValueError,
"%R in __slots__ conflicts with class variable",
@ -3585,6 +3599,32 @@ type_new_set_classcell(PyTypeObject *type)
return 0;
}
static int
type_new_set_classdictcell(PyTypeObject *type)
{
PyObject *dict = lookup_tp_dict(type);
PyObject *cell = PyDict_GetItemWithError(dict, &_Py_ID(__classdictcell__));
if (cell == NULL) {
if (PyErr_Occurred()) {
return -1;
}
return 0;
}
/* At least one method requires a reference to the dict of its defining class */
if (!PyCell_Check(cell)) {
PyErr_Format(PyExc_TypeError,
"__classdictcell__ must be a nonlocal cell, not %.200R",
Py_TYPE(cell));
return -1;
}
(void)PyCell_Set(cell, (PyObject *)dict);
if (PyDict_DelItem(dict, &_Py_ID(__classdictcell__)) < 0) {
return -1;
}
return 0;
}
static int
type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type)
@ -3629,6 +3669,9 @@ type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type)
if (type_new_set_classcell(type) < 0) {
return -1;
}
if (type_new_set_classdictcell(type) < 0) {
return -1;
}
return 0;
}

1620
Objects/typevarobject.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -147,10 +147,14 @@ get_types(PyObject **obj, Py_ssize_t *size)
static int
is_unionable(PyObject *obj)
{
return (obj == Py_None ||
if (obj == Py_None ||
PyType_Check(obj) ||
_PyGenericAlias_Check(obj) ||
_PyUnion_Check(obj));
_PyUnion_Check(obj)) {
return 1;
}
PyInterpreterState *interp = PyInterpreterState_Get();
return Py_IS_TYPE(obj, interp->cached_objects.typealias_type);
}
PyObject *

View File

@ -159,6 +159,7 @@
<ClCompile Include="..\Objects\structseq.c" />
<ClCompile Include="..\Objects\tupleobject.c" />
<ClCompile Include="..\Objects\typeobject.c" />
<ClCompile Include="..\Objects\typevarobject.c" />
<ClCompile Include="..\Objects\unicodectype.c" />
<ClCompile Include="..\Objects\unicodeobject.c" />
<ClCompile Include="..\Objects\unionobject.c" />

View File

@ -269,6 +269,7 @@
<ClInclude Include="..\Include\internal\pycore_tracemalloc.h" />
<ClInclude Include="..\Include\internal\pycore_tuple.h" />
<ClInclude Include="..\Include\internal\pycore_typeobject.h" />
<ClInclude Include="..\Include\internal\pycore_typevarobject.h" />
<ClInclude Include="..\Include\internal\pycore_ucnhash.h" />
<ClInclude Include="..\Include\internal\pycore_unionobject.h" />
<ClInclude Include="..\Include\internal\pycore_unicodeobject.h" />
@ -481,6 +482,7 @@
<ClCompile Include="..\Objects\structseq.c" />
<ClCompile Include="..\Objects\tupleobject.c" />
<ClCompile Include="..\Objects\typeobject.c" />
<ClCompile Include="..\Objects\typevarobject.c" />
<ClCompile Include="..\Objects\unicodectype.c" />
<ClCompile Include="..\Objects\unicodeobject.c" />
<ClCompile Include="..\Objects\unionobject.c" />

View File

@ -705,6 +705,9 @@
<ClInclude Include="..\Include\internal\pycore_typeobject.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_typevarobject.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_ucnhash.h">
<Filter>Include\internal</Filter>
</ClInclude>
@ -1364,6 +1367,9 @@
<ClCompile Include="..\Objects\genericaliasobject.c">
<Filter>Objects</Filter>
</ClCompile>
<ClCompile Include="..\Objects\typevarobject.c">
<Filter>Objects</Filter>
</ClCompile>
<ClCompile Include="..\Objects\unionobject.c">
<Filter>Objects</Filter>
</ClCompile>

View File

@ -8,14 +8,15 @@ module Python
| Expression(expr body)
| FunctionType(expr* argtypes, expr returns)
stmt = FunctionDef(identifier name, arguments args,
stmt = FunctionDef(identifier name, typeparam* typeparams, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| AsyncFunctionDef(identifier name, arguments args,
| AsyncFunctionDef(identifier name, typeparam* typeparams, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| ClassDef(identifier name,
typeparam* typeparams,
expr* bases,
keyword* keywords,
stmt* body,
@ -24,6 +25,7 @@ module Python
| Delete(expr* targets)
| Assign(expr* targets, expr value, string? type_comment)
| TypeAlias(expr name, typeparam* typeparams, expr value)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
@ -142,4 +144,9 @@ module Python
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
typeparam = TypeVar(identifier name, expr? bound)
| ParamSpec(identifier name)
| TypeVarTuple(identifier name)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
}

View File

@ -752,7 +752,8 @@ _PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty f
assert(function_def != NULL);
if (function_def->kind == AsyncFunctionDef_kind) {
return _PyAST_AsyncFunctionDef(
function_def->v.FunctionDef.name, function_def->v.FunctionDef.args,
function_def->v.FunctionDef.name, function_def->v.FunctionDef.typeparams,
function_def->v.FunctionDef.args,
function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns,
function_def->v.FunctionDef.type_comment, function_def->lineno,
function_def->col_offset, function_def->end_lineno, function_def->end_col_offset,
@ -760,7 +761,8 @@ _PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty f
}
return _PyAST_FunctionDef(
function_def->v.FunctionDef.name, function_def->v.FunctionDef.args,
function_def->v.FunctionDef.name, function_def->v.FunctionDef.typeparams,
function_def->v.FunctionDef.args,
function_def->v.FunctionDef.body, decorators,
function_def->v.FunctionDef.returns,
function_def->v.FunctionDef.type_comment, function_def->lineno,
@ -774,8 +776,9 @@ _PyPegen_class_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty clas
{
assert(class_def != NULL);
return _PyAST_ClassDef(
class_def->v.ClassDef.name, class_def->v.ClassDef.bases,
class_def->v.ClassDef.keywords, class_def->v.ClassDef.body, decorators,
class_def->v.ClassDef.name, class_def->v.ClassDef.typeparams,
class_def->v.ClassDef.bases, class_def->v.ClassDef.keywords,
class_def->v.ClassDef.body, decorators,
class_def->lineno, class_def->col_offset, class_def->end_lineno,
class_def->end_col_offset, p->arena);
}

9091
Parser/parser.c generated

File diff suppressed because it is too large Load Diff

767
Python/Python-ast.c generated

File diff suppressed because it is too large Load Diff

View File

@ -17,10 +17,12 @@ struct validator {
static int validate_stmts(struct validator *, asdl_stmt_seq *);
static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int);
static int validate_patterns(struct validator *, asdl_pattern_seq *, int);
static int validate_typeparams(struct validator *, asdl_typeparam_seq *);
static int _validate_nonempty_seq(asdl_seq *, const char *, const char *);
static int validate_stmt(struct validator *, stmt_ty);
static int validate_expr(struct validator *, expr_ty, expr_context_ty);
static int validate_pattern(struct validator *, pattern_ty, int);
static int validate_typeparam(struct validator *, typeparam_ty);
#define VALIDATE_POSITIONS(node) \
if (node->lineno > node->end_lineno) { \
@ -726,6 +728,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
switch (stmt->kind) {
case FunctionDef_kind:
ret = validate_body(state, stmt->v.FunctionDef.body, "FunctionDef") &&
validate_typeparams(state, stmt->v.FunctionDef.typeparams) &&
validate_arguments(state, stmt->v.FunctionDef.args) &&
validate_exprs(state, stmt->v.FunctionDef.decorator_list, Load, 0) &&
(!stmt->v.FunctionDef.returns ||
@ -733,6 +736,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
break;
case ClassDef_kind:
ret = validate_body(state, stmt->v.ClassDef.body, "ClassDef") &&
validate_typeparams(state, stmt->v.ClassDef.typeparams) &&
validate_exprs(state, stmt->v.ClassDef.bases, Load, 0) &&
validate_keywords(state, stmt->v.ClassDef.keywords) &&
validate_exprs(state, stmt->v.ClassDef.decorator_list, Load, 0);
@ -763,6 +767,11 @@ validate_stmt(struct validator *state, stmt_ty stmt)
validate_expr(state, stmt->v.AnnAssign.value, Load)) &&
validate_expr(state, stmt->v.AnnAssign.annotation, Load);
break;
case TypeAlias_kind:
ret = validate_expr(state, stmt->v.TypeAlias.name, Store) &&
validate_typeparams(state, stmt->v.TypeAlias.typeparams) &&
validate_expr(state, stmt->v.TypeAlias.value, Load);
break;
case For_kind:
ret = validate_expr(state, stmt->v.For.target, Store) &&
validate_expr(state, stmt->v.For.iter, Load) &&
@ -910,6 +919,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
break;
case AsyncFunctionDef_kind:
ret = validate_body(state, stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
validate_typeparams(state, stmt->v.AsyncFunctionDef.typeparams) &&
validate_arguments(state, stmt->v.AsyncFunctionDef.args) &&
validate_exprs(state, stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
(!stmt->v.AsyncFunctionDef.returns ||
@ -982,6 +992,41 @@ validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_
return 1;
}
static int
validate_typeparam(struct validator *state, typeparam_ty tp)
{
VALIDATE_POSITIONS(tp);
int ret = -1;
switch (tp->kind) {
case TypeVar_kind:
ret = validate_name(tp->v.TypeVar.name) &&
(!tp->v.TypeVar.bound ||
validate_expr(state, tp->v.TypeVar.bound, Load));
break;
case ParamSpec_kind:
ret = validate_name(tp->v.ParamSpec.name);
break;
case TypeVarTuple_kind:
ret = validate_name(tp->v.TypeVarTuple.name);
break;
}
return ret;
}
static int
validate_typeparams(struct validator *state, asdl_typeparam_seq *tps)
{
Py_ssize_t i;
for (i = 0; i < asdl_seq_LEN(tps); i++) {
typeparam_ty tp = asdl_seq_GET(tps, i);
if (tp) {
if (!validate_typeparam(state, tp))
return 0;
}
}
return 1;
}
/* See comments in symtable.c. */
#define COMPILER_STACK_FRAME_SCALE 3

View File

@ -642,6 +642,7 @@ static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeStat
static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_typeparam(typeparam_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
#define CALL(FUNC, TYPE, ARG) \
if (!FUNC((ARG), ctx_, state)) \
@ -880,6 +881,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
switch (node_->kind) {
case FunctionDef_kind:
CALL_SEQ(astfold_typeparam, typeparam, node_->v.FunctionDef.typeparams);
CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
@ -888,6 +890,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
break;
case AsyncFunctionDef_kind:
CALL_SEQ(astfold_typeparam, typeparam, node_->v.AsyncFunctionDef.typeparams);
CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
@ -896,6 +899,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
break;
case ClassDef_kind:
CALL_SEQ(astfold_typeparam, typeparam, node_->v.ClassDef.typeparams);
CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
@ -922,6 +926,11 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
break;
case TypeAlias_kind:
CALL(astfold_expr, expr_ty, node_->v.TypeAlias.name);
CALL_SEQ(astfold_typeparam, typeparam, node_->v.TypeAlias.typeparams);
CALL(astfold_expr, expr_ty, node_->v.TypeAlias.value);
break;
case For_kind:
CALL(astfold_expr, expr_ty, node_->v.For.target);
CALL(astfold_expr, expr_ty, node_->v.For.iter);
@ -1074,6 +1083,21 @@ astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat
return 1;
}
static int
astfold_typeparam(typeparam_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
switch (node_->kind) {
case TypeVar_kind:
CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.bound);
break;
case ParamSpec_kind:
break;
case TypeVarTuple_kind:
break;
}
return 1;
}
#undef CALL
#undef CALL_OPT
#undef CALL_SEQ

View File

@ -56,7 +56,7 @@ static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub
static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;
static PyObject *list, *tuple, *dict, *owner, *set, *str, *tup, *map, *keys;
static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter;
static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc;
static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc, *locals;
static PyObject *orig, *excs, *update, *b, *fromlist, *level, *from;
static PyObject **pieces, **values;
static size_t jump;
@ -125,6 +125,7 @@ dummy_func(
PyObject *subject;
PyObject *top;
PyObject *type;
PyObject *typevars;
int values_or_none;
switch (opcode) {
@ -1002,6 +1003,7 @@ dummy_func(
}
}
inst(STORE_NAME, (v -- )) {
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
PyObject *ns = LOCALS();
@ -1158,31 +1160,41 @@ dummy_func(
}
}
inst(LOAD_NAME, ( -- v)) {
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
PyObject *locals = LOCALS();
op(_LOAD_LOCALS, ( -- locals)) {
locals = LOCALS();
if (locals == NULL) {
_PyErr_Format(tstate, PyExc_SystemError,
"no locals when loading %R", name);
goto error;
_PyErr_SetString(tstate, PyExc_SystemError,
"no locals found");
ERROR_IF(true, error);
}
if (PyDict_CheckExact(locals)) {
v = PyDict_GetItemWithError(locals, name);
Py_INCREF(locals);
}
macro(LOAD_LOCALS) = _LOAD_LOCALS;
op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
if (PyDict_CheckExact(mod_or_class_dict)) {
v = PyDict_GetItemWithError(mod_or_class_dict, name);
if (v != NULL) {
Py_INCREF(v);
}
else if (_PyErr_Occurred(tstate)) {
Py_DECREF(mod_or_class_dict);
goto error;
}
}
else {
v = PyObject_GetItem(locals, name);
v = PyObject_GetItem(mod_or_class_dict, name);
if (v == NULL) {
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError))
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
Py_DECREF(mod_or_class_dict);
goto error;
}
_PyErr_Clear(tstate);
}
}
Py_DECREF(mod_or_class_dict);
if (v == NULL) {
v = PyDict_GetItemWithError(GLOBALS(), name);
if (v != NULL) {
@ -1219,6 +1231,10 @@ dummy_func(
}
}
macro(LOAD_NAME) = _LOAD_LOCALS + _LOAD_FROM_DICT_OR_GLOBALS;
macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS;
family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
LOAD_GLOBAL,
LOAD_GLOBAL_MODULE,
@ -1339,29 +1355,32 @@ dummy_func(
Py_DECREF(oldobj);
}
inst(LOAD_CLASSDEREF, ( -- value)) {
PyObject *name, *locals = LOCALS();
assert(locals);
inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {
PyObject *name;
assert(class_dict);
assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
if (PyDict_CheckExact(locals)) {
value = PyDict_GetItemWithError(locals, name);
if (PyDict_CheckExact(class_dict)) {
value = PyDict_GetItemWithError(class_dict, name);
if (value != NULL) {
Py_INCREF(value);
}
else if (_PyErr_Occurred(tstate)) {
Py_DECREF(class_dict);
goto error;
}
}
else {
value = PyObject_GetItem(locals, name);
value = PyObject_GetItem(class_dict, name);
if (value == NULL) {
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
Py_DECREF(class_dict);
goto error;
}
_PyErr_Clear(tstate);
}
}
Py_DECREF(class_dict);
if (!value) {
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);

View File

@ -147,6 +147,7 @@ enum {
COMPILER_SCOPE_ASYNC_FUNCTION,
COMPILER_SCOPE_LAMBDA,
COMPILER_SCOPE_COMPREHENSION,
COMPILER_SCOPE_TYPEPARAMS,
};
@ -231,6 +232,7 @@ instr_sequence_next_inst(instr_sequence *seq) {
&seq->s_allocated,
INITIAL_INSTR_SEQUENCE_SIZE,
sizeof(instruction)));
assert(seq->s_allocated >= 0);
assert(seq->s_used < seq->s_allocated);
return seq->s_used++;
}
@ -714,6 +716,19 @@ compiler_set_qualname(struct compiler *c)
capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1);
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
assert(parent);
if (parent->u_scope_type == COMPILER_SCOPE_TYPEPARAMS) {
/* The parent is a type parameter scope, so we need to
look at the grandparent. */
if (stack_size == 2) {
// If we're immediately within the module, we can skip
// the rest and just set the qualname to be the same as name.
u->u_metadata.u_qualname = Py_NewRef(u->u_metadata.u_name);
return SUCCESS;
}
capsule = PyList_GET_ITEM(c->c_stack, stack_size - 2);
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
assert(parent);
}
if (u->u_scope_type == COMPILER_SCOPE_FUNCTION
|| u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
@ -1114,16 +1129,18 @@ codegen_addop_j(instr_sequence *seq, location loc,
return instr_sequence_addop(seq, opcode, target.id, loc);
}
#define ADDOP(C, LOC, OP) \
RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
#define ADDOP_IN_SCOPE(C, LOC, OP) { \
if (codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)) < 0) { \
compiler_exit_scope(C); \
#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \
if ((CALL) < 0) { \
compiler_exit_scope((C)); \
return ERROR; \
} \
}
#define ADDOP(C, LOC, OP) \
RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
#define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
#define ADDOP_LOAD_CONST(C, LOC, O) \
RETURN_IF_ERROR(compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), (O)))
@ -1183,12 +1200,8 @@ codegen_addop_j(instr_sequence *seq, location loc,
#define VISIT(C, TYPE, V) \
RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), (V)));
#define VISIT_IN_SCOPE(C, TYPE, V) {\
if (compiler_visit_ ## TYPE((C), (V)) < 0) { \
compiler_exit_scope(C); \
return ERROR; \
} \
}
#define VISIT_IN_SCOPE(C, TYPE, V) \
RETURN_IF_ERROR_IN_SCOPE((C), compiler_visit_ ## TYPE((C), (V)))
#define VISIT_SEQ(C, TYPE, SEQ) { \
int _i; \
@ -1252,6 +1265,16 @@ compiler_enter_scope(struct compiler *c, identifier name,
return ERROR;
}
}
if (u->u_ste->ste_needs_classdict) {
/* Cook up an implicit __classdict__ cell. */
Py_ssize_t res;
assert(u->u_scope_type == COMPILER_SCOPE_CLASS);
res = dict_add_o(u->u_metadata.u_cellvars, &_Py_ID(__classdict__));
if (res < 0) {
compiler_unit_free(u);
return ERROR;
}
}
u->u_metadata.u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,
PyDict_GET_SIZE(u->u_metadata.u_cellvars));
@ -1718,8 +1741,10 @@ get_ref_type(struct compiler *c, PyObject *name)
{
int scope;
if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
_PyUnicode_EqualToASCIIString(name, "__class__"))
(_PyUnicode_EqualToASCIIString(name, "__class__") ||
_PyUnicode_EqualToASCIIString(name, "__classdict__"))) {
return CELL;
}
scope = _PyST_GetScope(c->u->u_ste, name);
if (scope == 0) {
PyErr_Format(PyExc_SystemError,
@ -2085,26 +2110,81 @@ wrap_in_stopiteration_handler(struct compiler *c)
}
static int
compiler_function(struct compiler *c, stmt_ty s, int is_async)
compiler_type_params(struct compiler *c, asdl_typeparam_seq *typeparams)
{
if (!typeparams) {
return SUCCESS;
}
Py_ssize_t n = asdl_seq_LEN(typeparams);
for (Py_ssize_t i = 0; i < n; i++) {
typeparam_ty typeparam = asdl_seq_GET(typeparams, i);
location loc = LOC(typeparam);
switch(typeparam->kind) {
case TypeVar_kind:
ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVar.name);
if (typeparam->v.TypeVar.bound) {
expr_ty bound = typeparam->v.TypeVar.bound;
if (compiler_enter_scope(c, typeparam->v.TypeVar.name, COMPILER_SCOPE_TYPEPARAMS,
(void *)typeparam, bound->lineno) == -1) {
return ERROR;
}
VISIT_IN_SCOPE(c, expr, bound);
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
PyCodeObject *co = optimize_and_assemble(c, 1);
compiler_exit_scope(c);
if (co == NULL) {
return ERROR;
}
if (compiler_make_closure(c, loc, co, 0) < 0) {
Py_DECREF(co);
return ERROR;
}
Py_DECREF(co);
int intrinsic = bound->kind == Tuple_kind
? INTRINSIC_TYPEVAR_WITH_CONSTRAINTS
: INTRINSIC_TYPEVAR_WITH_BOUND;
ADDOP_I(c, loc, CALL_INTRINSIC_2, intrinsic);
}
else {
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVAR);
}
ADDOP_I(c, loc, COPY, 1);
RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVar.name, Store));
break;
case TypeVarTuple_kind:
ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVarTuple.name);
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVARTUPLE);
ADDOP_I(c, loc, COPY, 1);
RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVarTuple.name, Store));
break;
case ParamSpec_kind:
ADDOP_LOAD_CONST(c, loc, typeparam->v.ParamSpec.name);
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PARAMSPEC);
ADDOP_I(c, loc, COPY, 1);
RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.ParamSpec.name, Store));
break;
}
}
ADDOP_I(c, LOC(asdl_seq_GET(typeparams, 0)), BUILD_TUPLE, n);
return SUCCESS;
}
static int
compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags,
int firstlineno)
{
PyCodeObject *co;
PyObject *docstring = NULL;
arguments_ty args;
expr_ty returns;
identifier name;
asdl_expr_seq* decos;
asdl_stmt_seq *body;
Py_ssize_t i, funcflags;
int annotations;
int scope_type;
int firstlineno;
if (is_async) {
assert(s->kind == AsyncFunctionDef_kind);
args = s->v.AsyncFunctionDef.args;
returns = s->v.AsyncFunctionDef.returns;
decos = s->v.AsyncFunctionDef.decorator_list;
name = s->v.AsyncFunctionDef.name;
body = s->v.AsyncFunctionDef.body;
@ -2113,33 +2193,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
assert(s->kind == FunctionDef_kind);
args = s->v.FunctionDef.args;
returns = s->v.FunctionDef.returns;
decos = s->v.FunctionDef.decorator_list;
name = s->v.FunctionDef.name;
body = s->v.FunctionDef.body;
scope_type = COMPILER_SCOPE_FUNCTION;
}
RETURN_IF_ERROR(compiler_check_debug_args(c, args));
RETURN_IF_ERROR(compiler_decorators(c, decos));
firstlineno = s->lineno;
if (asdl_seq_LEN(decos)) {
firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
}
location loc = LOC(s);
funcflags = compiler_default_arguments(c, loc, args);
if (funcflags == -1) {
return ERROR;
}
annotations = compiler_visit_annotations(c, loc, args, returns);
RETURN_IF_ERROR(annotations);
if (annotations > 0) {
funcflags |= 0x04;
}
RETURN_IF_ERROR(
compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno));
@ -2155,7 +2214,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
for (i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) {
for (Py_ssize_t i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) {
VISIT_IN_SCOPE(c, stmt, (stmt_ty)asdl_seq_GET(body, i));
}
if (c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator) {
@ -2164,29 +2223,52 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
return ERROR;
}
}
co = optimize_and_assemble(c, 1);
PyCodeObject *co = optimize_and_assemble(c, 1);
compiler_exit_scope(c);
if (co == NULL) {
Py_XDECREF(co);
return ERROR;
}
location loc = LOC(s);
if (compiler_make_closure(c, loc, co, funcflags) < 0) {
Py_DECREF(co);
return ERROR;
}
Py_DECREF(co);
RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
return compiler_nameop(c, loc, name, Store);
return SUCCESS;
}
static int
compiler_class(struct compiler *c, stmt_ty s)
compiler_function(struct compiler *c, stmt_ty s, int is_async)
{
PyCodeObject *co;
int i, firstlineno;
asdl_expr_seq *decos = s->v.ClassDef.decorator_list;
arguments_ty args;
expr_ty returns;
identifier name;
asdl_expr_seq *decos;
asdl_typeparam_seq *typeparams;
Py_ssize_t funcflags;
int annotations;
int firstlineno;
if (is_async) {
assert(s->kind == AsyncFunctionDef_kind);
args = s->v.AsyncFunctionDef.args;
returns = s->v.AsyncFunctionDef.returns;
decos = s->v.AsyncFunctionDef.decorator_list;
name = s->v.AsyncFunctionDef.name;
typeparams = s->v.AsyncFunctionDef.typeparams;
} else {
assert(s->kind == FunctionDef_kind);
args = s->v.FunctionDef.args;
returns = s->v.FunctionDef.returns;
decos = s->v.FunctionDef.decorator_list;
name = s->v.FunctionDef.name;
typeparams = s->v.FunctionDef.typeparams;
}
RETURN_IF_ERROR(compiler_check_debug_args(c, args));
RETURN_IF_ERROR(compiler_decorators(c, decos));
firstlineno = s->lineno;
@ -2194,6 +2276,108 @@ compiler_class(struct compiler *c, stmt_ty s)
firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
}
location loc = LOC(s);
int is_generic = asdl_seq_LEN(typeparams) > 0;
if (is_generic) {
// Used by the CALL to the type parameters function.
ADDOP(c, loc, PUSH_NULL);
}
funcflags = compiler_default_arguments(c, loc, args);
if (funcflags == -1) {
return ERROR;
}
int num_typeparam_args = 0;
if (is_generic) {
if (funcflags & 0x01) {
num_typeparam_args += 1;
}
if (funcflags & 0x02) {
num_typeparam_args += 1;
}
if (num_typeparam_args == 2) {
ADDOP_I(c, loc, SWAP, 2);
}
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>", name);
if (!typeparams_name) {
return ERROR;
}
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
(void *)typeparams, firstlineno) == -1) {
Py_DECREF(typeparams_name);
return ERROR;
}
Py_DECREF(typeparams_name);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, typeparams));
if ((funcflags & 0x01) || (funcflags & 0x02)) {
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, 0, loc));
}
if ((funcflags & 0x01) && (funcflags & 0x02)) {
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, 1, loc));
}
}
annotations = compiler_visit_annotations(c, loc, args, returns);
if (annotations < 0) {
if (is_generic) {
compiler_exit_scope(c);
}
return ERROR;
}
if (annotations > 0) {
funcflags |= 0x04;
}
if (compiler_function_body(c, s, is_async, funcflags, firstlineno) < 0) {
if (is_generic) {
compiler_exit_scope(c);
}
return ERROR;
}
if (is_generic) {
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(
INSTR_SEQUENCE(c), SWAP, 2, loc));
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(
INSTR_SEQUENCE(c), CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS, loc));
c->u->u_metadata.u_argcount = num_typeparam_args;
PyCodeObject *co = optimize_and_assemble(c, 0);
compiler_exit_scope(c);
if (co == NULL) {
return ERROR;
}
if (compiler_make_closure(c, loc, co, 0) < 0) {
Py_DECREF(co);
return ERROR;
}
Py_DECREF(co);
if (num_typeparam_args > 0) {
ADDOP_I(c, loc, SWAP, num_typeparam_args + 1);
}
ADDOP_I(c, loc, CALL, num_typeparam_args);
}
RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
return compiler_nameop(c, loc, name, Store);
}
static int
compiler_set_type_params_in_class(struct compiler *c, location loc)
{
_Py_DECLARE_STR(type_params, ".type_params");
RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_STR(type_params), Load));
RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_ID(__type_params__), Store));
return 1;
}
static int
compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
{
/* ultimately generate code for:
<name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
where:
@ -2204,68 +2388,100 @@ compiler_class(struct compiler *c, stmt_ty s)
<keywords> is the keyword arguments and **kwds argument
This borrows from compiler_call.
*/
/* 1. compile the class body into a code object */
RETURN_IF_ERROR(
compiler_enter_scope(c, s->v.ClassDef.name,
COMPILER_SCOPE_CLASS, (void *)s, firstlineno));
/* this block represents what we do in the new scope */
{
location loc = LOCATION(firstlineno, firstlineno, 0, 0);
/* use the class name for name mangling */
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
/* load (global) __name__ ... */
if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) {
compiler_exit_scope(c);
return ERROR;
}
/* ... and store it as __module__ */
if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
assert(c->u->u_metadata.u_qualname);
ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname);
if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
/* compile the body proper */
if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {
compiler_exit_scope(c);
return ERROR;
}
/* The following code is artificial */
/* Return __classcell__ if it is referenced, otherwise return None */
if (c->u->u_ste->ste_needs_class_closure) {
/* Store __classcell__ into class namespace & return it */
i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));
if (i < 0) {
compiler_exit_scope(c);
return ERROR;
}
ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
ADDOP_I(c, NO_LOCATION, COPY, 1);
if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
}
else {
/* No methods referenced __class__, so just return None */
ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
}
ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE);
/* create the code object */
co = optimize_and_assemble(c, 1);
location loc = LOCATION(firstlineno, firstlineno, 0, 0);
/* use the class name for name mangling */
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
/* load (global) __name__ ... */
if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) {
compiler_exit_scope(c);
return ERROR;
}
/* ... and store it as __module__ */
if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
assert(c->u->u_metadata.u_qualname);
ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname);
if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
asdl_typeparam_seq *typeparams = s->v.ClassDef.typeparams;
if (asdl_seq_LEN(typeparams) > 0) {
if (!compiler_set_type_params_in_class(c, loc)) {
compiler_exit_scope(c);
return ERROR;
}
}
if (c->u->u_ste->ste_needs_classdict) {
ADDOP(c, loc, LOAD_LOCALS);
// We can't use compiler_nameop here because we need to generate a
// STORE_DEREF in a class namespace, and compiler_nameop() won't do
// that by default.
PyObject *cellvars = c->u->u_metadata.u_cellvars;
if (compiler_addop_o(c->u, loc, STORE_DEREF, cellvars,
&_Py_ID(__classdict__)) < 0) {
compiler_exit_scope(c);
return ERROR;
}
}
/* compile the body proper */
if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {
compiler_exit_scope(c);
return ERROR;
}
/* The following code is artificial */
/* Set __classdictcell__ if necessary */
if (c->u->u_ste->ste_needs_classdict) {
/* Store __classdictcell__ into class namespace */
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__));
if (i < 0) {
compiler_exit_scope(c);
return ERROR;
}
ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classdictcell__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
}
/* Return __classcell__ if it is referenced, otherwise return None */
if (c->u->u_ste->ste_needs_class_closure) {
/* Store __classcell__ into class namespace & return it */
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));
if (i < 0) {
compiler_exit_scope(c);
return ERROR;
}
ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
ADDOP_I(c, NO_LOCATION, COPY, 1);
if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) {
compiler_exit_scope(c);
return ERROR;
}
}
else {
/* No methods referenced __class__, so just return None */
ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
}
ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE);
/* create the code object */
PyCodeObject *co = optimize_and_assemble(c, 1);
/* leave the new scope */
compiler_exit_scope(c);
if (co == NULL) {
return ERROR;
}
location loc = LOC(s);
/* 2. load the 'build_class' function */
ADDOP(c, loc, PUSH_NULL);
ADDOP(c, loc, LOAD_BUILD_CLASS);
@ -2280,10 +2496,100 @@ compiler_class(struct compiler *c, stmt_ty s)
/* 4. load class name */
ADDOP_LOAD_CONST(c, loc, s->v.ClassDef.name);
/* 5. generate the rest of the code for the call */
RETURN_IF_ERROR(compiler_call_helper(c, loc, 2,
s->v.ClassDef.bases,
s->v.ClassDef.keywords));
return SUCCESS;
}
static int
compiler_class(struct compiler *c, stmt_ty s)
{
asdl_expr_seq *decos = s->v.ClassDef.decorator_list;
RETURN_IF_ERROR(compiler_decorators(c, decos));
int firstlineno = s->lineno;
if (asdl_seq_LEN(decos)) {
firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
}
location loc = LOC(s);
asdl_typeparam_seq *typeparams = s->v.ClassDef.typeparams;
int is_generic = asdl_seq_LEN(typeparams) > 0;
if (is_generic) {
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
ADDOP(c, loc, PUSH_NULL);
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>",
s->v.ClassDef.name);
if (!typeparams_name) {
return ERROR;
}
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
(void *)typeparams, firstlineno) == -1) {
Py_DECREF(typeparams_name);
return ERROR;
}
Py_DECREF(typeparams_name);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, typeparams));
_Py_DECLARE_STR(type_params, ".type_params");
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Store));
}
if (compiler_class_body(c, s, firstlineno) < 0) {
if (is_generic) {
compiler_exit_scope(c);
}
return ERROR;
}
/* generate the rest of the code for the call */
if (is_generic) {
_Py_DECLARE_STR(type_params, ".type_params");
_Py_DECLARE_STR(generic_base, ".generic_base");
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Load));
RETURN_IF_ERROR_IN_SCOPE(
c, codegen_addop_i(INSTR_SEQUENCE(c), CALL_INTRINSIC_1, INTRINSIC_SUBSCRIPT_GENERIC, loc)
)
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(generic_base), Store));
Py_ssize_t original_len = asdl_seq_LEN(s->v.ClassDef.bases);
asdl_expr_seq *bases = _Py_asdl_expr_seq_new(
original_len + 1, c->c_arena);
if (bases == NULL) {
compiler_exit_scope(c);
return ERROR;
}
for (Py_ssize_t i = 0; i < original_len; i++) {
asdl_seq_SET(bases, i, asdl_seq_GET(s->v.ClassDef.bases, i));
}
expr_ty name_node = _PyAST_Name(
&_Py_STR(generic_base), Load,
loc.lineno, loc.col_offset, loc.end_lineno, loc.end_col_offset, c->c_arena
);
if (name_node == NULL) {
compiler_exit_scope(c);
return ERROR;
}
asdl_seq_SET(bases, original_len, name_node);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_call_helper(c, loc, 2,
bases,
s->v.ClassDef.keywords));
PyCodeObject *co = optimize_and_assemble(c, 0);
compiler_exit_scope(c);
if (co == NULL) {
return ERROR;
}
if (compiler_make_closure(c, loc, co, 0) < 0) {
Py_DECREF(co);
return ERROR;
}
Py_DECREF(co);
ADDOP_I(c, loc, CALL, 0);
} else {
RETURN_IF_ERROR(compiler_call_helper(c, loc, 2,
s->v.ClassDef.bases,
s->v.ClassDef.keywords));
}
/* 6. apply decorators */
RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
@ -2293,6 +2599,87 @@ compiler_class(struct compiler *c, stmt_ty s)
return SUCCESS;
}
static int
compiler_typealias_body(struct compiler *c, stmt_ty s)
{
location loc = LOC(s);
PyObject *name = s->v.TypeAlias.name->v.Name.id;
RETURN_IF_ERROR(
compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno));
/* Make None the first constant, so the evaluate function can't have a
docstring. */
RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));
VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value);
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
PyCodeObject *co = optimize_and_assemble(c, 0);
compiler_exit_scope(c);
if (co == NULL) {
return ERROR;
}
if (compiler_make_closure(c, loc, co, 0) < 0) {
Py_DECREF(co);
return ERROR;
}
Py_DECREF(co);
ADDOP_I(c, loc, BUILD_TUPLE, 3);
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEALIAS);
return SUCCESS;
}
static int
compiler_typealias(struct compiler *c, stmt_ty s)
{
location loc = LOC(s);
asdl_typeparam_seq *typeparams = s->v.TypeAlias.typeparams;
int is_generic = asdl_seq_LEN(typeparams) > 0;
PyObject *name = s->v.TypeAlias.name->v.Name.id;
if (is_generic) {
ADDOP(c, loc, PUSH_NULL);
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>",
name);
if (!typeparams_name) {
return ERROR;
}
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
(void *)typeparams, loc.lineno) == -1) {
Py_DECREF(typeparams_name);
return ERROR;
}
Py_DECREF(typeparams_name);
RETURN_IF_ERROR_IN_SCOPE(
c, compiler_addop_load_const(c->c_const_cache, c->u, loc, name)
);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, typeparams));
}
else {
ADDOP_LOAD_CONST(c, loc, name);
ADDOP_LOAD_CONST(c, loc, Py_None);
}
if (compiler_typealias_body(c, s) < 0) {
if (is_generic) {
compiler_exit_scope(c);
}
return ERROR;
}
if (is_generic) {
PyCodeObject *co = optimize_and_assemble(c, 0);
compiler_exit_scope(c);
if (co == NULL) {
return ERROR;
}
if (compiler_make_closure(c, loc, co, 0) < 0) {
Py_DECREF(co);
return ERROR;
}
Py_DECREF(co);
ADDOP_I(c, loc, CALL, 0);
}
RETURN_IF_ERROR(compiler_nameop(c, loc, name, Store));
return SUCCESS;
}
/* Return false if the expression is a constant value except named singletons.
Return true otherwise. */
static bool
@ -2705,7 +3092,7 @@ compiler_return(struct compiler *c, stmt_ty s)
location loc = LOC(s);
int preserve_tos = ((s->v.Return.value != NULL) &&
(s->v.Return.value->kind != Constant_kind));
if (c->u->u_ste->ste_type != FunctionBlock) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
return compiler_error(c, loc, "'return' outside function");
}
if (s->v.Return.value != NULL &&
@ -3519,6 +3906,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
return compiler_function(c, s, 0);
case ClassDef_kind:
return compiler_class(c, s);
case TypeAlias_kind:
return compiler_typealias(c, s);
case Return_kind:
return compiler_return(c, s);
case Delete_kind:
@ -3725,12 +4114,12 @@ compiler_nameop(struct compiler *c, location loc,
optype = OP_DEREF;
break;
case LOCAL:
if (c->u->u_ste->ste_type == FunctionBlock ||
if (_PyST_IsFunctionLike(c->u->u_ste) ||
(PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True))
optype = OP_FAST;
break;
case GLOBAL_IMPLICIT:
if (c->u->u_ste->ste_type == FunctionBlock)
if (_PyST_IsFunctionLike(c->u->u_ste))
optype = OP_GLOBAL;
break;
case GLOBAL_EXPLICIT:
@ -3748,7 +4137,24 @@ compiler_nameop(struct compiler *c, location loc,
case OP_DEREF:
switch (ctx) {
case Load:
op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF;
if (c->u->u_ste->ste_type == ClassBlock) {
op = LOAD_FROM_DICT_OR_DEREF;
// First load the locals
if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) {
return ERROR;
}
}
else if (c->u->u_ste->ste_can_see_class_scope) {
op = LOAD_FROM_DICT_OR_DEREF;
// First load the classdict
if (compiler_addop_o(c->u, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
return ERROR;
}
}
else {
op = LOAD_DEREF;
}
break;
case Store: op = STORE_DEREF; break;
case Del: op = DELETE_DEREF; break;
@ -3764,7 +4170,18 @@ compiler_nameop(struct compiler *c, location loc,
return SUCCESS;
case OP_GLOBAL:
switch (ctx) {
case Load: op = LOAD_GLOBAL; break;
case Load:
if (c->u->u_ste->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) {
op = LOAD_FROM_DICT_OR_GLOBALS;
// First load the classdict
if (compiler_addop_o(c->u, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
return ERROR;
}
} else {
op = LOAD_GLOBAL;
}
break;
case Store: op = STORE_GLOBAL; break;
case Del: op = DELETE_GLOBAL; break;
}
@ -5008,7 +5425,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
// assignment expression to a nonlocal in the comprehension, these don't
// need handling here since they shouldn't be isolated
if (symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) {
if (c->u->u_ste->ste_type != FunctionBlock) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
// non-function scope: override this name to use fast locals
PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k);
if (orig != Py_True) {
@ -5604,7 +6021,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
case DictComp_kind:
return compiler_dictcomp(c, e);
case Yield_kind:
if (c->u->u_ste->ste_type != FunctionBlock) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
return compiler_error(c, loc, "'yield' outside function");
}
if (e->v.Yield.value) {
@ -5616,7 +6033,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
ADDOP_YIELD(c, loc);
break;
case YieldFrom_kind:
if (c->u->u_ste->ste_type != FunctionBlock) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
return compiler_error(c, loc, "'yield' outside function");
}
if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) {
@ -5629,7 +6046,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
break;
case Await_kind:
if (!IS_TOP_LEVEL_AWAIT(c)){
if (c->u->u_ste->ste_type != FunctionBlock){
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
return compiler_error(c, loc, "'await' outside function");
}
@ -6916,7 +7333,7 @@ compute_code_flags(struct compiler *c)
{
PySTEntryObject *ste = c->u->u_ste;
int flags = 0;
if (ste->ste_type == FunctionBlock) {
if (_PyST_IsFunctionLike(c->u->u_ste)) {
flags |= CO_NEWLOCALS | CO_OPTIMIZED;
if (ste->ste_nested)
flags |= CO_NESTED;
@ -7114,7 +7531,7 @@ fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *
case LOAD_DEREF:
case STORE_DEREF:
case DELETE_DEREF:
case LOAD_CLASSDEREF:
case LOAD_FROM_DICT_OR_DEREF:
assert(oldoffset >= 0);
assert(oldoffset < noffsets);
assert(fixedmap[oldoffset] >= 0);

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,12 @@
#include "Python.h"
#include "pycore_frame.h"
#include "pycore_function.h"
#include "pycore_runtime.h"
#include "pycore_global_objects.h"
#include "pycore_intrinsics.h"
#include "pycore_pyerrors.h"
#include "pycore_typevarobject.h"
/******** Unary functions ********/
@ -199,6 +201,13 @@ list_to_tuple(PyThreadState* unused, PyObject *v)
return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));
}
static PyObject *
make_typevar(PyThreadState* Py_UNUSED(ignored), PyObject *v)
{
assert(PyUnicode_Check(v));
return _Py_make_typevar(v, NULL, NULL);
}
const instrinsic_func1
_PyIntrinsics_UnaryFunctions[] = {
[0] = no_intrinsic,
@ -208,6 +217,11 @@ _PyIntrinsics_UnaryFunctions[] = {
[INTRINSIC_ASYNC_GEN_WRAP] = _PyAsyncGenValueWrapperNew,
[INTRINSIC_UNARY_POSITIVE] = unary_pos,
[INTRINSIC_LIST_TO_TUPLE] = list_to_tuple,
[INTRINSIC_TYPEVAR] = make_typevar,
[INTRINSIC_PARAMSPEC] = _Py_make_paramspec,
[INTRINSIC_TYPEVARTUPLE] = _Py_make_typevartuple,
[INTRINSIC_SUBSCRIPT_GENERIC] = _Py_subscript_generic,
[INTRINSIC_TYPEALIAS] = _Py_make_typealias,
};
@ -221,8 +235,26 @@ prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs)
return _PyExc_PrepReraiseStar(orig, excs);
}
static PyObject *
make_typevar_with_bound(PyThreadState* Py_UNUSED(ignored), PyObject *name,
PyObject *evaluate_bound)
{
assert(PyUnicode_Check(name));
return _Py_make_typevar(name, evaluate_bound, NULL);
}
static PyObject *
make_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name,
PyObject *evaluate_constraints)
{
assert(PyUnicode_Check(name));
return _Py_make_typevar(name, NULL, evaluate_constraints);
}
const instrinsic_func2
_PyIntrinsics_BinaryFunctions[] = {
[INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star,
[INTRINSIC_TYPEVAR_WITH_BOUND] = make_typevar_with_bound,
[INTRINSIC_TYPEVAR_WITH_CONSTRAINTS] = make_typevar_with_constraints,
[INTRINSIC_SET_FUNCTION_TYPE_PARAMS] = _Py_set_function_type_params,
};

View File

@ -161,8 +161,12 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1;
case DELETE_GLOBAL:
return 0;
case LOAD_NAME:
case LOAD_LOCALS:
return 0;
case LOAD_NAME:
return 0+1;
case LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_GLOBAL:
return 0;
case LOAD_GLOBAL_MODULE:
@ -175,8 +179,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 0;
case DELETE_DEREF:
return 0;
case LOAD_CLASSDEREF:
return 0;
case LOAD_FROM_DICT_OR_DEREF:
return 1;
case LOAD_DEREF:
return 0;
case STORE_DEREF:
@ -551,7 +555,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0;
case DELETE_GLOBAL:
return 0;
case LOAD_LOCALS:
return 1;
case LOAD_NAME:
return 1+1;
case LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_GLOBAL:
return ((oparg & 1) ? 1 : 0) + 1;
@ -565,7 +573,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0;
case DELETE_DEREF:
return 0;
case LOAD_CLASSDEREF:
case LOAD_FROM_DICT_OR_DEREF:
return 1;
case LOAD_DEREF:
return 1;
@ -869,14 +877,16 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[DELETE_ATTR] = { true, INSTR_FMT_IB },
[STORE_GLOBAL] = { true, INSTR_FMT_IB },
[DELETE_GLOBAL] = { true, INSTR_FMT_IB },
[LOAD_LOCALS] = { true, INSTR_FMT_IB },
[LOAD_NAME] = { true, INSTR_FMT_IB },
[LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB },
[LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 },
[LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 },
[LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 },
[DELETE_FAST] = { true, INSTR_FMT_IB },
[MAKE_CELL] = { true, INSTR_FMT_IB },
[DELETE_DEREF] = { true, INSTR_FMT_IB },
[LOAD_CLASSDEREF] = { true, INSTR_FMT_IB },
[LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB },
[LOAD_DEREF] = { true, INSTR_FMT_IB },
[STORE_DEREF] = { true, INSTR_FMT_IB },
[COPY_FREE_VARS] = { true, INSTR_FMT_IB },

View File

@ -86,8 +86,8 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_CONST__LOAD_FAST,
&&TARGET_SETUP_ANNOTATIONS,
&&TARGET_LOAD_FAST__LOAD_CONST,
&&TARGET_LOAD_LOCALS,
&&TARGET_LOAD_FAST__LOAD_FAST,
&&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_POP_EXCEPT,
&&TARGET_STORE_NAME,
&&TARGET_DELETE_NAME,
@ -110,9 +110,9 @@ static void *opcode_targets[256] = {
&&TARGET_IMPORT_NAME,
&&TARGET_IMPORT_FROM,
&&TARGET_JUMP_FORWARD,
&&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_LOAD_GLOBAL_MODULE,
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
&&TARGET_STORE_ATTR_SLOT,
&&TARGET_POP_JUMP_IF_FALSE,
&&TARGET_POP_JUMP_IF_TRUE,
&&TARGET_LOAD_GLOBAL,
@ -147,7 +147,7 @@ static void *opcode_targets[256] = {
&&TARGET_LIST_APPEND,
&&TARGET_SET_ADD,
&&TARGET_MAP_ADD,
&&TARGET_LOAD_CLASSDEREF,
&&TARGET_STORE_ATTR_SLOT,
&&TARGET_COPY_FREE_VARS,
&&TARGET_YIELD_VALUE,
&&TARGET_RESUME,
@ -174,8 +174,8 @@ static void *opcode_targets[256] = {
&&TARGET_KW_NAMES,
&&TARGET_CALL_INTRINSIC_1,
&&TARGET_CALL_INTRINSIC_2,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_LOAD_FROM_DICT_OR_GLOBALS,
&&TARGET_LOAD_FROM_DICT_OR_DEREF,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,

View File

@ -26,6 +26,7 @@
#include "pycore_sysmodule.h" // _PySys_ClearAuditHooks()
#include "pycore_traceback.h" // _Py_DumpTracebackThreads()
#include "pycore_typeobject.h" // _PyTypes_InitTypes()
#include "pycore_typevarobject.h" // _Py_clear_generic_types()
#include "pycore_unicodeobject.h" // _PyUnicode_InitTypes()
#include "opcode.h"
@ -1698,6 +1699,7 @@ finalize_interp_clear(PyThreadState *tstate)
int is_main_interp = _Py_IsMainInterpreter(tstate->interp);
_PyExc_ClearExceptionGroupType(tstate->interp);
_Py_clear_generic_types(tstate->interp);
/* Clear interpreter state and all thread states */
_PyInterpreterState_Clear(tstate);

View File

@ -47,6 +47,18 @@
#define ANNOTATION_NOT_ALLOWED \
"'%s' can not be used within an annotation"
#define TYPEVAR_BOUND_NOT_ALLOWED \
"'%s' can not be used within a TypeVar bound"
#define TYPEALIAS_NOT_ALLOWED \
"'%s' can not be used within a type alias"
#define TYPEPARAM_NOT_ALLOWED \
"'%s' can not be used within the definition of a generic"
#define DUPLICATE_TYPE_PARAM \
"duplicate type parameter '%U'"
#define LOCATION(x) \
(x)->lineno, (x)->col_offset, (x)->end_lineno, (x)->end_col_offset
@ -95,7 +107,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
if (st->st_cur != NULL &&
(st->st_cur->ste_nested ||
st->st_cur->ste_type == FunctionBlock))
_PyST_IsFunctionLike(st->st_cur)))
ste->ste_nested = 1;
ste->ste_child_free = 0;
ste->ste_generator = 0;
@ -105,7 +117,9 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
ste->ste_needs_class_closure = 0;
ste->ste_comp_inlined = 0;
ste->ste_comp_iter_target = 0;
ste->ste_can_see_class_scope = 0;
ste->ste_comp_iter_expr = 0;
ste->ste_needs_classdict = 0;
ste->ste_symbols = PyDict_New();
ste->ste_varnames = PyList_New(0);
@ -208,6 +222,7 @@ static int symtable_enter_block(struct symtable *st, identifier name,
static int symtable_exit_block(struct symtable *st);
static int symtable_visit_stmt(struct symtable *st, stmt_ty s);
static int symtable_visit_expr(struct symtable *st, expr_ty s);
static int symtable_visit_typeparam(struct symtable *st, typeparam_ty s);
static int symtable_visit_genexp(struct symtable *st, expr_ty s);
static int symtable_visit_listcomp(struct symtable *st, expr_ty s);
static int symtable_visit_setcomp(struct symtable *st, expr_ty s);
@ -403,6 +418,15 @@ _PyST_GetScope(PySTEntryObject *ste, PyObject *name)
return (symbol >> SCOPE_OFFSET) & SCOPE_MASK;
}
int
_PyST_IsFunctionLike(PySTEntryObject *ste)
{
return ste->ste_type == FunctionBlock
|| ste->ste_type == TypeVarBoundBlock
|| ste->ste_type == TypeAliasBlock
|| ste->ste_type == TypeParamBlock;
}
static int
error_at_directive(PySTEntryObject *ste, PyObject *name)
{
@ -495,7 +519,7 @@ error_at_directive(PySTEntryObject *ste, PyObject *name)
static int
analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
PyObject *bound, PyObject *local, PyObject *free,
PyObject *global)
PyObject *global, PyObject *typeparams, PySTEntryObject *class_entry)
{
if (flags & DEF_GLOBAL) {
if (flags & DEF_NONLOCAL) {
@ -524,6 +548,12 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
return error_at_directive(ste, name);
}
if (PySet_Contains(typeparams, name)) {
PyErr_Format(PyExc_SyntaxError,
"nonlocal binding not allowed for type parameter '%U'",
name);
return error_at_directive(ste, name);
}
SET_SCOPE(scopes, name, FREE);
ste->ste_free = 1;
return PySet_Add(free, name) >= 0;
@ -534,8 +564,34 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
return 0;
if (PySet_Discard(global, name) < 0)
return 0;
if (flags & DEF_TYPE_PARAM) {
if (PySet_Add(typeparams, name) < 0)
return 0;
}
else {
if (PySet_Discard(typeparams, name) < 0)
return 0;
}
return 1;
}
// If we were passed class_entry (i.e., we're in an ste_can_see_class_scope scope)
// and the bound name is in that set, then the name is potentially bound both by
// the immediately enclosing class namespace, and also by an outer function namespace.
// In that case, we want the runtime name resolution to look at only the class
// namespace and the globals (not the namespace providing the bound).
// Similarly, if the name is explicitly global in the class namespace (through the
// global statement), we want to also treat it as a global in this scope.
if (class_entry != NULL) {
long class_flags = _PyST_GetSymbol(class_entry, name);
if (class_flags & DEF_GLOBAL) {
SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
return 1;
}
else if (class_flags & DEF_BOUND && !(class_flags & DEF_NONLOCAL)) {
SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
return 1;
}
}
/* If an enclosing block has a binding for this name, it
is a free variable rather than a global variable.
Note that having a non-NULL bound implies that the block
@ -611,7 +667,7 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
if (PyLong_AsLong(existing) & DEF_BOUND) {
// cell vars in comprehension that are locals in outer scope
// must be promoted to cell so u_cellvars isn't wrong
if (scope == CELL && ste->ste_type == FunctionBlock) {
if (scope == CELL && _PyST_IsFunctionLike(ste)) {
if (PySet_Add(promote_to_cell, k) < 0) {
return 0;
}
@ -682,6 +738,11 @@ drop_class_free(PySTEntryObject *ste, PyObject *free)
return 0;
if (res)
ste->ste_needs_class_closure = 1;
res = PySet_Discard(free, &_Py_ID(__classdict__));
if (res < 0)
return 0;
if (res)
ste->ste_needs_classdict = 1;
return 1;
}
@ -799,11 +860,13 @@ error:
static int
analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
PyObject *global, PyObject **child_free);
PyObject *global, PyObject *typeparams,
PySTEntryObject *class_entry, PyObject **child_free);
static int
analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
PyObject *global)
PyObject *global, PyObject *typeparams,
PySTEntryObject *class_entry)
{
PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL;
PyObject *newglobal = NULL, *newfree = NULL, *promote_to_cell = NULL;
@ -865,14 +928,14 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {
long flags = PyLong_AS_LONG(v);
if (!analyze_name(ste, scopes, name, flags,
bound, local, free, global))
bound, local, free, global, typeparams, class_entry))
goto error;
}
/* Populate global and bound sets to be passed to children. */
if (ste->ste_type != ClassBlock) {
/* Add function locals to bound set */
if (ste->ste_type == FunctionBlock) {
if (_PyST_IsFunctionLike(ste)) {
temp = PyNumber_InPlaceOr(newbound, local);
if (!temp)
goto error;
@ -892,9 +955,11 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
Py_DECREF(temp);
}
else {
/* Special-case __class__ */
/* Special-case __class__ and __classdict__ */
if (PySet_Add(newbound, &_Py_ID(__class__)) < 0)
goto error;
if (PySet_Add(newbound, &_Py_ID(__classdict__)) < 0)
goto error;
}
/* Recursively call analyze_child_block() on each child block.
@ -910,13 +975,23 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
assert(c && PySTEntry_Check(c));
entry = (PySTEntryObject*)c;
PySTEntryObject *new_class_entry = NULL;
if (entry->ste_can_see_class_scope) {
if (ste->ste_type == ClassBlock) {
new_class_entry = ste;
}
else if (class_entry) {
new_class_entry = class_entry;
}
}
// we inline all non-generator-expression comprehensions
int inline_comp =
entry->ste_comprehension &&
!entry->ste_generator;
if (!analyze_child_block(entry, newbound, newfree, newglobal,
&child_free))
typeparams, new_class_entry, &child_free))
{
goto error;
}
@ -952,7 +1027,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
}
/* Check if any local variables must be converted to cell variables */
if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, promote_to_cell))
if (_PyST_IsFunctionLike(ste) && !analyze_cells(scopes, newfree, promote_to_cell))
goto error;
else if (ste->ste_type == ClassBlock && !drop_class_free(ste, newfree))
goto error;
@ -980,9 +1055,11 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
static int
analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
PyObject *global, PyObject** child_free)
PyObject *global, PyObject *typeparams,
PySTEntryObject *class_entry, PyObject** child_free)
{
PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL;
PyObject *temp_typeparams = NULL;
/* Copy the bound/global/free sets.
@ -1000,24 +1077,30 @@ analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
temp_global = PySet_New(global);
if (!temp_global)
goto error;
temp_typeparams = PySet_New(typeparams);
if (!temp_typeparams)
goto error;
if (!analyze_block(entry, temp_bound, temp_free, temp_global))
if (!analyze_block(entry, temp_bound, temp_free, temp_global,
temp_typeparams, class_entry))
goto error;
*child_free = temp_free;
Py_DECREF(temp_bound);
Py_DECREF(temp_global);
Py_DECREF(temp_typeparams);
return 1;
error:
Py_XDECREF(temp_bound);
Py_XDECREF(temp_free);
Py_XDECREF(temp_global);
Py_XDECREF(temp_typeparams);
return 0;
}
static int
symtable_analyze(struct symtable *st)
{
PyObject *free, *global;
PyObject *free, *global, *typeparams;
int r;
free = PySet_New(NULL);
@ -1028,9 +1111,16 @@ symtable_analyze(struct symtable *st)
Py_DECREF(free);
return 0;
}
r = analyze_block(st->st_top, NULL, free, global);
typeparams = PySet_New(NULL);
if (!typeparams) {
Py_DECREF(free);
Py_DECREF(global);
return 0;
}
r = analyze_block(st->st_top, NULL, free, global, typeparams, NULL);
Py_DECREF(free);
Py_DECREF(global);
Py_DECREF(typeparams);
return r;
}
@ -1133,6 +1223,13 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s
end_lineno, end_col_offset + 1);
goto error;
}
if ((flag & DEF_TYPE_PARAM) && (val & DEF_TYPE_PARAM)) {
PyErr_Format(PyExc_SyntaxError, DUPLICATE_TYPE_PARAM, name);
PyErr_RangedSyntaxLocationObject(st->st_filename,
lineno, col_offset + 1,
end_lineno, end_col_offset + 1);
goto error;
}
val |= flag;
}
else if (PyErr_Occurred()) {
@ -1204,6 +1301,65 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag,
lineno, col_offset, end_lineno, end_col_offset);
}
static int
symtable_enter_typeparam_block(struct symtable *st, identifier name,
void *ast, int has_defaults, int has_kwdefaults,
enum _stmt_kind kind,
int lineno, int col_offset,
int end_lineno, int end_col_offset)
{
_Py_block_ty current_type = st->st_cur->ste_type;
if(!symtable_enter_block(st, name, TypeParamBlock, ast, lineno,
col_offset, end_lineno, end_col_offset)) {
return 0;
}
if (current_type == ClassBlock) {
st->st_cur->ste_can_see_class_scope = 1;
if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
}
if (kind == ClassDef_kind) {
_Py_DECLARE_STR(type_params, ".type_params");
// It gets "set" when we create the type params tuple and
// "used" when we build up the bases.
if (!symtable_add_def(st, &_Py_STR(type_params), DEF_LOCAL,
lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
if (!symtable_add_def(st, &_Py_STR(type_params), USE,
lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
st->st_private = name;
// This is used for setting the generic base
_Py_DECLARE_STR(generic_base, ".generic_base");
if (!symtable_add_def(st, &_Py_STR(generic_base), DEF_LOCAL,
lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
if (!symtable_add_def(st, &_Py_STR(generic_base), USE,
lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
}
if (has_defaults) {
_Py_DECLARE_STR(defaults, ".defaults");
if (!symtable_add_def(st, &_Py_STR(defaults), DEF_PARAM,
lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
}
if (has_kwdefaults) {
_Py_DECLARE_STR(kwdefaults, ".kwdefaults");
if (!symtable_add_def(st, &_Py_STR(kwdefaults), DEF_PARAM,
lineno, col_offset, end_lineno, end_col_offset)) {
return 0;
}
}
return 1;
}
/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument.
They use the ASDL name to synthesize the name of the C type and the visit
function.
@ -1275,6 +1431,17 @@ symtable_record_directive(struct symtable *st, identifier name, int lineno,
return res == 0;
}
static int
has_kwonlydefaults(asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)
{
for (int i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
expr_ty default_ = asdl_seq_GET(kw_defaults, i);
if (default_) {
return 1;
}
}
return 0;
}
static int
symtable_visit_stmt(struct symtable *st, stmt_ty s)
@ -1292,11 +1459,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
if (s->v.FunctionDef.args->kw_defaults)
VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults);
if (s->v.FunctionDef.decorator_list)
VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
if (asdl_seq_LEN(s->v.FunctionDef.typeparams) > 0) {
if (!symtable_enter_typeparam_block(
st, s->v.FunctionDef.name,
(void *)s->v.FunctionDef.typeparams,
s->v.FunctionDef.args->defaults != NULL,
has_kwonlydefaults(s->v.FunctionDef.args->kwonlyargs,
s->v.FunctionDef.args->kw_defaults),
s->kind,
LOCATION(s))) {
VISIT_QUIT(st, 0);
}
VISIT_SEQ(st, typeparam, s->v.FunctionDef.typeparams);
}
if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
s->v.FunctionDef.returns))
VISIT_QUIT(st, 0);
if (s->v.FunctionDef.decorator_list)
VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
if (!symtable_enter_block(st, s->v.FunctionDef.name,
FunctionBlock, (void *)s,
LOCATION(s)))
@ -1305,25 +1485,85 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
if (asdl_seq_LEN(s->v.FunctionDef.typeparams) > 0) {
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
}
break;
case ClassDef_kind: {
PyObject *tmp;
if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s)))
VISIT_QUIT(st, 0);
VISIT_SEQ(st, expr, s->v.ClassDef.bases);
VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
if (s->v.ClassDef.decorator_list)
VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
if (asdl_seq_LEN(s->v.ClassDef.typeparams) > 0) {
if (!symtable_enter_typeparam_block(st, s->v.ClassDef.name,
(void *)s->v.ClassDef.typeparams,
false, false, s->kind,
LOCATION(s))) {
VISIT_QUIT(st, 0);
}
VISIT_SEQ(st, typeparam, s->v.ClassDef.typeparams);
}
VISIT_SEQ(st, expr, s->v.ClassDef.bases);
VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
(void *)s, s->lineno, s->col_offset,
s->end_lineno, s->end_col_offset))
VISIT_QUIT(st, 0);
tmp = st->st_private;
st->st_private = s->v.ClassDef.name;
if (asdl_seq_LEN(s->v.ClassDef.typeparams) > 0) {
if (!symtable_add_def(st, &_Py_ID(__type_params__),
DEF_LOCAL, LOCATION(s))) {
VISIT_QUIT(st, 0);
}
_Py_DECLARE_STR(type_params, ".type_params");
if (!symtable_add_def(st, &_Py_STR(type_params),
USE, LOCATION(s))) {
VISIT_QUIT(st, 0);
}
}
VISIT_SEQ(st, stmt, s->v.ClassDef.body);
st->st_private = tmp;
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
if (asdl_seq_LEN(s->v.ClassDef.typeparams) > 0) {
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
}
break;
}
case TypeAlias_kind: {
VISIT(st, expr, s->v.TypeAlias.name);
assert(s->v.TypeAlias.name->kind == Name_kind);
PyObject *name = s->v.TypeAlias.name->v.Name.id;
int is_in_class = st->st_cur->ste_type == ClassBlock;
int is_generic = asdl_seq_LEN(s->v.TypeAlias.typeparams) > 0;
if (is_generic) {
if (!symtable_enter_typeparam_block(
st, name,
(void *)s->v.TypeAlias.typeparams,
false, false, s->kind,
LOCATION(s))) {
VISIT_QUIT(st, 0);
}
VISIT_SEQ(st, typeparam, s->v.TypeAlias.typeparams);
}
if (!symtable_enter_block(st, name, TypeAliasBlock,
(void *)s, LOCATION(s)))
VISIT_QUIT(st, 0);
st->st_cur->ste_can_see_class_scope = is_in_class;
if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(s->v.TypeAlias.value))) {
VISIT_QUIT(st, 0);
}
VISIT(st, expr, s->v.TypeAlias.value);
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
if (is_generic) {
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
}
break;
}
case Return_kind:
@ -1532,11 +1772,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (s->v.AsyncFunctionDef.args->kw_defaults)
VISIT_SEQ_WITH_NULL(st, expr,
s->v.AsyncFunctionDef.args->kw_defaults);
if (s->v.AsyncFunctionDef.decorator_list)
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list);
if (asdl_seq_LEN(s->v.AsyncFunctionDef.typeparams) > 0) {
if (!symtable_enter_typeparam_block(
st, s->v.AsyncFunctionDef.name,
(void *)s->v.AsyncFunctionDef.typeparams,
s->v.AsyncFunctionDef.args->defaults != NULL,
has_kwonlydefaults(s->v.AsyncFunctionDef.args->kwonlyargs,
s->v.AsyncFunctionDef.args->kw_defaults),
s->kind,
LOCATION(s))) {
VISIT_QUIT(st, 0);
}
VISIT_SEQ(st, typeparam, s->v.AsyncFunctionDef.typeparams);
}
if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
s->v.AsyncFunctionDef.returns))
VISIT_QUIT(st, 0);
if (s->v.AsyncFunctionDef.decorator_list)
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list);
if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name,
FunctionBlock, (void *)s,
s->lineno, s->col_offset,
@ -1547,6 +1800,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body);
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
if (asdl_seq_LEN(s->v.AsyncFunctionDef.typeparams) > 0) {
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
}
break;
case AsyncWith_kind:
VISIT_SEQ(st, withitem, s->v.AsyncWith.items);
@ -1598,7 +1855,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
}
/* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */
if (ste->ste_type == FunctionBlock) {
if (_PyST_IsFunctionLike(ste)) {
long target_in_scope = _PyST_GetSymbol(ste, target_name);
if (target_in_scope & DEF_GLOBAL) {
if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))
@ -1633,7 +1890,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
}
}
/* We should always find either a FunctionBlock, ModuleBlock or ClassBlock
/* We should always find either a function-like block, ModuleBlock or ClassBlock
and should never fall to this case
*/
Py_UNREACHABLE();
@ -1806,7 +2063,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
VISIT_QUIT(st, 0);
/* Special-case super: it counts as a use of __class__ */
if (e->v.Name.ctx == Load &&
st->st_cur->ste_type == FunctionBlock &&
_PyST_IsFunctionLike(st->st_cur) &&
_PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) {
if (!symtable_add_def(st, &_Py_ID(__class__), USE, LOCATION(e)))
VISIT_QUIT(st, 0);
@ -1823,6 +2080,45 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
VISIT_QUIT(st, 1);
}
static int
symtable_visit_typeparam(struct symtable *st, typeparam_ty tp)
{
if (++st->recursion_depth > st->recursion_limit) {
PyErr_SetString(PyExc_RecursionError,
"maximum recursion depth exceeded during compilation");
VISIT_QUIT(st, 0);
}
switch(tp->kind) {
case TypeVar_kind:
if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
VISIT_QUIT(st, 0);
if (tp->v.TypeVar.bound) {
int is_in_class = st->st_cur->ste_can_see_class_scope;
if (!symtable_enter_block(st, tp->v.TypeVar.name,
TypeVarBoundBlock, (void *)tp,
LOCATION(tp)))
VISIT_QUIT(st, 0);
st->st_cur->ste_can_see_class_scope = is_in_class;
if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(tp->v.TypeVar.bound))) {
VISIT_QUIT(st, 0);
}
VISIT(st, expr, tp->v.TypeVar.bound);
if (!symtable_exit_block(st))
VISIT_QUIT(st, 0);
}
break;
case TypeVarTuple_kind:
if (!symtable_add_def(st, tp->v.TypeVarTuple.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
VISIT_QUIT(st, 0);
break;
case ParamSpec_kind:
if (!symtable_add_def(st, tp->v.ParamSpec.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
VISIT_QUIT(st, 0);
break;
}
VISIT_QUIT(st, 1);
}
static int
symtable_visit_pattern(struct symtable *st, pattern_ty p)
{
@ -2194,11 +2490,18 @@ symtable_visit_dictcomp(struct symtable *st, expr_ty e)
static int
symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_ty e)
{
if (st->st_cur->ste_type != AnnotationBlock) {
enum _block_type type = st->st_cur->ste_type;
if (type == AnnotationBlock)
PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
else if (type == TypeVarBoundBlock)
PyErr_Format(PyExc_SyntaxError, TYPEVAR_BOUND_NOT_ALLOWED, name);
else if (type == TypeAliasBlock)
PyErr_Format(PyExc_SyntaxError, TYPEALIAS_NOT_ALLOWED, name);
else if (type == TypeParamBlock)
PyErr_Format(PyExc_SyntaxError, TYPEPARAM_NOT_ALLOWED, name);
else
return 1;
}
PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
PyErr_RangedSyntaxLocationObject(st->st_filename,
e->lineno,
e->col_offset + 1,