mirror of
https://github.com/python/cpython.git
synced 2025-07-12 13:55:34 +00:00
cleanup the construction of __qualname__ (closes #19301 again)
This commit is contained in:
parent
a7a150c7c6
commit
6b4f7803f8
5 changed files with 225 additions and 207 deletions
150
Python/compile.c
150
Python/compile.c
|
@ -94,6 +94,7 @@ enum {
|
|||
COMPILER_SCOPE_MODULE,
|
||||
COMPILER_SCOPE_CLASS,
|
||||
COMPILER_SCOPE_FUNCTION,
|
||||
COMPILER_SCOPE_LAMBDA,
|
||||
COMPILER_SCOPE_COMPREHENSION,
|
||||
};
|
||||
|
||||
|
@ -104,6 +105,7 @@ struct compiler_unit {
|
|||
PySTEntryObject *u_ste;
|
||||
|
||||
PyObject *u_name;
|
||||
PyObject *u_qualname; /* dot-separated qualified name (lazy) */
|
||||
int u_scope_type;
|
||||
|
||||
/* The following fields are dicts that map objects to
|
||||
|
@ -199,6 +201,7 @@ static int compiler_call_helper(struct compiler *c, int n,
|
|||
expr_ty starargs,
|
||||
expr_ty kwargs);
|
||||
static int compiler_try_except(struct compiler *, stmt_ty);
|
||||
static int compiler_set_qualname(struct compiler *);
|
||||
|
||||
static PyCodeObject *assemble(struct compiler *, int addNone);
|
||||
static PyObject *__doc__;
|
||||
|
@ -506,6 +509,7 @@ compiler_unit_free(struct compiler_unit *u)
|
|||
}
|
||||
Py_CLEAR(u->u_ste);
|
||||
Py_CLEAR(u->u_name);
|
||||
Py_CLEAR(u->u_qualname);
|
||||
Py_CLEAR(u->u_consts);
|
||||
Py_CLEAR(u->u_names);
|
||||
Py_CLEAR(u->u_varnames);
|
||||
|
@ -620,6 +624,11 @@ compiler_enter_scope(struct compiler *c, identifier name,
|
|||
if (compiler_use_new_block(c) == NULL)
|
||||
return 0;
|
||||
|
||||
if (u->u_scope_type != COMPILER_SCOPE_MODULE) {
|
||||
if (!compiler_set_qualname(c))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -647,71 +656,77 @@ compiler_exit_scope(struct compiler *c)
|
|||
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
compiler_scope_qualname(struct compiler *c, identifier scope_name)
|
||||
static int
|
||||
compiler_set_qualname(struct compiler *c)
|
||||
{
|
||||
Py_ssize_t stack_size;
|
||||
int global_scope;
|
||||
_Py_static_string(dot, ".");
|
||||
_Py_static_string(locals, "<locals>");
|
||||
struct compiler_unit *u;
|
||||
PyObject *capsule, *name, *seq, *dot_str, *locals_str;
|
||||
|
||||
u = c->u;
|
||||
seq = PyList_New(0);
|
||||
if (seq == NULL)
|
||||
return NULL;
|
||||
_Py_static_string(dot_locals, ".<locals>");
|
||||
Py_ssize_t stack_size;
|
||||
struct compiler_unit *u = c->u;
|
||||
PyObject *name, *base, *dot_str, *dot_locals_str;
|
||||
|
||||
base = NULL;
|
||||
stack_size = PyList_GET_SIZE(c->c_stack);
|
||||
assert(stack_size >= 1);
|
||||
global_scope = stack_size == 1;
|
||||
if (scope_name != NULL && !global_scope) {
|
||||
int scope;
|
||||
PyObject *mangled;
|
||||
if (stack_size > 1) {
|
||||
int scope, force_global = 0;
|
||||
struct compiler_unit *parent;
|
||||
PyObject *mangled, *capsule;
|
||||
|
||||
capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1);
|
||||
u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT);
|
||||
assert(u);
|
||||
mangled = _Py_Mangle(u->u_private, scope_name);
|
||||
if (!mangled)
|
||||
return NULL;
|
||||
scope = PyST_GetScope(u->u_ste, mangled);
|
||||
Py_DECREF(mangled);
|
||||
assert(scope != GLOBAL_IMPLICIT);
|
||||
if (scope == GLOBAL_EXPLICIT)
|
||||
global_scope = 1;
|
||||
}
|
||||
if (!global_scope) {
|
||||
Py_ssize_t i;
|
||||
for (i = 1; i < stack_size; i++) {
|
||||
capsule = PyList_GET_ITEM(c->c_stack, i);
|
||||
u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT);
|
||||
assert(u);
|
||||
assert(u->u_scope_type != COMPILER_SCOPE_MODULE);
|
||||
if (PyList_Append(seq, u->u_name))
|
||||
goto _error;
|
||||
if (u->u_scope_type == COMPILER_SCOPE_FUNCTION) {
|
||||
locals_str = _PyUnicode_FromId(&locals);
|
||||
if (locals_str == NULL)
|
||||
goto _error;
|
||||
if (PyList_Append(seq, locals_str))
|
||||
goto _error;
|
||||
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT);
|
||||
assert(parent);
|
||||
|
||||
if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) {
|
||||
assert(u->u_name);
|
||||
mangled = _Py_Mangle(parent->u_private, u->u_name);
|
||||
if (!mangled)
|
||||
return 0;
|
||||
scope = PyST_GetScope(parent->u_ste, mangled);
|
||||
Py_DECREF(mangled);
|
||||
assert(scope != GLOBAL_IMPLICIT);
|
||||
if (scope == GLOBAL_EXPLICIT)
|
||||
force_global = 1;
|
||||
}
|
||||
|
||||
if (!force_global) {
|
||||
if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION
|
||||
|| parent->u_scope_type == COMPILER_SCOPE_LAMBDA) {
|
||||
dot_locals_str = _PyUnicode_FromId(&dot_locals);
|
||||
if (dot_locals_str == NULL)
|
||||
return 0;
|
||||
base = PyUnicode_Concat(parent->u_qualname, dot_locals_str);
|
||||
if (base == NULL)
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
Py_INCREF(parent->u_qualname);
|
||||
base = parent->u_qualname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u = c->u;
|
||||
if (PyList_Append(seq, u->u_name))
|
||||
goto _error;
|
||||
dot_str = _PyUnicode_FromId(&dot);
|
||||
if (dot_str == NULL)
|
||||
goto _error;
|
||||
name = PyUnicode_Join(dot_str, seq);
|
||||
Py_DECREF(seq);
|
||||
return name;
|
||||
if (base != NULL) {
|
||||
dot_str = _PyUnicode_FromId(&dot);
|
||||
if (dot_str == NULL) {
|
||||
Py_DECREF(base);
|
||||
return 0;
|
||||
}
|
||||
name = PyUnicode_Concat(base, dot_str);
|
||||
Py_DECREF(base);
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
PyUnicode_Append(&name, u->u_name);
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
Py_INCREF(u->u_name);
|
||||
name = u->u_name;
|
||||
}
|
||||
u->u_qualname = name;
|
||||
|
||||
_error:
|
||||
Py_XDECREF(seq);
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate a new block and return a pointer to it.
|
||||
|
@ -1661,9 +1676,10 @@ compiler_function(struct compiler *c, stmt_ty s)
|
|||
VISIT_IN_SCOPE(c, stmt, st);
|
||||
}
|
||||
co = assemble(c, 1);
|
||||
qualname = compiler_scope_qualname(c, s->v.FunctionDef.name);
|
||||
qualname = c->u->u_qualname;
|
||||
Py_INCREF(qualname);
|
||||
compiler_exit_scope(c);
|
||||
if (qualname == NULL || co == NULL) {
|
||||
if (co == NULL) {
|
||||
Py_XDECREF(qualname);
|
||||
Py_XDECREF(co);
|
||||
return 0;
|
||||
|
@ -1733,14 +1749,8 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
return 0;
|
||||
}
|
||||
Py_DECREF(str);
|
||||
/* store the __qualname__ */
|
||||
str = compiler_scope_qualname(c, s->v.ClassDef.name);
|
||||
if (!str) {
|
||||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
ADDOP_O(c, LOAD_CONST, str, consts);
|
||||
Py_DECREF(str);
|
||||
assert(c->u->u_qualname);
|
||||
ADDOP_O(c, LOAD_CONST, c->u->u_qualname, consts);
|
||||
str = PyUnicode_InternFromString("__qualname__");
|
||||
if (!str || !compiler_nameop(c, str, Store)) {
|
||||
Py_XDECREF(str);
|
||||
|
@ -1855,7 +1865,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
|||
if (res < 0) return 0;
|
||||
kw_default_count = res;
|
||||
}
|
||||
if (!compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION,
|
||||
if (!compiler_enter_scope(c, name, COMPILER_SCOPE_LAMBDA,
|
||||
(void *)e, e->lineno))
|
||||
return 0;
|
||||
|
||||
|
@ -1874,9 +1884,10 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
|||
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
||||
}
|
||||
co = assemble(c, 1);
|
||||
qualname = compiler_scope_qualname(c, NULL);
|
||||
qualname = c->u->u_qualname;
|
||||
Py_INCREF(qualname);
|
||||
compiler_exit_scope(c);
|
||||
if (qualname == NULL || co == NULL)
|
||||
if (co == NULL)
|
||||
return 0;
|
||||
|
||||
arglength = asdl_seq_LEN(args->defaults);
|
||||
|
@ -3151,9 +3162,10 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
|||
}
|
||||
|
||||
co = assemble(c, 1);
|
||||
qualname = compiler_scope_qualname(c, NULL);
|
||||
qualname = c->u->u_qualname;
|
||||
Py_INCREF(qualname);
|
||||
compiler_exit_scope(c);
|
||||
if (qualname == NULL || co == NULL)
|
||||
if (co == NULL)
|
||||
goto error;
|
||||
|
||||
if (!compiler_make_closure(c, co, 0, qualname))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue