[Python-checkins] cpython: give explicitly global functions and classes a global __qualname__ (closes
benjamin.peterson
python-checkins at python.org
Sat Oct 19 22:06:18 CEST 2013
http://hg.python.org/cpython/rev/35b384ed594b
changeset: 86491:35b384ed594b
user: Benjamin Peterson <benjamin at python.org>
date: Sat Oct 19 16:01:13 2013 -0400
summary:
give explicitly global functions and classes a global __qualname__ (closes #19301)
files:
Lib/importlib/_bootstrap.py | 3 +-
Lib/test/test_descr.py | 5 +
Lib/test/test_funcattrs.py | 4 +
Misc/NEWS | 3 +
Python/compile.c | 54 +-
Python/importlib.h | 6645 +++++++++++-----------
6 files changed, 3262 insertions(+), 3452 deletions(-)
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -369,12 +369,13 @@
# free vars)
# Python 3.4a1 3270 (various tweaks to the __class__ closure)
# Python 3.4a1 3280 (remove implicit class argument)
+# Python 3.4a4 3290 (changes to __qualname__ computation)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
# due to the addition of new opcodes).
-MAGIC_NUMBER = (3280).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3290).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -4517,6 +4517,11 @@
self.assertRaises(TypeError, type.__dict__['__qualname__'].__set__,
str, 'Oink')
+ global Y
+ class Y:
+ pass
+ self.assertEqual(Y.__qualname__, 'Y')
+
def test_qualname_dict(self):
ns = {'__qualname__': 'some.name'}
tp = type('Foo', (), ns)
diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py
--- a/Lib/test/test_funcattrs.py
+++ b/Lib/test/test_funcattrs.py
@@ -7,6 +7,9 @@
def inner_function():
class LocalClass:
pass
+ global inner_global_function
+ def inner_global_function():
+ pass
return LocalClass
return lambda: inner_function
@@ -116,6 +119,7 @@
'global_function.<locals>.inner_function')
self.assertEqual(global_function()()().__qualname__,
'global_function.<locals>.inner_function.<locals>.LocalClass')
+ self.assertEqual(inner_global_function.__qualname__, 'inner_global_function')
self.b.__qualname__ = 'c'
self.assertEqual(self.b.__qualname__, 'c')
self.b.__qualname__ = 'd'
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
Core and Builtins
-----------------
+- Issue #19301: Give classes and functions that are explicitly marked global a
+ global qualname.
+
- Issue #19279: UTF-7 decoder no more produces illegal strings.
- Issue #16612: Add "Argument Clinic", a compile-time preprocessor for
diff --git a/Python/compile.c b/Python/compile.c
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -650,9 +650,10 @@
}
static PyObject *
-compiler_scope_qualname(struct compiler *c)
+compiler_scope_qualname(struct compiler *c, identifier scope_name)
{
- Py_ssize_t stack_size, i;
+ Py_ssize_t stack_size;
+ int global_scope;
_Py_static_string(dot, ".");
_Py_static_string(locals, "<locals>");
struct compiler_unit *u;
@@ -669,22 +670,41 @@
return NULL;
stack_size = PyList_GET_SIZE(c->c_stack);
- for (i = 0; i < stack_size; i++) {
- capsule = PyList_GET_ITEM(c->c_stack, i);
+ global_scope = stack_size <= 1;
+ if (scope_name != NULL && !global_scope) {
+ int scope;
+ PyObject *mangled;
+ capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1);
u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT);
assert(u);
- if (u->u_scope_type == COMPILER_SCOPE_MODULE)
- continue;
- 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)
+ 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 (PyList_Append(seq, locals_str))
- 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;
+ }
}
}
+
u = c->u;
if (PyList_Append(seq, u->u_name))
goto _error;
@@ -1649,7 +1669,7 @@
VISIT_IN_SCOPE(c, stmt, st);
}
co = assemble(c, 1);
- qualname = compiler_scope_qualname(c);
+ qualname = compiler_scope_qualname(c, s->v.FunctionDef.name);
compiler_exit_scope(c);
if (qualname == NULL || co == NULL) {
Py_XDECREF(qualname);
@@ -1722,7 +1742,7 @@
}
Py_DECREF(str);
/* store the __qualname__ */
- str = compiler_scope_qualname(c);
+ str = compiler_scope_qualname(c, s->v.ClassDef.name);
if (!str) {
compiler_exit_scope(c);
return 0;
@@ -1862,7 +1882,7 @@
ADDOP_IN_SCOPE(c, RETURN_VALUE);
}
co = assemble(c, 1);
- qualname = compiler_scope_qualname(c);
+ qualname = compiler_scope_qualname(c, NULL);
compiler_exit_scope(c);
if (qualname == NULL || co == NULL)
return 0;
@@ -3139,7 +3159,7 @@
}
co = assemble(c, 1);
- qualname = compiler_scope_qualname(c);
+ qualname = compiler_scope_qualname(c, NULL);
compiler_exit_scope(c);
if (qualname == NULL || co == NULL)
goto error;
diff --git a/Python/importlib.h b/Python/importlib.h
--- a/Python/importlib.h
+++ b/Python/importlib.h
[stripped]
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list