diff options
Diffstat (limited to 'Objects/descrobject.c')
-rw-r--r-- | Objects/descrobject.c | 112 |
1 files changed, 104 insertions, 8 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a786bae..ecf372a 100644 --- 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); + Py_XDECREF(descr->d_qualname); PyObject_GC_Del(descr); } @@ -321,6 +322,44 @@ method_get_doc(PyMethodDescrObject *descr, void *closure) return PyUnicode_FromString(descr->d_method->ml_doc); } +static PyObject * +calculate_qualname(PyDescrObject *descr) +{ + PyObject *type_qualname, *res; + _Py_IDENTIFIER(__qualname__); + + if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) { + PyErr_SetString(PyExc_TypeError, + "<descriptor>.__name__ is not a unicode object"); + return NULL; + } + + type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type, + &PyId___qualname__); + if (type_qualname == NULL) + return NULL; + + if (!PyUnicode_Check(type_qualname)) { + PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__." + "__qualname__ is not a unicode object"); + Py_XDECREF(type_qualname); + return NULL; + } + + 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); + 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 *descr, void *closure) static PyGetSetDef member_getset[] = { {"__doc__", (getter)member_get_doc}, + {"__qualname__", (getter)descr_get_qualname}, {0} }; @@ -359,6 +400,7 @@ getset_get_doc(PyGetSetDescrObject *descr, void *closure) static PyGetSetDef getset_getset[] = { {"__doc__", (getter)getset_get_doc}, + {"__qualname__", (getter)descr_get_qualname}, {0} }; @@ -374,6 +416,7 @@ wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure) static PyGetSetDef wrapperdescr_getset[] = { {"__doc__", (getter)wrapperdescr_get_doc}, + {"__qualname__", (getter)descr_get_qualname}, {0} }; @@ -585,6 +628,9 @@ descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) Py_DECREF(descr); descr = NULL; } + else { + descr->d_qualname = NULL; + } } return descr; } @@ -703,34 +749,39 @@ static PyObject * proxy_get(proxyobject *pp, PyObject *args) { PyObject *key, *def = Py_None; + _Py_IDENTIFIER(get); if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) return NULL; - return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def); + return _PyObject_CallMethodId(pp->dict, &PyId_get, "(OO)", key, def); } static PyObject * proxy_keys(proxyobject *pp) { - return PyObject_CallMethod(pp->dict, "keys", NULL); + _Py_IDENTIFIER(keys); + return _PyObject_CallMethodId(pp->dict, &PyId_keys, NULL); } static PyObject * proxy_values(proxyobject *pp) { - return PyObject_CallMethod(pp->dict, "values", NULL); + _Py_IDENTIFIER(values); + return _PyObject_CallMethodId(pp->dict, &PyId_values, NULL); } static PyObject * proxy_items(proxyobject *pp) { - return PyObject_CallMethod(pp->dict, "items", NULL); + _Py_IDENTIFIER(items); + return _PyObject_CallMethodId(pp->dict, &PyId_items, NULL); } static PyObject * proxy_copy(proxyobject *pp) { - return PyObject_CallMethod(pp->dict, "copy", NULL); + _Py_IDENTIFIER(copy); + return _PyObject_CallMethodId(pp->dict, &PyId_copy, NULL); } static PyMethodDef proxy_methods[] = { @@ -982,9 +1033,16 @@ wrapper_doc(wrapperobject *wp) } } +static PyObject * +wrapper_qualname(wrapperobject *wp) +{ + return descr_get_qualname((PyDescrObject *)wp->descr); +} + static PyGetSetDef wrapper_getsets[] = { {"__objclass__", (getter)wrapper_objclass}, {"__name__", (getter)wrapper_name}, + {"__qualname__", (getter)wrapper_qualname}, {"__doc__", (getter)wrapper_doc}, {0} }; @@ -1294,7 +1352,8 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds) /* if no docstring given and the getter has one, use that one */ if ((doc == NULL || doc == Py_None) && get != NULL) { - PyObject *get_doc = PyObject_GetAttrString(get, "__doc__"); + _Py_IDENTIFIER(__doc__); + PyObject *get_doc = _PyObject_GetAttrId(get, &PyId___doc__); if (get_doc) { if (Py_TYPE(self) == &PyProperty_Type) { Py_XDECREF(prop->prop_doc); @@ -1305,7 +1364,7 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds) in dict of the subclass instance instead, otherwise it gets shadowed by __doc__ in the class's dict. */ - int err = PyObject_SetAttrString(self, "__doc__", get_doc); + int err = _PyObject_SetAttrId(self, &PyId___doc__, get_doc); Py_DECREF(get_doc); if (err < 0) return -1; @@ -1323,6 +1382,43 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds) return 0; } +static PyObject * +property_get___isabstractmethod__(propertyobject *prop, void *closure) +{ + int res = _PyObject_IsAbstract(prop->prop_get); + if (res == -1) { + return NULL; + } + else if (res) { + Py_RETURN_TRUE; + } + + res = _PyObject_IsAbstract(prop->prop_set); + if (res == -1) { + return NULL; + } + else if (res) { + Py_RETURN_TRUE; + } + + res = _PyObject_IsAbstract(prop->prop_del); + if (res == -1) { + return NULL; + } + else if (res) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +static PyGetSetDef property_getsetlist[] = { + {"__isabstractmethod__", + (getter)property_get___isabstractmethod__, NULL, + NULL, + NULL}, + {NULL} /* Sentinel */ +}; + PyDoc_STRVAR(property_doc, "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n" "\n" @@ -1388,7 +1484,7 @@ PyTypeObject PyProperty_Type = { 0, /* tp_iternext */ property_methods, /* tp_methods */ property_members, /* tp_members */ - 0, /* tp_getset */ + property_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ property_descr_get, /* tp_descr_get */ |