mirror of https://github.com/python/cpython
PEP 3155 / issue #13448: Qualified name for classes and functions.
This commit is contained in:
parent
0e86a5842d
commit
86a36b500a
|
@ -38,6 +38,16 @@ There are a few functions specific to Python functions.
|
||||||
object, the argument defaults and closure are set to *NULL*.
|
object, the argument defaults and closure are set to *NULL*.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)
|
||||||
|
|
||||||
|
As :c:func:`PyFunction_New`, but also allows to set the function object's
|
||||||
|
``__qualname__`` attribute. *qualname* should be a unicode object or NULL;
|
||||||
|
if NULL, the ``__qualname__`` attribute is set to the same value as its
|
||||||
|
``__name__`` attribute.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: PyObject* PyFunction_GetCode(PyObject *op)
|
.. c:function:: PyObject* PyFunction_GetCode(PyObject *op)
|
||||||
|
|
||||||
Return the code object associated with the function object *op*.
|
Return the code object associated with the function object *op*.
|
||||||
|
|
|
@ -465,6 +465,11 @@ PyFunction_New:PyObject*::+1:
|
||||||
PyFunction_New:PyObject*:code:+1:
|
PyFunction_New:PyObject*:code:+1:
|
||||||
PyFunction_New:PyObject*:globals:+1:
|
PyFunction_New:PyObject*:globals:+1:
|
||||||
|
|
||||||
|
PyFunction_NewWithQualName:PyObject*::+1:
|
||||||
|
PyFunction_NewWithQualName:PyObject*:code:+1:
|
||||||
|
PyFunction_NewWithQualName:PyObject*:globals:+1:
|
||||||
|
PyFunction_NewWithQualName:PyObject*:qualname:+1:
|
||||||
|
|
||||||
PyFunction_SetClosure:int:::
|
PyFunction_SetClosure:int:::
|
||||||
PyFunction_SetClosure:PyObject*:op:0:
|
PyFunction_SetClosure:PyObject*:op:0:
|
||||||
PyFunction_SetClosure:PyObject*:closure:+1:
|
PyFunction_SetClosure:PyObject*:closure:+1:
|
||||||
|
|
|
@ -544,6 +544,24 @@ Glossary
|
||||||
for piece in food:
|
for piece in food:
|
||||||
print(piece)
|
print(piece)
|
||||||
|
|
||||||
|
qualified name
|
||||||
|
A dotted name showing the "path" from a module's global scope to a
|
||||||
|
class, function or method defined in that module, as defined in
|
||||||
|
:pep:`3155`. For top-level functions and classes, the qualified name
|
||||||
|
is the same as the object's name::
|
||||||
|
|
||||||
|
>>> class C:
|
||||||
|
... class D:
|
||||||
|
... def meth(self):
|
||||||
|
... pass
|
||||||
|
...
|
||||||
|
>>> C.__qualname__
|
||||||
|
'C'
|
||||||
|
>>> C.D.__qualname__
|
||||||
|
'C.D'
|
||||||
|
>>> C.D.meth.__qualname__
|
||||||
|
'C.D.meth'
|
||||||
|
|
||||||
reference count
|
reference count
|
||||||
The number of references to an object. When the reference count of an
|
The number of references to an object. When the reference count of an
|
||||||
object drops to zero, it is deallocated. Reference counting is
|
object drops to zero, it is deallocated. Reference counting is
|
||||||
|
|
|
@ -2824,6 +2824,13 @@ types, where they are relevant. Some of these are not reported by the
|
||||||
The name of the class or type.
|
The name of the class or type.
|
||||||
|
|
||||||
|
|
||||||
|
.. attribute:: class.__qualname__
|
||||||
|
|
||||||
|
The :term:`qualified name` of the class or type.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: class.__mro__
|
.. attribute:: class.__mro__
|
||||||
|
|
||||||
This attribute is a tuple of classes that are considered when looking for
|
This attribute is a tuple of classes that are considered when looking for
|
||||||
|
|
|
@ -448,6 +448,11 @@ Callable types
|
||||||
+-------------------------+-------------------------------+-----------+
|
+-------------------------+-------------------------------+-----------+
|
||||||
| :attr:`__name__` | The function's name | Writable |
|
| :attr:`__name__` | The function's name | Writable |
|
||||||
+-------------------------+-------------------------------+-----------+
|
+-------------------------+-------------------------------+-----------+
|
||||||
|
| :attr:`__qualname__` | The function's | Writable |
|
||||||
|
| | :term:`qualified name` | |
|
||||||
|
| | | |
|
||||||
|
| | .. versionadded:: 3.3 | |
|
||||||
|
+-------------------------+-------------------------------+-----------+
|
||||||
| :attr:`__module__` | The name of the module the | Writable |
|
| :attr:`__module__` | The name of the module the | Writable |
|
||||||
| | function was defined in, or | |
|
| | function was defined in, or | |
|
||||||
| | ``None`` if unavailable. | |
|
| | ``None`` if unavailable. | |
|
||||||
|
|
|
@ -31,6 +31,7 @@ typedef struct {
|
||||||
PyObject *func_weakreflist; /* List of weak references */
|
PyObject *func_weakreflist; /* List of weak references */
|
||||||
PyObject *func_module; /* The __module__ attribute, can be anything */
|
PyObject *func_module; /* The __module__ attribute, can be anything */
|
||||||
PyObject *func_annotations; /* Annotations, a dict or NULL */
|
PyObject *func_annotations; /* Annotations, a dict or NULL */
|
||||||
|
PyObject *func_qualname; /* The qualified name */
|
||||||
|
|
||||||
/* Invariant:
|
/* Invariant:
|
||||||
* func_closure contains the bindings for func_code->co_freevars, so
|
* func_closure contains the bindings for func_code->co_freevars, so
|
||||||
|
@ -44,6 +45,7 @@ PyAPI_DATA(PyTypeObject) PyFunction_Type;
|
||||||
#define PyFunction_Check(op) (Py_TYPE(op) == &PyFunction_Type)
|
#define PyFunction_Check(op) (Py_TYPE(op) == &PyFunction_Type)
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_New(PyObject *, PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_New(PyObject *, PyObject *);
|
||||||
|
PyAPI_FUNC(PyObject *) PyFunction_NewWithQualName(PyObject *, PyObject *, PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_GetCode(PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_GetCode(PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_GetGlobals(PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_GetGlobals(PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *);
|
||||||
|
|
|
@ -418,7 +418,7 @@ typedef struct _heaptypeobject {
|
||||||
a given operator (e.g. __getitem__).
|
a given operator (e.g. __getitem__).
|
||||||
see add_operators() in typeobject.c . */
|
see add_operators() in typeobject.c . */
|
||||||
PyBufferProcs as_buffer;
|
PyBufferProcs as_buffer;
|
||||||
PyObject *ht_name, *ht_slots;
|
PyObject *ht_name, *ht_slots, *ht_qualname;
|
||||||
/* here are optional user slots, followed by the members. */
|
/* here are optional user slots, followed by the members. */
|
||||||
} PyHeapTypeObject;
|
} PyHeapTypeObject;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ def visiblename(name, all=None, obj=None):
|
||||||
if name in {'__builtins__', '__doc__', '__file__', '__path__',
|
if name in {'__builtins__', '__doc__', '__file__', '__path__',
|
||||||
'__module__', '__name__', '__slots__', '__package__',
|
'__module__', '__name__', '__slots__', '__package__',
|
||||||
'__cached__', '__author__', '__credits__', '__date__',
|
'__cached__', '__author__', '__credits__', '__date__',
|
||||||
'__version__'}:
|
'__version__', '__qualname__'}:
|
||||||
return 0
|
return 0
|
||||||
# Private names are hidden, but special names are displayed.
|
# Private names are hidden, but special names are displayed.
|
||||||
if name.startswith('__') and name.endswith('__'): return 1
|
if name.startswith('__') and name.endswith('__'): return 1
|
||||||
|
|
|
@ -16,7 +16,7 @@ cellvars: ('x',)
|
||||||
freevars: ()
|
freevars: ()
|
||||||
nlocals: 2
|
nlocals: 2
|
||||||
flags: 3
|
flags: 3
|
||||||
consts: ('None', '<code object g>')
|
consts: ('None', '<code object g>', "'f.<locals>.g'")
|
||||||
|
|
||||||
>>> dump(f(4).__code__)
|
>>> dump(f(4).__code__)
|
||||||
name: g
|
name: g
|
||||||
|
|
|
@ -4492,9 +4492,14 @@ class DictProxyTests(unittest.TestCase):
|
||||||
self.assertEqual(type(C.__dict__), type(B.__dict__))
|
self.assertEqual(type(C.__dict__), type(B.__dict__))
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
# Testing dict_proxy.__repr__
|
# Testing dict_proxy.__repr__.
|
||||||
dict_ = {k: v for k, v in self.C.__dict__.items()}
|
# We can't blindly compare with the repr of another dict as ordering
|
||||||
self.assertEqual(repr(self.C.__dict__), 'dict_proxy({!r})'.format(dict_))
|
# of keys and values is arbitrary and may differ.
|
||||||
|
r = repr(self.C.__dict__)
|
||||||
|
self.assertTrue(r.startswith('dict_proxy('), r)
|
||||||
|
self.assertTrue(r.endswith(')'), r)
|
||||||
|
for k, v in self.C.__dict__.items():
|
||||||
|
self.assertIn('{!r}: {!r}'.format(k, v), r)
|
||||||
|
|
||||||
|
|
||||||
class PTypesLongInitTest(unittest.TestCase):
|
class PTypesLongInitTest(unittest.TestCase):
|
||||||
|
|
|
@ -339,6 +339,7 @@ Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR
|
||||||
Constants:
|
Constants:
|
||||||
0: None
|
0: None
|
||||||
1: <code object f at (.*), file "(.*)", line (.*)>
|
1: <code object f at (.*), file "(.*)", line (.*)>
|
||||||
|
2: 'tricky.<locals>.f'
|
||||||
Variable names:
|
Variable names:
|
||||||
0: x
|
0: x
|
||||||
1: y
|
1: y
|
||||||
|
|
|
@ -2,6 +2,15 @@ from test import support
|
||||||
import types
|
import types
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
def global_function():
|
||||||
|
def inner_function():
|
||||||
|
class LocalClass:
|
||||||
|
pass
|
||||||
|
return LocalClass
|
||||||
|
return lambda: inner_function
|
||||||
|
|
||||||
|
|
||||||
class FuncAttrsTest(unittest.TestCase):
|
class FuncAttrsTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class F:
|
class F:
|
||||||
|
@ -96,6 +105,24 @@ class FunctionPropertiesTest(FuncAttrsTest):
|
||||||
self.assertEqual(self.fi.a.__name__, 'a')
|
self.assertEqual(self.fi.a.__name__, 'a')
|
||||||
self.cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError)
|
self.cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError)
|
||||||
|
|
||||||
|
def test___qualname__(self):
|
||||||
|
# PEP 3155
|
||||||
|
self.assertEqual(self.b.__qualname__, 'FuncAttrsTest.setUp.<locals>.b')
|
||||||
|
self.assertEqual(FuncAttrsTest.setUp.__qualname__, 'FuncAttrsTest.setUp')
|
||||||
|
self.assertEqual(global_function.__qualname__, 'global_function')
|
||||||
|
self.assertEqual(global_function().__qualname__,
|
||||||
|
'global_function.<locals>.<lambda>')
|
||||||
|
self.assertEqual(global_function()().__qualname__,
|
||||||
|
'global_function.<locals>.inner_function')
|
||||||
|
self.assertEqual(global_function()()().__qualname__,
|
||||||
|
'global_function.<locals>.inner_function.<locals>.LocalClass')
|
||||||
|
self.b.__qualname__ = 'c'
|
||||||
|
self.assertEqual(self.b.__qualname__, 'c')
|
||||||
|
self.b.__qualname__ = 'd'
|
||||||
|
self.assertEqual(self.b.__qualname__, 'd')
|
||||||
|
# __qualname__ must be a string
|
||||||
|
self.cannot_set_attr(self.b, '__qualname__', 7, TypeError)
|
||||||
|
|
||||||
def test___code__(self):
|
def test___code__(self):
|
||||||
num_one, num_two = 7, 8
|
num_one, num_two = 7, 8
|
||||||
def a(): pass
|
def a(): pass
|
||||||
|
|
|
@ -159,6 +159,7 @@ Use a __prepare__ method that returns an instrumented dict.
|
||||||
... bar = 123
|
... bar = 123
|
||||||
...
|
...
|
||||||
d['__module__'] = 'test.test_metaclass'
|
d['__module__'] = 'test.test_metaclass'
|
||||||
|
d['__qualname__'] = 'C'
|
||||||
d['foo'] = 4
|
d['foo'] = 4
|
||||||
d['foo'] = 42
|
d['foo'] = 42
|
||||||
d['bar'] = 123
|
d['bar'] = 123
|
||||||
|
@ -177,12 +178,12 @@ Use a metaclass that doesn't derive from type.
|
||||||
... b = 24
|
... b = 24
|
||||||
...
|
...
|
||||||
meta: C ()
|
meta: C ()
|
||||||
ns: [('__module__', 'test.test_metaclass'), ('a', 42), ('b', 24)]
|
ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)]
|
||||||
kw: []
|
kw: []
|
||||||
>>> type(C) is dict
|
>>> type(C) is dict
|
||||||
True
|
True
|
||||||
>>> print(sorted(C.items()))
|
>>> print(sorted(C.items()))
|
||||||
[('__module__', 'test.test_metaclass'), ('a', 42), ('b', 24)]
|
[('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)]
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
And again, with a __prepare__ attribute.
|
And again, with a __prepare__ attribute.
|
||||||
|
@ -199,11 +200,12 @@ And again, with a __prepare__ attribute.
|
||||||
...
|
...
|
||||||
prepare: C () [('other', 'booh')]
|
prepare: C () [('other', 'booh')]
|
||||||
d['__module__'] = 'test.test_metaclass'
|
d['__module__'] = 'test.test_metaclass'
|
||||||
|
d['__qualname__'] = 'C'
|
||||||
d['a'] = 1
|
d['a'] = 1
|
||||||
d['a'] = 2
|
d['a'] = 2
|
||||||
d['b'] = 3
|
d['b'] = 3
|
||||||
meta: C ()
|
meta: C ()
|
||||||
ns: [('__module__', 'test.test_metaclass'), ('a', 2), ('b', 3)]
|
ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 2), ('b', 3)]
|
||||||
kw: [('other', 'booh')]
|
kw: [('other', 'booh')]
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
|
|
|
@ -129,8 +129,8 @@ class ReprTests(unittest.TestCase):
|
||||||
self.assertIn(s.find("..."), [12, 13])
|
self.assertIn(s.find("..."), [12, 13])
|
||||||
|
|
||||||
def test_lambda(self):
|
def test_lambda(self):
|
||||||
self.assertTrue(repr(lambda x: x).startswith(
|
r = repr(lambda x: x)
|
||||||
"<function <lambda"))
|
self.assertTrue(r.startswith("<function ReprTests.test_lambda.<locals>.<lambda"), r)
|
||||||
# XXX anonymous functions? see func_repr
|
# XXX anonymous functions? see func_repr
|
||||||
|
|
||||||
def test_builtin_function(self):
|
def test_builtin_function(self):
|
||||||
|
@ -278,13 +278,14 @@ class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
''')
|
''')
|
||||||
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
|
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
|
||||||
# Unbound methods first
|
# Unbound methods first
|
||||||
self.assertTrue(repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod).startswith(
|
r = repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod)
|
||||||
'<function amethod'))
|
self.assertTrue(r.startswith('<function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod'), r)
|
||||||
# Bound method next
|
# Bound method next
|
||||||
iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
|
iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
|
||||||
self.assertTrue(repr(iqux.amethod).startswith(
|
r = repr(iqux.amethod)
|
||||||
|
self.assertTrue(r.startswith(
|
||||||
'<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa object at 0x' \
|
'<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa object at 0x' \
|
||||||
% (qux.__name__,) ))
|
% (qux.__name__,) ), r)
|
||||||
|
|
||||||
def test_builtin_function(self):
|
def test_builtin_function(self):
|
||||||
# XXX test built-in functions and methods with really long names
|
# XXX test built-in functions and methods with really long names
|
||||||
|
|
|
@ -730,7 +730,7 @@ class SizeofTest(unittest.TestCase):
|
||||||
check(x, size(vh + '12P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))
|
check(x, size(vh + '12P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))
|
||||||
# function
|
# function
|
||||||
def func(): pass
|
def func(): pass
|
||||||
check(func, size(h + '11P'))
|
check(func, size(h + '12P'))
|
||||||
class c():
|
class c():
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def foo():
|
def foo():
|
||||||
|
@ -828,7 +828,7 @@ class SizeofTest(unittest.TestCase):
|
||||||
# type
|
# type
|
||||||
# (PyTypeObject + PyNumberMethods + PyMappingMethods +
|
# (PyTypeObject + PyNumberMethods + PyMappingMethods +
|
||||||
# PySequenceMethods + PyBufferProcs)
|
# PySequenceMethods + PyBufferProcs)
|
||||||
s = size(vh + 'P2P15Pl4PP9PP11PI') + size('16Pi17P 3P 10P 2P 2P')
|
s = size(vh + 'P2P15Pl4PP9PP11PI') + size('16Pi17P 3P 10P 2P 3P')
|
||||||
check(int, s)
|
check(int, s)
|
||||||
# class
|
# class
|
||||||
class newstyleclass(object): pass
|
class newstyleclass(object): pass
|
||||||
|
|
|
@ -10,6 +10,8 @@ What's New in Python 3.3 Alpha 1?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- PEP 3155 / issue #13448: Qualified name for classes and functions.
|
||||||
|
|
||||||
- Issue #13436: Fix a bogus error message when an AST object was passed
|
- Issue #13436: Fix a bogus error message when an AST object was passed
|
||||||
an invalid integer value.
|
an invalid integer value.
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyFunction_New(PyObject *code, PyObject *globals)
|
PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)
|
||||||
{
|
{
|
||||||
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
|
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
|
||||||
&PyFunction_Type);
|
&PyFunction_Type);
|
||||||
|
@ -54,6 +54,11 @@ PyFunction_New(PyObject *code, PyObject *globals)
|
||||||
Py_INCREF(module);
|
Py_INCREF(module);
|
||||||
op->func_module = module;
|
op->func_module = module;
|
||||||
}
|
}
|
||||||
|
if (qualname)
|
||||||
|
op->func_qualname = qualname;
|
||||||
|
else
|
||||||
|
op->func_qualname = op->func_name;
|
||||||
|
Py_INCREF(op->func_qualname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -61,6 +66,12 @@ PyFunction_New(PyObject *code, PyObject *globals)
|
||||||
return (PyObject *)op;
|
return (PyObject *)op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyFunction_New(PyObject *code, PyObject *globals)
|
||||||
|
{
|
||||||
|
return PyFunction_NewWithQualName(code, globals, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyFunction_GetCode(PyObject *op)
|
PyFunction_GetCode(PyObject *op)
|
||||||
{
|
{
|
||||||
|
@ -333,6 +344,32 @@ func_set_name(PyFunctionObject *op, PyObject *value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
func_get_qualname(PyFunctionObject *op)
|
||||||
|
{
|
||||||
|
Py_INCREF(op->func_qualname);
|
||||||
|
return op->func_qualname;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
func_set_qualname(PyFunctionObject *op, PyObject *value)
|
||||||
|
{
|
||||||
|
PyObject *tmp;
|
||||||
|
|
||||||
|
/* Not legal to del f.__qualname__ or to set it to anything
|
||||||
|
* other than a string object. */
|
||||||
|
if (value == NULL || !PyUnicode_Check(value)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"__qualname__ must be set to a string object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmp = op->func_qualname;
|
||||||
|
Py_INCREF(value);
|
||||||
|
op->func_qualname = value;
|
||||||
|
Py_DECREF(tmp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
func_get_defaults(PyFunctionObject *op)
|
func_get_defaults(PyFunctionObject *op)
|
||||||
{
|
{
|
||||||
|
@ -441,6 +478,7 @@ static PyGetSetDef func_getsetlist[] = {
|
||||||
(setter)func_set_annotations},
|
(setter)func_set_annotations},
|
||||||
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
|
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
|
||||||
{"__name__", (getter)func_get_name, (setter)func_set_name},
|
{"__name__", (getter)func_get_name, (setter)func_set_name},
|
||||||
|
{"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -561,6 +599,7 @@ func_dealloc(PyFunctionObject *op)
|
||||||
Py_XDECREF(op->func_dict);
|
Py_XDECREF(op->func_dict);
|
||||||
Py_XDECREF(op->func_closure);
|
Py_XDECREF(op->func_closure);
|
||||||
Py_XDECREF(op->func_annotations);
|
Py_XDECREF(op->func_annotations);
|
||||||
|
Py_XDECREF(op->func_qualname);
|
||||||
PyObject_GC_Del(op);
|
PyObject_GC_Del(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,7 +607,7 @@ static PyObject*
|
||||||
func_repr(PyFunctionObject *op)
|
func_repr(PyFunctionObject *op)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromFormat("<function %U at %p>",
|
return PyUnicode_FromFormat("<function %U at %p>",
|
||||||
op->func_name, op);
|
op->func_qualname, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -584,6 +623,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
|
||||||
Py_VISIT(f->func_dict);
|
Py_VISIT(f->func_dict);
|
||||||
Py_VISIT(f->func_closure);
|
Py_VISIT(f->func_closure);
|
||||||
Py_VISIT(f->func_annotations);
|
Py_VISIT(f->func_annotations);
|
||||||
|
Py_VISIT(f->func_qualname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,6 +242,19 @@ type_name(PyTypeObject *type, void *context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
type_qualname(PyTypeObject *type, void *context)
|
||||||
|
{
|
||||||
|
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
||||||
|
PyHeapTypeObject* et = (PyHeapTypeObject*)type;
|
||||||
|
Py_INCREF(et->ht_qualname);
|
||||||
|
return et->ht_qualname;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return type_name(type, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
type_set_name(PyTypeObject *type, PyObject *value, void *context)
|
type_set_name(PyTypeObject *type, PyObject *value, void *context)
|
||||||
{
|
{
|
||||||
|
@ -286,6 +299,25 @@ type_set_name(PyTypeObject *type, PyObject *value, void *context)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
type_set_qualname(PyTypeObject *type, PyObject *value, void *context)
|
||||||
|
{
|
||||||
|
PyHeapTypeObject* et;
|
||||||
|
|
||||||
|
if (!PyUnicode_Check(value)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"can only assign string to %s.__qualname__, not '%s'",
|
||||||
|
type->tp_name, Py_TYPE(value)->tp_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
et = (PyHeapTypeObject*)type;
|
||||||
|
Py_INCREF(value);
|
||||||
|
Py_DECREF(et->ht_qualname);
|
||||||
|
et->ht_qualname = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
type_module(PyTypeObject *type, void *context)
|
type_module(PyTypeObject *type, void *context)
|
||||||
{
|
{
|
||||||
|
@ -631,6 +663,7 @@ type___subclasscheck__(PyObject *type, PyObject *inst)
|
||||||
|
|
||||||
static PyGetSetDef type_getsets[] = {
|
static PyGetSetDef type_getsets[] = {
|
||||||
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
|
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
|
||||||
|
{"__qualname__", (getter)type_qualname, (setter)type_set_qualname, NULL},
|
||||||
{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
|
{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
|
||||||
{"__module__", (getter)type_module, (setter)type_set_module, NULL},
|
{"__module__", (getter)type_module, (setter)type_set_module, NULL},
|
||||||
{"__abstractmethods__", (getter)type_abstractmethods,
|
{"__abstractmethods__", (getter)type_abstractmethods,
|
||||||
|
@ -652,7 +685,7 @@ type_repr(PyTypeObject *type)
|
||||||
Py_DECREF(mod);
|
Py_DECREF(mod);
|
||||||
mod = NULL;
|
mod = NULL;
|
||||||
}
|
}
|
||||||
name = type_name(type, NULL);
|
name = type_qualname(type, NULL);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -1955,7 +1988,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyObject *name, *bases, *dict;
|
PyObject *name, *bases, *dict;
|
||||||
static char *kwlist[] = {"name", "bases", "dict", 0};
|
static char *kwlist[] = {"name", "bases", "dict", 0};
|
||||||
PyObject *slots, *tmp, *newslots;
|
PyObject *qualname, *slots, *tmp, *newslots;
|
||||||
PyTypeObject *type, *base, *tmptype, *winner;
|
PyTypeObject *type, *base, *tmptype, *winner;
|
||||||
PyHeapTypeObject *et;
|
PyHeapTypeObject *et;
|
||||||
PyMemberDef *mp;
|
PyMemberDef *mp;
|
||||||
|
@ -2032,6 +2065,18 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for a __qualname__ variable in dict */
|
||||||
|
qualname = PyDict_GetItemString(dict, "__qualname__");
|
||||||
|
if (qualname == NULL) {
|
||||||
|
qualname = name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (PyDict_DelItemString(dict, "__qualname__") < 0) {
|
||||||
|
Py_DECREF(bases);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for a __slots__ sequence variable in dict, and count it */
|
/* Check for a __slots__ sequence variable in dict, and count it */
|
||||||
slots = PyDict_GetItemString(dict, "__slots__");
|
slots = PyDict_GetItemString(dict, "__slots__");
|
||||||
nslots = 0;
|
nslots = 0;
|
||||||
|
@ -2185,7 +2230,9 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
|
||||||
/* Keep name and slots alive in the extended type object */
|
/* Keep name and slots alive in the extended type object */
|
||||||
et = (PyHeapTypeObject *)type;
|
et = (PyHeapTypeObject *)type;
|
||||||
Py_INCREF(name);
|
Py_INCREF(name);
|
||||||
|
Py_INCREF(qualname);
|
||||||
et->ht_name = name;
|
et->ht_name = name;
|
||||||
|
et->ht_qualname = qualname;
|
||||||
et->ht_slots = slots;
|
et->ht_slots = slots;
|
||||||
|
|
||||||
/* Initialize tp_flags */
|
/* Initialize tp_flags */
|
||||||
|
@ -2369,6 +2416,8 @@ PyObject* PyType_FromSpec(PyType_Spec *spec)
|
||||||
res->ht_name = PyUnicode_FromString(spec->name);
|
res->ht_name = PyUnicode_FromString(spec->name);
|
||||||
if (!res->ht_name)
|
if (!res->ht_name)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
res->ht_qualname = res->ht_name;
|
||||||
|
Py_INCREF(res->ht_qualname);
|
||||||
res->ht_type.tp_name = _PyUnicode_AsString(res->ht_name);
|
res->ht_type.tp_name = _PyUnicode_AsString(res->ht_name);
|
||||||
if (!res->ht_type.tp_name)
|
if (!res->ht_type.tp_name)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -2568,6 +2617,7 @@ type_dealloc(PyTypeObject *type)
|
||||||
*/
|
*/
|
||||||
PyObject_Free((char *)type->tp_doc);
|
PyObject_Free((char *)type->tp_doc);
|
||||||
Py_XDECREF(et->ht_name);
|
Py_XDECREF(et->ht_name);
|
||||||
|
Py_XDECREF(et->ht_qualname);
|
||||||
Py_XDECREF(et->ht_slots);
|
Py_XDECREF(et->ht_slots);
|
||||||
Py_TYPE(type)->tp_free((PyObject *)type);
|
Py_TYPE(type)->tp_free((PyObject *)type);
|
||||||
}
|
}
|
||||||
|
@ -2983,7 +3033,7 @@ object_repr(PyObject *self)
|
||||||
Py_DECREF(mod);
|
Py_DECREF(mod);
|
||||||
mod = NULL;
|
mod = NULL;
|
||||||
}
|
}
|
||||||
name = type_name(type, NULL);
|
name = type_qualname(type, NULL);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins"))
|
if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins"))
|
||||||
|
|
|
@ -2687,9 +2687,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
int kwdefaults = (oparg>>8) & 0xff;
|
int kwdefaults = (oparg>>8) & 0xff;
|
||||||
int num_annotations = (oparg >> 16) & 0x7fff;
|
int num_annotations = (oparg >> 16) & 0x7fff;
|
||||||
|
|
||||||
|
w = POP(); /* qualname */
|
||||||
v = POP(); /* code object */
|
v = POP(); /* code object */
|
||||||
x = PyFunction_New(v, f->f_globals);
|
x = PyFunction_NewWithQualName(v, f->f_globals, w);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
|
Py_DECREF(w);
|
||||||
|
|
||||||
if (x != NULL && opcode == MAKE_CLOSURE) {
|
if (x != NULL && opcode == MAKE_CLOSURE) {
|
||||||
v = POP();
|
v = POP();
|
||||||
|
|
139
Python/compile.c
139
Python/compile.c
|
@ -90,6 +90,13 @@ struct fblockinfo {
|
||||||
basicblock *fb_block;
|
basicblock *fb_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
COMPILER_SCOPE_MODULE,
|
||||||
|
COMPILER_SCOPE_CLASS,
|
||||||
|
COMPILER_SCOPE_FUNCTION,
|
||||||
|
COMPILER_SCOPE_COMPREHENSION,
|
||||||
|
};
|
||||||
|
|
||||||
/* The following items change on entry and exit of code blocks.
|
/* The following items change on entry and exit of code blocks.
|
||||||
They must be saved and restored when returning to a block.
|
They must be saved and restored when returning to a block.
|
||||||
*/
|
*/
|
||||||
|
@ -97,6 +104,9 @@ struct compiler_unit {
|
||||||
PySTEntryObject *u_ste;
|
PySTEntryObject *u_ste;
|
||||||
|
|
||||||
PyObject *u_name;
|
PyObject *u_name;
|
||||||
|
PyObject *u_qualname; /* dot-separated qualified name (lazy) */
|
||||||
|
int u_scope_type;
|
||||||
|
|
||||||
/* The following fields are dicts that map objects to
|
/* The following fields are dicts that map objects to
|
||||||
the index of them in co_XXX. The index is used as
|
the index of them in co_XXX. The index is used as
|
||||||
the argument for opcodes that refer to those collections.
|
the argument for opcodes that refer to those collections.
|
||||||
|
@ -149,7 +159,7 @@ struct compiler {
|
||||||
PyArena *c_arena; /* pointer to memory allocation arena */
|
PyArena *c_arena; /* pointer to memory allocation arena */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int compiler_enter_scope(struct compiler *, identifier, void *, int);
|
static int compiler_enter_scope(struct compiler *, identifier, int, void *, int);
|
||||||
static void compiler_free(struct compiler *);
|
static void compiler_free(struct compiler *);
|
||||||
static basicblock *compiler_new_block(struct compiler *);
|
static basicblock *compiler_new_block(struct compiler *);
|
||||||
static int compiler_next_instr(struct compiler *, basicblock *);
|
static int compiler_next_instr(struct compiler *, basicblock *);
|
||||||
|
@ -457,6 +467,7 @@ compiler_unit_free(struct compiler_unit *u)
|
||||||
}
|
}
|
||||||
Py_CLEAR(u->u_ste);
|
Py_CLEAR(u->u_ste);
|
||||||
Py_CLEAR(u->u_name);
|
Py_CLEAR(u->u_name);
|
||||||
|
Py_CLEAR(u->u_qualname);
|
||||||
Py_CLEAR(u->u_consts);
|
Py_CLEAR(u->u_consts);
|
||||||
Py_CLEAR(u->u_names);
|
Py_CLEAR(u->u_names);
|
||||||
Py_CLEAR(u->u_varnames);
|
Py_CLEAR(u->u_varnames);
|
||||||
|
@ -467,8 +478,8 @@ compiler_unit_free(struct compiler_unit *u)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_enter_scope(struct compiler *c, identifier name, void *key,
|
compiler_enter_scope(struct compiler *c, identifier name,
|
||||||
int lineno)
|
int scope_type, void *key, int lineno)
|
||||||
{
|
{
|
||||||
struct compiler_unit *u;
|
struct compiler_unit *u;
|
||||||
|
|
||||||
|
@ -479,6 +490,7 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(u, 0, sizeof(struct compiler_unit));
|
memset(u, 0, sizeof(struct compiler_unit));
|
||||||
|
u->u_scope_type = scope_type;
|
||||||
u->u_argcount = 0;
|
u->u_argcount = 0;
|
||||||
u->u_kwonlyargcount = 0;
|
u->u_kwonlyargcount = 0;
|
||||||
u->u_ste = PySymtable_Lookup(c->c_st, key);
|
u->u_ste = PySymtable_Lookup(c->c_st, key);
|
||||||
|
@ -566,6 +578,59 @@ compiler_exit_scope(struct compiler *c)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
compiler_scope_qualname(struct compiler *c)
|
||||||
|
{
|
||||||
|
Py_ssize_t stack_size, i;
|
||||||
|
_Py_static_string(dot, ".");
|
||||||
|
_Py_static_string(locals, "<locals>");
|
||||||
|
struct compiler_unit *u;
|
||||||
|
PyObject *capsule, *name, *seq, *dot_str, *locals_str;
|
||||||
|
|
||||||
|
u = c->u;
|
||||||
|
if (u->u_qualname != NULL) {
|
||||||
|
Py_INCREF(u->u_qualname);
|
||||||
|
return u->u_qualname;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq = PyList_New(0);
|
||||||
|
if (seq == NULL)
|
||||||
|
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);
|
||||||
|
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)
|
||||||
|
goto _error;
|
||||||
|
if (PyList_Append(seq, locals_str))
|
||||||
|
goto _error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
u->u_qualname = name;
|
||||||
|
Py_XINCREF(name);
|
||||||
|
return name;
|
||||||
|
|
||||||
|
_error:
|
||||||
|
Py_XDECREF(seq);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a new block and return a pointer to it.
|
/* Allocate a new block and return a pointer to it.
|
||||||
Returns NULL on error.
|
Returns NULL on error.
|
||||||
*/
|
*/
|
||||||
|
@ -862,9 +927,9 @@ opcode_stack_effect(int opcode, int oparg)
|
||||||
case CALL_FUNCTION_VAR_KW:
|
case CALL_FUNCTION_VAR_KW:
|
||||||
return -NARGS(oparg)-2;
|
return -NARGS(oparg)-2;
|
||||||
case MAKE_FUNCTION:
|
case MAKE_FUNCTION:
|
||||||
return -NARGS(oparg) - ((oparg >> 16) & 0xffff);
|
return -1 -NARGS(oparg) - ((oparg >> 16) & 0xffff);
|
||||||
case MAKE_CLOSURE:
|
case MAKE_CLOSURE:
|
||||||
return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff);
|
return -2 - NARGS(oparg) - ((oparg >> 16) & 0xffff);
|
||||||
#undef NARGS
|
#undef NARGS
|
||||||
case BUILD_SLICE:
|
case BUILD_SLICE:
|
||||||
if (oparg == 3)
|
if (oparg == 3)
|
||||||
|
@ -1194,7 +1259,7 @@ compiler_mod(struct compiler *c, mod_ty mod)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Use 0 for firstlineno initially, will fixup in assemble(). */
|
/* Use 0 for firstlineno initially, will fixup in assemble(). */
|
||||||
if (!compiler_enter_scope(c, module, mod, 0))
|
if (!compiler_enter_scope(c, module, COMPILER_SCOPE_MODULE, mod, 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
switch (mod->kind) {
|
switch (mod->kind) {
|
||||||
case Module_kind:
|
case Module_kind:
|
||||||
|
@ -1270,11 +1335,15 @@ compiler_lookup_arg(PyObject *dict, PyObject *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_make_closure(struct compiler *c, PyCodeObject *co, int args)
|
compiler_make_closure(struct compiler *c, PyCodeObject *co, int args, PyObject *qualname)
|
||||||
{
|
{
|
||||||
int i, free = PyCode_GetNumFree(co);
|
int i, free = PyCode_GetNumFree(co);
|
||||||
|
if (qualname == NULL)
|
||||||
|
qualname = co->co_name;
|
||||||
|
|
||||||
if (free == 0) {
|
if (free == 0) {
|
||||||
ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
|
ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
|
||||||
|
ADDOP_O(c, LOAD_CONST, qualname, consts);
|
||||||
ADDOP_I(c, MAKE_FUNCTION, args);
|
ADDOP_I(c, MAKE_FUNCTION, args);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1311,6 +1380,7 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, int args)
|
||||||
}
|
}
|
||||||
ADDOP_I(c, BUILD_TUPLE, free);
|
ADDOP_I(c, BUILD_TUPLE, free);
|
||||||
ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
|
ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
|
||||||
|
ADDOP_O(c, LOAD_CONST, qualname, consts);
|
||||||
ADDOP_I(c, MAKE_CLOSURE, args);
|
ADDOP_I(c, MAKE_CLOSURE, args);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1452,7 +1522,7 @@ static int
|
||||||
compiler_function(struct compiler *c, stmt_ty s)
|
compiler_function(struct compiler *c, stmt_ty s)
|
||||||
{
|
{
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
PyObject *first_const = Py_None;
|
PyObject *qualname, *first_const = Py_None;
|
||||||
arguments_ty args = s->v.FunctionDef.args;
|
arguments_ty args = s->v.FunctionDef.args;
|
||||||
expr_ty returns = s->v.FunctionDef.returns;
|
expr_ty returns = s->v.FunctionDef.returns;
|
||||||
asdl_seq* decos = s->v.FunctionDef.decorator_list;
|
asdl_seq* decos = s->v.FunctionDef.decorator_list;
|
||||||
|
@ -1478,7 +1548,8 @@ compiler_function(struct compiler *c, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
assert((num_annotations & 0xFFFF) == num_annotations);
|
assert((num_annotations & 0xFFFF) == num_annotations);
|
||||||
|
|
||||||
if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s,
|
if (!compiler_enter_scope(c, s->v.FunctionDef.name,
|
||||||
|
COMPILER_SCOPE_FUNCTION, (void *)s,
|
||||||
s->lineno))
|
s->lineno))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1500,14 +1571,19 @@ compiler_function(struct compiler *c, stmt_ty s)
|
||||||
VISIT_IN_SCOPE(c, stmt, st);
|
VISIT_IN_SCOPE(c, stmt, st);
|
||||||
}
|
}
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
|
qualname = compiler_scope_qualname(c);
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
if (co == NULL)
|
if (qualname == NULL || co == NULL) {
|
||||||
|
Py_XDECREF(qualname);
|
||||||
|
Py_XDECREF(co);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
arglength = asdl_seq_LEN(args->defaults);
|
arglength = asdl_seq_LEN(args->defaults);
|
||||||
arglength |= kw_default_count << 8;
|
arglength |= kw_default_count << 8;
|
||||||
arglength |= num_annotations << 16;
|
arglength |= num_annotations << 16;
|
||||||
compiler_make_closure(c, co, arglength);
|
compiler_make_closure(c, co, arglength, qualname);
|
||||||
|
Py_DECREF(qualname);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
/* decorators */
|
/* decorators */
|
||||||
|
@ -1542,7 +1618,8 @@ compiler_class(struct compiler *c, stmt_ty s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 1. compile the class body into a code object */
|
/* 1. compile the class body into a code object */
|
||||||
if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno))
|
if (!compiler_enter_scope(c, s->v.ClassDef.name,
|
||||||
|
COMPILER_SCOPE_CLASS, (void *)s, s->lineno))
|
||||||
return 0;
|
return 0;
|
||||||
/* this block represents what we do in the new scope */
|
/* this block represents what we do in the new scope */
|
||||||
{
|
{
|
||||||
|
@ -1572,6 +1649,21 @@ compiler_class(struct compiler *c, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Py_DECREF(str);
|
Py_DECREF(str);
|
||||||
|
/* store the __qualname__ */
|
||||||
|
str = compiler_scope_qualname(c);
|
||||||
|
if (!str) {
|
||||||
|
compiler_exit_scope(c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ADDOP_O(c, LOAD_CONST, str, consts);
|
||||||
|
Py_DECREF(str);
|
||||||
|
str = PyUnicode_InternFromString("__qualname__");
|
||||||
|
if (!str || !compiler_nameop(c, str, Store)) {
|
||||||
|
Py_XDECREF(str);
|
||||||
|
compiler_exit_scope(c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Py_DECREF(str);
|
||||||
/* compile the body proper */
|
/* compile the body proper */
|
||||||
if (!compiler_body(c, s->v.ClassDef.body)) {
|
if (!compiler_body(c, s->v.ClassDef.body)) {
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
|
@ -1608,7 +1700,7 @@ compiler_class(struct compiler *c, stmt_ty s)
|
||||||
ADDOP(c, LOAD_BUILD_CLASS);
|
ADDOP(c, LOAD_BUILD_CLASS);
|
||||||
|
|
||||||
/* 3. load a function (or closure) made from the code object */
|
/* 3. load a function (or closure) made from the code object */
|
||||||
compiler_make_closure(c, co, 0);
|
compiler_make_closure(c, co, 0, NULL);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
/* 4. load class name */
|
/* 4. load class name */
|
||||||
|
@ -1659,6 +1751,7 @@ static int
|
||||||
compiler_lambda(struct compiler *c, expr_ty e)
|
compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
{
|
{
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
|
PyObject *qualname;
|
||||||
static identifier name;
|
static identifier name;
|
||||||
int kw_default_count = 0, arglength;
|
int kw_default_count = 0, arglength;
|
||||||
arguments_ty args = e->v.Lambda.args;
|
arguments_ty args = e->v.Lambda.args;
|
||||||
|
@ -1678,7 +1771,8 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
}
|
}
|
||||||
if (args->defaults)
|
if (args->defaults)
|
||||||
VISIT_SEQ(c, expr, args->defaults);
|
VISIT_SEQ(c, expr, args->defaults);
|
||||||
if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
|
if (!compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION,
|
||||||
|
(void *)e, e->lineno))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Make None the first constant, so the lambda can't have a
|
/* Make None the first constant, so the lambda can't have a
|
||||||
|
@ -1696,13 +1790,15 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
||||||
}
|
}
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
|
qualname = compiler_scope_qualname(c);
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
if (co == NULL)
|
if (qualname == NULL || co == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
arglength = asdl_seq_LEN(args->defaults);
|
arglength = asdl_seq_LEN(args->defaults);
|
||||||
arglength |= kw_default_count << 8;
|
arglength |= kw_default_count << 8;
|
||||||
compiler_make_closure(c, co, arglength);
|
compiler_make_closure(c, co, arglength, qualname);
|
||||||
|
Py_DECREF(qualname);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2916,11 +3012,13 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
{
|
{
|
||||||
PyCodeObject *co = NULL;
|
PyCodeObject *co = NULL;
|
||||||
expr_ty outermost_iter;
|
expr_ty outermost_iter;
|
||||||
|
PyObject *qualname = NULL;
|
||||||
|
|
||||||
outermost_iter = ((comprehension_ty)
|
outermost_iter = ((comprehension_ty)
|
||||||
asdl_seq_GET(generators, 0))->iter;
|
asdl_seq_GET(generators, 0))->iter;
|
||||||
|
|
||||||
if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
|
if (!compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION,
|
||||||
|
(void *)e, e->lineno))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (type != COMP_GENEXP) {
|
if (type != COMP_GENEXP) {
|
||||||
|
@ -2953,12 +3051,14 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
}
|
}
|
||||||
|
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
|
qualname = compiler_scope_qualname(c);
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
if (co == NULL)
|
if (qualname == NULL || co == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!compiler_make_closure(c, co, 0))
|
if (!compiler_make_closure(c, co, 0, qualname))
|
||||||
goto error;
|
goto error;
|
||||||
|
Py_DECREF(qualname);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
VISIT(c, expr, outermost_iter);
|
VISIT(c, expr, outermost_iter);
|
||||||
|
@ -2968,6 +3068,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
error_in_scope:
|
error_in_scope:
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
error:
|
error:
|
||||||
|
Py_XDECREF(qualname);
|
||||||
Py_XDECREF(co);
|
Py_XDECREF(co);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,7 @@ typedef unsigned short mode_t;
|
||||||
tag: cpython-32
|
tag: cpython-32
|
||||||
Python 3.2a2 3180 (add DELETE_DEREF)
|
Python 3.2a2 3180 (add DELETE_DEREF)
|
||||||
Python 3.3a0 3190 __class__ super closure changed
|
Python 3.3a0 3190 __class__ super closure changed
|
||||||
|
Python 3.3a0 3200 (__qualname__ added)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* MAGIC must change whenever the bytecode emitted by the compiler may no
|
/* MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||||
|
@ -115,7 +116,7 @@ typedef unsigned short mode_t;
|
||||||
#define STRIFY(name) QUOTE(name)
|
#define STRIFY(name) QUOTE(name)
|
||||||
#define MAJOR STRIFY(PY_MAJOR_VERSION)
|
#define MAJOR STRIFY(PY_MAJOR_VERSION)
|
||||||
#define MINOR STRIFY(PY_MINOR_VERSION)
|
#define MINOR STRIFY(PY_MINOR_VERSION)
|
||||||
#define MAGIC (3190 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
#define MAGIC (3200 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||||
#define TAG "cpython-" MAJOR MINOR;
|
#define TAG "cpython-" MAJOR MINOR;
|
||||||
#define CACHEDIR "__pycache__"
|
#define CACHEDIR "__pycache__"
|
||||||
/* Current magic word and string tag as globals. */
|
/* Current magic word and string tag as globals. */
|
||||||
|
|
Loading…
Reference in New Issue