cpython: 24238e89f938 (original) (raw)
Mercurial > cpython
changeset 73948:24238e89f938
Issue #13577: various kinds of descriptors now have a __qualname__ attribute. Patch by sbt. [#13577]
Antoine Pitrou solipsis@pitrou.net | |
---|---|
date | Mon, 12 Dec 2011 13:47:25 +0100 |
parents | 3ad7d01acbf4 |
children | 021e5bb297d1 |
files | Include/descrobject.h Lib/test/test_descr.py Lib/test/test_sys.py Objects/descrobject.c |
diffstat | 4 files changed, 74 insertions(+), 4 deletions(-)[+] [-] Include/descrobject.h 1 Lib/test/test_descr.py 18 Lib/test/test_sys.py 8 Objects/descrobject.c 51 |
line wrap: on
line diff
--- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -42,6 +42,7 @@ typedef struct { PyObject_HEAD PyTypeObject *d_type; PyObject *d_name;
} PyDescrObject; #define PyDescr_COMMON PyDescrObject d_common
--- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4442,6 +4442,24 @@ order (MRO) for bases """ self.assertIn("can't delete X.doc", str(cm.exception)) self.assertEqual(X.doc, "banana")
- def test_qualname(self):
descriptors = [str.lower, complex.real, float.real, int.__add__][](#l2.8)
types = ['method', 'member', 'getset', 'wrapper'][](#l2.9)
# make sure we have an example of each type of descriptor[](#l2.11)
for d, n in zip(descriptors, types):[](#l2.12)
self.assertEqual(type(d).__name__, n + '_descriptor')[](#l2.13)
for d in descriptors:[](#l2.15)
qualname = d.__objclass__.__qualname__ + '.' + d.__name__[](#l2.16)
self.assertEqual(d.__qualname__, qualname)[](#l2.17)
self.assertEqual(str.lower.__qualname__, 'str.lower')[](#l2.19)
self.assertEqual(complex.real.__qualname__, 'complex.real')[](#l2.20)
self.assertEqual(float.real.__qualname__, 'float.real')[](#l2.21)
self.assertEqual(int.__add__.__qualname__, 'int.__add__')[](#l2.22)
+ + class DictProxyTests(unittest.TestCase): def setUp(self): class C(object):
--- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -670,17 +670,17 @@ class SizeofTest(unittest.TestCase): # complex check(complex(0,1), size(h + '2d')) # method_descriptor (descriptor object)
check(str.lower, size(h + '2PP'))[](#l3.7)
check(str.lower, size(h + '3PP'))[](#l3.8) # classmethod_descriptor (descriptor object)[](#l3.9) # XXX[](#l3.10) # member_descriptor (descriptor object)[](#l3.11) import datetime[](#l3.12)
check(datetime.timedelta.days, size(h + '2PP'))[](#l3.13)
check(datetime.timedelta.days, size(h + '3PP'))[](#l3.14) # getset_descriptor (descriptor object)[](#l3.15) import collections[](#l3.16)
check(collections.defaultdict.default_factory, size(h + '2PP'))[](#l3.17)
check(collections.defaultdict.default_factory, size(h + '3PP'))[](#l3.18) # wrapper_descriptor (descriptor object)[](#l3.19)
check(int.__add__, size(h + '2P2P'))[](#l3.20)
check(int.__add__, size(h + '3P2P'))[](#l3.21) # method-wrapper (descriptor object)[](#l3.22) check({}.__iter__, size(h + '2P'))[](#l3.23) # dict[](#l3.24)
--- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -9,6 +9,7 @@ descr_dealloc(PyDescrObject *descr) _PyObject_GC_UNTRACK(descr); Py_XDECREF(descr->d_type); Py_XDECREF(descr->d_name);
@@ -321,6 +322,44 @@ method_get_doc(PyMethodDescrObject *desc return PyUnicode_FromString(descr->d_method->ml_doc); } +static PyObject * +calculate_qualname(PyDescrObject *descr) +{
- if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
PyErr_SetString(PyExc_TypeError,[](#l4.22)
"<descriptor>.__name__ is not a unicode object");[](#l4.23)
return NULL;[](#l4.24)
- }
- type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
&PyId___qualname__);[](#l4.28)
- if (type_qualname == NULL)
return NULL;[](#l4.30)
- if (!PyUnicode_Check(type_qualname)) {
PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."[](#l4.33)
"__qualname__ is not a unicode object");[](#l4.34)
Py_XDECREF(type_qualname);[](#l4.35)
return NULL;[](#l4.36)
- }
- res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
- Py_DECREF(type_qualname);
- return res;
+} + +static PyObject * +descr_get_qualname(PyDescrObject *descr) +{
- if (descr->d_qualname == NULL)
descr->d_qualname = calculate_qualname(descr);[](#l4.48)
- Py_XINCREF(descr->d_qualname);
- return descr->d_qualname;
+} + static PyMemberDef descr_members[] = { {"objclass", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY}, {"name", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY}, @@ -329,6 +368,7 @@ static PyMemberDef descr_members[] = { static PyGetSetDef method_getset[] = { {"doc", (getter)method_get_doc},
- {"qualname", (getter)descr_get_qualname}, {0} }; @@ -344,6 +384,7 @@ member_get_doc(PyMemberDescrObject *desc static PyGetSetDef member_getset[] = { {"doc", (getter)member_get_doc},
- {"qualname", (getter)descr_get_qualname}, {0} }; @@ -359,6 +400,7 @@ getset_get_doc(PyGetSetDescrObject *desc static PyGetSetDef getset_getset[] = { {"doc", (getter)getset_get_doc},
- {"qualname", (getter)descr_get_qualname}, {0} }; @@ -374,6 +416,7 @@ wrapperdescr_get_doc(PyWrapperDescrObjec static PyGetSetDef wrapperdescr_getset[] = { {"doc", (getter)wrapperdescr_get_doc},
- {"qualname", (getter)descr_get_qualname}, {0} }; @@ -585,6 +628,7 @@ descr_new(PyTypeObject *descrtype, PyTyp Py_DECREF(descr); descr = NULL; }
} return descr; } @@ -987,9 +1031,16 @@ wrapper_doc(wrapperobject *wp) } } +static PyObject * +wrapper_qualname(wrapperobject *wp) +{descr->d_qualname = NULL;[](#l4.92)
- return descr_get_qualname((PyDescrObject *)wp->descr);
+} + static PyGetSetDef wrapper_getsets[] = { {"objclass", (getter)wrapper_objclass}, {"name", (getter)wrapper_name},