summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-11-25 17:56:07 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-11-25 17:56:07 (GMT)
commit86a36b500a7f7581194382ce4df914e4bb487873 (patch)
tree0d83f90f9a14d40d3559ae188c203e9c8941c6db /Objects
parent0e86a5842d0fadff37c299e8a1c03535c6727b19 (diff)
downloadcpython-86a36b500a7f7581194382ce4df914e4bb487873.zip
cpython-86a36b500a7f7581194382ce4df914e4bb487873.tar.gz
cpython-86a36b500a7f7581194382ce4df914e4bb487873.tar.bz2
PEP 3155 / issue #13448: Qualified name for classes and functions.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/funcobject.c44
-rw-r--r--Objects/typeobject.c56
2 files changed, 95 insertions, 5 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 45f9f57..2839a24 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -6,7 +6,7 @@
#include "structmember.h"
PyObject *
-PyFunction_New(PyObject *code, PyObject *globals)
+PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)
{
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
&PyFunction_Type);
@@ -54,6 +54,11 @@ PyFunction_New(PyObject *code, PyObject *globals)
Py_INCREF(module);
op->func_module = module;
}
+ if (qualname)
+ op->func_qualname = qualname;
+ else
+ op->func_qualname = op->func_name;
+ Py_INCREF(op->func_qualname);
}
else
return NULL;
@@ -62,6 +67,12 @@ PyFunction_New(PyObject *code, PyObject *globals)
}
PyObject *
+PyFunction_New(PyObject *code, PyObject *globals)
+{
+ return PyFunction_NewWithQualName(code, globals, NULL);
+}
+
+PyObject *
PyFunction_GetCode(PyObject *op)
{
if (!PyFunction_Check(op)) {
@@ -334,6 +345,32 @@ func_set_name(PyFunctionObject *op, PyObject *value)
}
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 *
func_get_defaults(PyFunctionObject *op)
{
if (op->func_defaults == NULL) {
@@ -441,6 +478,7 @@ static PyGetSetDef func_getsetlist[] = {
(setter)func_set_annotations},
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
{"__name__", (getter)func_get_name, (setter)func_set_name},
+ {"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname},
{NULL} /* Sentinel */
};
@@ -561,6 +599,7 @@ func_dealloc(PyFunctionObject *op)
Py_XDECREF(op->func_dict);
Py_XDECREF(op->func_closure);
Py_XDECREF(op->func_annotations);
+ Py_XDECREF(op->func_qualname);
PyObject_GC_Del(op);
}
@@ -568,7 +607,7 @@ static PyObject*
func_repr(PyFunctionObject *op)
{
return PyUnicode_FromFormat("<function %U at %p>",
- op->func_name, op);
+ op->func_qualname, op);
}
static int
@@ -584,6 +623,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_qualname);
return 0;
}
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index d53ae93..010120a 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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
type_set_name(PyTypeObject *type, PyObject *value, void *context)
{
@@ -286,6 +299,25 @@ type_set_name(PyTypeObject *type, PyObject *value, void *context)
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 *
type_module(PyTypeObject *type, void *context)
{
@@ -631,6 +663,7 @@ type___subclasscheck__(PyObject *type, PyObject *inst)
static PyGetSetDef type_getsets[] = {
{"__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},
{"__module__", (getter)type_module, (setter)type_set_module, NULL},
{"__abstractmethods__", (getter)type_abstractmethods,
@@ -652,7 +685,7 @@ type_repr(PyTypeObject *type)
Py_DECREF(mod);
mod = NULL;
}
- name = type_name(type, NULL);
+ name = type_qualname(type, NULL);
if (name == NULL)
return NULL;
@@ -1955,7 +1988,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{
PyObject *name, *bases, *dict;
static char *kwlist[] = {"name", "bases", "dict", 0};
- PyObject *slots, *tmp, *newslots;
+ PyObject *qualname, *slots, *tmp, *newslots;
PyTypeObject *type, *base, *tmptype, *winner;
PyHeapTypeObject *et;
PyMemberDef *mp;
@@ -2032,6 +2065,18 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
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 */
slots = PyDict_GetItemString(dict, "__slots__");
nslots = 0;
@@ -2185,7 +2230,9 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
/* Keep name and slots alive in the extended type object */
et = (PyHeapTypeObject *)type;
Py_INCREF(name);
+ Py_INCREF(qualname);
et->ht_name = name;
+ et->ht_qualname = qualname;
et->ht_slots = slots;
/* Initialize tp_flags */
@@ -2369,6 +2416,8 @@ PyObject* PyType_FromSpec(PyType_Spec *spec)
res->ht_name = PyUnicode_FromString(spec->name);
if (!res->ht_name)
goto fail;
+ res->ht_qualname = res->ht_name;
+ Py_INCREF(res->ht_qualname);
res->ht_type.tp_name = _PyUnicode_AsString(res->ht_name);
if (!res->ht_type.tp_name)
goto fail;
@@ -2568,6 +2617,7 @@ type_dealloc(PyTypeObject *type)
*/
PyObject_Free((char *)type->tp_doc);
Py_XDECREF(et->ht_name);
+ Py_XDECREF(et->ht_qualname);
Py_XDECREF(et->ht_slots);
Py_TYPE(type)->tp_free((PyObject *)type);
}
@@ -2983,7 +3033,7 @@ object_repr(PyObject *self)
Py_DECREF(mod);
mod = NULL;
}
- name = type_name(type, NULL);
+ name = type_qualname(type, NULL);
if (name == NULL)
return NULL;
if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins"))