mirror of https://github.com/python/cpython
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:
parent
fdafdc235e
commit
24d8b88420
|
@ -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=[],
|
||||
|
|
|
@ -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
|
||||
# -----------
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: \
|
||||
|
|
|
@ -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), \
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
26
Lib/ast.py
26
Lib/ast.py
|
@ -1051,6 +1051,7 @@ class _Unparser(NodeVisitor):
|
|||
self.fill("@")
|
||||
self.traverse(deco)
|
||||
self.fill("class " + node.name)
|
||||
self._typeparams_helper(node.typeparams)
|
||||
with self.delimit_if("(", ")", condition = node.bases or node.keywords):
|
||||
comma = False
|
||||
for e in node.bases:
|
||||
|
@ -1082,6 +1083,7 @@ class _Unparser(NodeVisitor):
|
|||
self.traverse(deco)
|
||||
def_str = fill_suffix + " " + node.name
|
||||
self.fill(def_str)
|
||||
self._typeparams_helper(node.typeparams)
|
||||
with self.delimit("(", ")"):
|
||||
self.traverse(node.args)
|
||||
if node.returns:
|
||||
|
@ -1090,6 +1092,30 @@ class _Unparser(NodeVisitor):
|
|||
with self.block(extra=self.get_type_comment(node)):
|
||||
self._write_docstring_and_traverse_body(node)
|
||||
|
||||
def _typeparams_helper(self, typeparams):
|
||||
if typeparams is not None and len(typeparams) > 0:
|
||||
with self.delimit("[", "]"):
|
||||
self.interleave(lambda: self.write(", "), self.traverse, typeparams)
|
||||
|
||||
def visit_TypeVar(self, node):
|
||||
self.write(node.name)
|
||||
if node.bound:
|
||||
self.write(": ")
|
||||
self.traverse(node.bound)
|
||||
|
||||
def visit_TypeVarTuple(self, node):
|
||||
self.write("*" + node.name)
|
||||
|
||||
def visit_ParamSpec(self, node):
|
||||
self.write("**" + node.name)
|
||||
|
||||
def visit_TypeAlias(self, node):
|
||||
self.fill("type ")
|
||||
self.traverse(node.name)
|
||||
self._typeparams_helper(node.typeparams)
|
||||
self.write(" = ")
|
||||
self.traverse(node.value)
|
||||
|
||||
def visit_For(self, node):
|
||||
self._for_helper("for ", node)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -56,7 +56,8 @@ kwlist = [
|
|||
softkwlist = [
|
||||
'_',
|
||||
'case',
|
||||
'match'
|
||||
'match',
|
||||
'type'
|
||||
]
|
||||
|
||||
iskeyword = frozenset(kwlist).__contains__
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)))]),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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))
|
|
@ -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)
|
|
@ -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,
|
||||
|
|
611
Lib/typing.py
611
Lib/typing.py
|
@ -23,6 +23,7 @@ from abc import abstractmethod, ABCMeta
|
|||
import collections
|
||||
from collections import defaultdict
|
||||
import collections.abc
|
||||
import copyreg
|
||||
import contextlib
|
||||
import functools
|
||||
import operator
|
||||
|
@ -32,12 +33,16 @@ import types
|
|||
import warnings
|
||||
from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias
|
||||
|
||||
|
||||
try:
|
||||
from _typing import _idfunc
|
||||
except ImportError:
|
||||
def _idfunc(_, x):
|
||||
return x
|
||||
from _typing import (
|
||||
_idfunc,
|
||||
TypeVar,
|
||||
ParamSpec,
|
||||
TypeVarTuple,
|
||||
ParamSpecArgs,
|
||||
ParamSpecKwargs,
|
||||
TypeAliasType,
|
||||
Generic,
|
||||
)
|
||||
|
||||
# Please keep __all__ alphabetized within each category.
|
||||
__all__ = [
|
||||
|
@ -149,6 +154,7 @@ __all__ = [
|
|||
'TYPE_CHECKING',
|
||||
'TypeAlias',
|
||||
'TypeGuard',
|
||||
'TypeAliasType',
|
||||
'Unpack',
|
||||
]
|
||||
|
||||
|
@ -695,6 +701,15 @@ def Union(self, parameters):
|
|||
return _UnionGenericAlias(self, parameters, name="Optional")
|
||||
return _UnionGenericAlias(self, parameters)
|
||||
|
||||
def _make_union(left, right):
|
||||
"""Used from the C implementation of TypeVar.
|
||||
|
||||
TypeVar.__or__ calls this instead of returning types.UnionType
|
||||
because we want to allow unions between TypeVars and strings
|
||||
(forward references.)
|
||||
"""
|
||||
return Union[left, right]
|
||||
|
||||
@_SpecialForm
|
||||
def Optional(self, parameters):
|
||||
"""Optional type.
|
||||
|
@ -926,333 +941,162 @@ class _PickleUsingNameMixin:
|
|||
return self.__name__
|
||||
|
||||
|
||||
class _BoundVarianceMixin:
|
||||
"""Mixin giving __init__ bound and variance arguments.
|
||||
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:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
|
|
@ -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]*/
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 *
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
45
Python/ast.c
45
Python/ast.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
651
Python/compile.c
651
Python/compile.c
|
@ -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
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue