mirror of
https://github.com/python/cpython.git
synced 2025-08-29 21:25:01 +00:00
hide the __class__ closure from the class body (#12370)
This commit is contained in:
parent
fe361dfab5
commit
312595ce3a
7 changed files with 221 additions and 152 deletions
|
@ -535,6 +535,37 @@ compiler_enter_scope(struct compiler *c, identifier name,
|
|||
compiler_unit_free(u);
|
||||
return 0;
|
||||
}
|
||||
if (u->u_ste->ste_needs_class_closure) {
|
||||
/* Cook up a implicit __class__ cell. */
|
||||
_Py_IDENTIFIER(__class__);
|
||||
PyObject *tuple, *name, *zero;
|
||||
int res;
|
||||
assert(u->u_scope_type == COMPILER_SCOPE_CLASS);
|
||||
assert(PyDict_Size(u->u_cellvars) == 0);
|
||||
name = _PyUnicode_FromId(&PyId___class__);
|
||||
if (!name) {
|
||||
compiler_unit_free(u);
|
||||
return 0;
|
||||
}
|
||||
tuple = PyTuple_Pack(2, name, Py_TYPE(name));
|
||||
if (!tuple) {
|
||||
compiler_unit_free(u);
|
||||
return 0;
|
||||
}
|
||||
zero = PyLong_FromLong(0);
|
||||
if (!zero) {
|
||||
Py_DECREF(tuple);
|
||||
compiler_unit_free(u);
|
||||
return 0;
|
||||
}
|
||||
res = PyDict_SetItem(u->u_cellvars, tuple, zero);
|
||||
Py_DECREF(tuple);
|
||||
Py_DECREF(zero);
|
||||
if (res < 0) {
|
||||
compiler_unit_free(u);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,
|
||||
PyDict_Size(u->u_cellvars));
|
||||
|
@ -1331,6 +1362,9 @@ compiler_mod(struct compiler *c, mod_ty mod)
|
|||
static int
|
||||
get_ref_type(struct compiler *c, PyObject *name)
|
||||
{
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
|
||||
!PyUnicode_CompareWithASCIIString(name, "__class__"))
|
||||
return CELL;
|
||||
int scope = PyST_GetScope(c->u->u_ste, name);
|
||||
if (scope == 0) {
|
||||
char buf[350];
|
||||
|
@ -1704,24 +1738,24 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
/* return the (empty) __class__ cell */
|
||||
str = PyUnicode_InternFromString("__class__");
|
||||
if (str == NULL) {
|
||||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
i = compiler_lookup_arg(c->u->u_cellvars, str);
|
||||
Py_DECREF(str);
|
||||
if (i == -1) {
|
||||
/* This happens when nobody references the cell */
|
||||
PyErr_Clear();
|
||||
/* Return None */
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
}
|
||||
else {
|
||||
if (c->u->u_ste->ste_needs_class_closure) {
|
||||
/* return the (empty) __class__ cell */
|
||||
str = PyUnicode_InternFromString("__class__");
|
||||
if (str == NULL) {
|
||||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
i = compiler_lookup_arg(c->u->u_cellvars, str);
|
||||
Py_DECREF(str);
|
||||
assert(i == 0);
|
||||
/* Return the cell where to store __class__ */
|
||||
ADDOP_I(c, LOAD_CLOSURE, i);
|
||||
}
|
||||
else {
|
||||
assert(PyDict_Size(c->u->u_cellvars) == 0);
|
||||
/* This happens when nobody references the cell. Return None. */
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
}
|
||||
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
||||
/* create the code object */
|
||||
co = assemble(c, 1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue