From 949c3f094c436fea35325980527d63d0d9eabd21 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 25 Nov 2011 18:56:07 +0100 Subject: PEP 3155 / issue #13448: Qualified name for classes and functions. --- Objects/funcobject.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'Objects/funcobject.c') diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 45f9f57578..2839a247ef 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; @@ -61,6 +66,12 @@ PyFunction_New(PyObject *code, PyObject *globals) return (PyObject *)op; } +PyObject * +PyFunction_New(PyObject *code, PyObject *globals) +{ + return PyFunction_NewWithQualName(code, globals, NULL); +} + PyObject * PyFunction_GetCode(PyObject *op) { @@ -333,6 +344,32 @@ func_set_name(PyFunctionObject *op, PyObject *value) 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 * func_get_defaults(PyFunctionObject *op) { @@ -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("", - 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; } -- cgit v1.2.1 From b964fcdb84d3a8df2ecb91ba59140d30d72c62a6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 15 Dec 2011 15:34:02 -0500 Subject: improve abstract property support (closes #11610) Thanks to Darren Dale for patch. --- Objects/funcobject.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'Objects/funcobject.c') diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 2839a247ef..b93f340bf6 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -814,6 +814,27 @@ static PyMemberDef cm_memberlist[] = { {NULL} /* Sentinel */ }; +static PyObject * +cm_get___isabstractmethod__(classmethod *cm, void *closure) +{ + int res = _PyObject_IsAbstract(cm->cm_callable); + if (res == -1) { + return NULL; + } + else if (res) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +static PyGetSetDef cm_getsetlist[] = { + {"__isabstractmethod__", + (getter)cm_get___isabstractmethod__, NULL, + NULL, + NULL}, + {NULL} /* Sentinel */ +}; + PyDoc_STRVAR(classmethod_doc, "classmethod(function) -> method\n\ \n\ @@ -865,7 +886,7 @@ PyTypeObject PyClassMethod_Type = { 0, /* tp_iternext */ 0, /* tp_methods */ cm_memberlist, /* tp_members */ - 0, /* tp_getset */ + cm_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ cm_descr_get, /* tp_descr_get */ @@ -969,6 +990,27 @@ static PyMemberDef sm_memberlist[] = { {NULL} /* Sentinel */ }; +static PyObject * +sm_get___isabstractmethod__(staticmethod *sm, void *closure) +{ + int res = _PyObject_IsAbstract(sm->sm_callable); + if (res == -1) { + return NULL; + } + else if (res) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +static PyGetSetDef sm_getsetlist[] = { + {"__isabstractmethod__", + (getter)sm_get___isabstractmethod__, NULL, + NULL, + NULL}, + {NULL} /* Sentinel */ +}; + PyDoc_STRVAR(staticmethod_doc, "staticmethod(function) -> method\n\ \n\ @@ -1017,7 +1059,7 @@ PyTypeObject PyStaticMethod_Type = { 0, /* tp_iternext */ 0, /* tp_methods */ sm_memberlist, /* tp_members */ - 0, /* tp_getset */ + sm_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ sm_descr_get, /* tp_descr_get */ -- cgit v1.2.1 From c01affa89784e9b9af2ce185fd307df1cb108462 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Feb 2012 01:10:25 -0500 Subject: allow arbitrary attributes on classmethod and staticmethod (closes #14051) --- Objects/funcobject.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'Objects/funcobject.c') diff --git a/Objects/funcobject.c b/Objects/funcobject.c index b93f340bf6..5db86a6721 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -754,6 +754,7 @@ PyTypeObject PyFunction_Type = { typedef struct { PyObject_HEAD PyObject *cm_callable; + PyObject *cm_dict; } classmethod; static void @@ -761,6 +762,7 @@ cm_dealloc(classmethod *cm) { _PyObject_GC_UNTRACK((PyObject *)cm); Py_XDECREF(cm->cm_callable); + Py_XDECREF(cm->cm_dict); Py_TYPE(cm)->tp_free((PyObject *)cm); } @@ -768,6 +770,7 @@ static int cm_traverse(classmethod *cm, visitproc visit, void *arg) { Py_VISIT(cm->cm_callable); + Py_VISIT(cm->cm_dict); return 0; } @@ -775,6 +778,7 @@ static int cm_clear(classmethod *cm) { Py_CLEAR(cm->cm_callable); + Py_CLEAR(cm->cm_dict); return 0; } @@ -827,11 +831,19 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure) Py_RETURN_FALSE; } +static PyObject * +cm_get___dict__(classmethod *cm, void *closure) +{ + Py_INCREF(cm->cm_dict); + return cm->cm_dict; +} + static PyGetSetDef cm_getsetlist[] = { {"__isabstractmethod__", (getter)cm_get___isabstractmethod__, NULL, NULL, NULL}, + {"__dict__", (getter)cm_get___dict__, NULL, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -891,7 +903,7 @@ PyTypeObject PyClassMethod_Type = { 0, /* tp_dict */ cm_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(classmethod, cm_dict), /* tp_dictoffset */ cm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ @@ -930,6 +942,7 @@ PyClassMethod_New(PyObject *callable) typedef struct { PyObject_HEAD PyObject *sm_callable; + PyObject *sm_dict; } staticmethod; static void @@ -937,6 +950,7 @@ sm_dealloc(staticmethod *sm) { _PyObject_GC_UNTRACK((PyObject *)sm); Py_XDECREF(sm->sm_callable); + Py_XDECREF(sm->sm_dict); Py_TYPE(sm)->tp_free((PyObject *)sm); } @@ -944,6 +958,7 @@ static int sm_traverse(staticmethod *sm, visitproc visit, void *arg) { Py_VISIT(sm->sm_callable); + Py_VISIT(sm->sm_dict); return 0; } @@ -952,6 +967,7 @@ sm_clear(staticmethod *sm) { Py_XDECREF(sm->sm_callable); sm->sm_callable = NULL; + Py_CLEAR(sm->sm_dict); return 0; } @@ -1003,11 +1019,19 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure) Py_RETURN_FALSE; } +static PyObject * +sm_get___dict__(staticmethod *sm, void *closure) +{ + Py_INCREF(sm->sm_dict); + return sm->sm_dict; +} + static PyGetSetDef sm_getsetlist[] = { {"__isabstractmethod__", (getter)sm_get___isabstractmethod__, NULL, NULL, NULL}, + {"__dict__", (getter)sm_get___dict__, NULL, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -1046,7 +1070,7 @@ PyTypeObject PyStaticMethod_Type = { 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, @@ -1064,7 +1088,7 @@ PyTypeObject PyStaticMethod_Type = { 0, /* tp_dict */ sm_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(staticmethod, sm_dict), /* tp_dictoffset */ sm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ -- cgit v1.2.1 From 2092911b39bff0b2e87247838a6359a3ea4839d5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Feb 2012 01:16:13 -0500 Subject: use defaults --- Objects/funcobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Objects/funcobject.c') diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 6cbf297c58..089356b40f 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -707,8 +707,8 @@ PyTypeObject PyFunction_Type = { 0, /* tp_hash */ function_call, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ func_doc, /* tp_doc */ @@ -885,7 +885,7 @@ PyTypeObject PyClassMethod_Type = { 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, -- cgit v1.2.1 From 558155dc6fe46a5408e21db56251b3e0b11e72a6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Feb 2012 10:17:30 -0500 Subject: initialize __dict__ if needed --- Objects/funcobject.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'Objects/funcobject.c') diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 089356b40f..6dd91b8ca4 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -832,10 +832,13 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure) } static PyObject * -cm_get___dict__(classmethod *cm, void *closure) +cm_get___dict__(PyObject *cm, void *closure) { - Py_INCREF(cm->cm_dict); - return cm->cm_dict; + PyObject **dictptr = _PyObject_GetDictPtr(cm); + if (*dictptr == NULL) + *dictptr = PyDict_New(); + Py_XINCREF(*dictptr); + return *dictptr; } static PyGetSetDef cm_getsetlist[] = { @@ -1018,10 +1021,13 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure) } static PyObject * -sm_get___dict__(staticmethod *sm, void *closure) +sm_get___dict__(PyObject *sm, void *closure) { - Py_INCREF(sm->sm_dict); - return sm->sm_dict; + PyObject **dictptr = _PyObject_GetDictPtr(sm); + if (*dictptr == NULL) + *dictptr = PyDict_New(); + Py_XINCREF(*dictptr); + return *dictptr; } static PyGetSetDef sm_getsetlist[] = { -- cgit v1.2.1 From bcbfcc25135e1e7d0ab0ec834ffabc887e30fcf7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Feb 2012 20:02:57 -0500 Subject: use new generic __dict__ descriptor implementations --- Objects/funcobject.c | 62 +++------------------------------------------------- 1 file changed, 3 insertions(+), 59 deletions(-) (limited to 'Objects/funcobject.c') diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 6dd91b8ca4..49415b95e1 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -244,42 +244,6 @@ static PyMemberDef func_memberlist[] = { {NULL} /* Sentinel */ }; -static PyObject * -func_get_dict(PyFunctionObject *op) -{ - if (op->func_dict == NULL) { - op->func_dict = PyDict_New(); - if (op->func_dict == NULL) - return NULL; - } - Py_INCREF(op->func_dict); - return op->func_dict; -} - -static int -func_set_dict(PyFunctionObject *op, PyObject *value) -{ - PyObject *tmp; - - /* It is illegal to del f.func_dict */ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, - "function's dictionary may not be deleted"); - return -1; - } - /* Can only set func_dict to a dictionary */ - if (!PyDict_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "setting function's dictionary to a non-dict"); - return -1; - } - tmp = op->func_dict; - Py_INCREF(value); - op->func_dict = value; - Py_XDECREF(tmp); - return 0; -} - static PyObject * func_get_code(PyFunctionObject *op) { @@ -476,7 +440,7 @@ static PyGetSetDef func_getsetlist[] = { (setter)func_set_kwdefaults}, {"__annotations__", (getter)func_get_annotations, (setter)func_set_annotations}, - {"__dict__", (getter)func_get_dict, (setter)func_set_dict}, + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, {"__name__", (getter)func_get_name, (setter)func_set_name}, {"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname}, {NULL} /* Sentinel */ @@ -831,22 +795,12 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure) Py_RETURN_FALSE; } -static PyObject * -cm_get___dict__(PyObject *cm, void *closure) -{ - PyObject **dictptr = _PyObject_GetDictPtr(cm); - if (*dictptr == NULL) - *dictptr = PyDict_New(); - Py_XINCREF(*dictptr); - return *dictptr; -} - static PyGetSetDef cm_getsetlist[] = { {"__isabstractmethod__", (getter)cm_get___isabstractmethod__, NULL, NULL, NULL}, - {"__dict__", (getter)cm_get___dict__, NULL, NULL, NULL}, + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -1020,22 +974,12 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure) Py_RETURN_FALSE; } -static PyObject * -sm_get___dict__(PyObject *sm, void *closure) -{ - PyObject **dictptr = _PyObject_GetDictPtr(sm); - if (*dictptr == NULL) - *dictptr = PyDict_New(); - Py_XINCREF(*dictptr); - return *dictptr; -} - static PyGetSetDef sm_getsetlist[] = { {"__isabstractmethod__", (getter)sm_get___isabstractmethod__, NULL, NULL, NULL}, - {"__dict__", (getter)sm_get___dict__, NULL, NULL, NULL}, + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL}, {NULL} /* Sentinel */ }; -- cgit v1.2.1