Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(147887)

Delta Between Two Patch Sets: Objects/descrobject.c

Issue 11610: Improving property to accept abstract methods
Left Patch Set: Created 8 years, 5 months ago
Right Patch Set: Created 8 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Misc/ACKS ('k') | Objects/funcobject.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* Descriptors -- a new, flexible way to describe attributes */ 1 /* Descriptors -- a new, flexible way to describe attributes */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h" /* Why is this not included in Python.h? */ 4 #include "structmember.h" /* Why is this not included in Python.h? */
5 5
6 static void 6 static void
7 descr_dealloc(PyDescrObject *descr) 7 descr_dealloc(PyDescrObject *descr)
8 { 8 {
9 _PyObject_GC_UNTRACK(descr); 9 _PyObject_GC_UNTRACK(descr);
10 Py_XDECREF(descr->d_type); 10 Py_XDECREF(descr->d_type);
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 0, /* sq_ass_slice */ 696 0, /* sq_ass_slice */
697 (objobjproc)proxy_contains, /* sq_contains */ 697 (objobjproc)proxy_contains, /* sq_contains */
698 0, /* sq_inplace_concat */ 698 0, /* sq_inplace_concat */
699 0, /* sq_inplace_repeat */ 699 0, /* sq_inplace_repeat */
700 }; 700 };
701 701
702 static PyObject * 702 static PyObject *
703 proxy_get(proxyobject *pp, PyObject *args) 703 proxy_get(proxyobject *pp, PyObject *args)
704 { 704 {
705 PyObject *key, *def = Py_None; 705 PyObject *key, *def = Py_None;
706 _Py_IDENTIFIER(get);
706 707
707 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) 708 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
708 return NULL; 709 return NULL;
709 return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def); 710 return _PyObject_CallMethodId(pp->dict, &PyId_get, "(OO)", key, def);
710 } 711 }
711 712
712 static PyObject * 713 static PyObject *
713 proxy_keys(proxyobject *pp) 714 proxy_keys(proxyobject *pp)
714 { 715 {
715 return PyObject_CallMethod(pp->dict, "keys", NULL); 716 _Py_IDENTIFIER(keys);
717 return _PyObject_CallMethodId(pp->dict, &PyId_keys, NULL);
716 } 718 }
717 719
718 static PyObject * 720 static PyObject *
719 proxy_values(proxyobject *pp) 721 proxy_values(proxyobject *pp)
720 { 722 {
721 return PyObject_CallMethod(pp->dict, "values", NULL); 723 _Py_IDENTIFIER(values);
724 return _PyObject_CallMethodId(pp->dict, &PyId_values, NULL);
722 } 725 }
723 726
724 static PyObject * 727 static PyObject *
725 proxy_items(proxyobject *pp) 728 proxy_items(proxyobject *pp)
726 { 729 {
727 return PyObject_CallMethod(pp->dict, "items", NULL); 730 _Py_IDENTIFIER(items);
731 return _PyObject_CallMethodId(pp->dict, &PyId_items, NULL);
728 } 732 }
729 733
730 static PyObject * 734 static PyObject *
731 proxy_copy(proxyobject *pp) 735 proxy_copy(proxyobject *pp)
732 { 736 {
733 return PyObject_CallMethod(pp->dict, "copy", NULL); 737 _Py_IDENTIFIER(copy);
738 return _PyObject_CallMethodId(pp->dict, &PyId_copy, NULL);
734 } 739 }
735 740
736 static PyMethodDef proxy_methods[] = { 741 static PyMethodDef proxy_methods[] = {
737 {"get", (PyCFunction)proxy_get, METH_VARARGS, 742 {"get", (PyCFunction)proxy_get, METH_VARARGS,
738 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." 743 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
739 " d defaults to None.")}, 744 " d defaults to None.")},
740 {"keys", (PyCFunction)proxy_keys, METH_NOARGS, 745 {"keys", (PyCFunction)proxy_keys, METH_NOARGS,
741 PyDoc_STR("D.keys() -> list of D's keys")}, 746 PyDoc_STR("D.keys() -> list of D's keys")},
742 {"values", (PyCFunction)proxy_values, METH_NOARGS, 747 {"values", (PyCFunction)proxy_values, METH_NOARGS,
743 PyDoc_STR("D.values() -> list of D's values")}, 748 PyDoc_STR("D.values() -> list of D's values")},
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 } 844 }
840 return (PyObject *)pp; 845 return (PyObject *)pp;
841 } 846 }
842 847
843 848
844 /* --- Wrapper object for "slot" methods --- */ 849 /* --- Wrapper object for "slot" methods --- */
845 850
846 /* This has no reason to be in this file except that adding new files is a 851 /* This has no reason to be in this file except that adding new files is a
847 bit of a pain */ 852 bit of a pain */
848 853
849 /* forward */
850 static PyTypeObject wrappertype;
851
852 typedef struct { 854 typedef struct {
853 PyObject_HEAD 855 PyObject_HEAD
854 PyWrapperDescrObject *descr; 856 PyWrapperDescrObject *descr;
855 PyObject *self; 857 PyObject *self;
856 } wrapperobject; 858 } wrapperobject;
857 859
858 #define Wrapper_Check(v) (Py_TYPE(v) == &wrappertype) 860 #define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
859 861
860 static void 862 static void
861 wrapper_dealloc(wrapperobject *wp) 863 wrapper_dealloc(wrapperobject *wp)
862 { 864 {
863 PyObject_GC_UnTrack(wp); 865 PyObject_GC_UnTrack(wp);
864 Py_TRASHCAN_SAFE_BEGIN(wp) 866 Py_TRASHCAN_SAFE_BEGIN(wp)
865 Py_XDECREF(wp->descr); 867 Py_XDECREF(wp->descr);
866 Py_XDECREF(wp->self); 868 Py_XDECREF(wp->self);
867 PyObject_GC_Del(wp); 869 PyObject_GC_Del(wp);
868 Py_TRASHCAN_SAFE_END(wp) 870 Py_TRASHCAN_SAFE_END(wp)
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 1016
1015 static int 1017 static int
1016 wrapper_traverse(PyObject *self, visitproc visit, void *arg) 1018 wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1017 { 1019 {
1018 wrapperobject *wp = (wrapperobject *)self; 1020 wrapperobject *wp = (wrapperobject *)self;
1019 Py_VISIT(wp->descr); 1021 Py_VISIT(wp->descr);
1020 Py_VISIT(wp->self); 1022 Py_VISIT(wp->self);
1021 return 0; 1023 return 0;
1022 } 1024 }
1023 1025
1024 static PyTypeObject wrappertype = { 1026 PyTypeObject _PyMethodWrapper_Type = {
1025 PyVarObject_HEAD_INIT(&PyType_Type, 0) 1027 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1026 "method-wrapper", /* tp_name */ 1028 "method-wrapper", /* tp_name */
1027 sizeof(wrapperobject), /* tp_basicsize */ 1029 sizeof(wrapperobject), /* tp_basicsize */
1028 0, /* tp_itemsize */ 1030 0, /* tp_itemsize */
1029 /* methods */ 1031 /* methods */
1030 (destructor)wrapper_dealloc, /* tp_dealloc */ 1032 (destructor)wrapper_dealloc, /* tp_dealloc */
1031 0, /* tp_print */ 1033 0, /* tp_print */
1032 0, /* tp_getattr */ 1034 0, /* tp_getattr */
1033 0, /* tp_setattr */ 1035 0, /* tp_setattr */
1034 0, /* tp_reserved */ 1036 0, /* tp_reserved */
(...skipping 28 matching lines...) Expand all
1063 PyWrapper_New(PyObject *d, PyObject *self) 1065 PyWrapper_New(PyObject *d, PyObject *self)
1064 { 1066 {
1065 wrapperobject *wp; 1067 wrapperobject *wp;
1066 PyWrapperDescrObject *descr; 1068 PyWrapperDescrObject *descr;
1067 1069
1068 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); 1070 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1069 descr = (PyWrapperDescrObject *)d; 1071 descr = (PyWrapperDescrObject *)d;
1070 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), 1072 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
1071 (PyObject *)PyDescr_TYPE(descr))); 1073 (PyObject *)PyDescr_TYPE(descr)));
1072 1074
1073 wp = PyObject_GC_New(wrapperobject, &wrappertype); 1075 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
1074 if (wp != NULL) { 1076 if (wp != NULL) {
1075 Py_INCREF(descr); 1077 Py_INCREF(descr);
1076 wp->descr = descr; 1078 wp->descr = descr;
1077 Py_INCREF(self); 1079 Py_INCREF(self);
1078 wp->self = self; 1080 wp->self = self;
1079 _PyObject_GC_TRACK(wp); 1081 _PyObject_GC_TRACK(wp);
1080 } 1082 }
1081 return (PyObject *)wp; 1083 return (PyObject *)wp;
1082 } 1084 }
1083 1085
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 Py_XINCREF(doc); 1292 Py_XINCREF(doc);
1291 1293
1292 prop->prop_get = get; 1294 prop->prop_get = get;
1293 prop->prop_set = set; 1295 prop->prop_set = set;
1294 prop->prop_del = del; 1296 prop->prop_del = del;
1295 prop->prop_doc = doc; 1297 prop->prop_doc = doc;
1296 prop->getter_doc = 0; 1298 prop->getter_doc = 0;
1297 1299
1298 /* if no docstring given and the getter has one, use that one */ 1300 /* if no docstring given and the getter has one, use that one */
1299 if ((doc == NULL || doc == Py_None) && get != NULL) { 1301 if ((doc == NULL || doc == Py_None) && get != NULL) {
1300 PyObject *get_doc = PyObject_GetAttrString(get, "__doc__"); 1302 _Py_IDENTIFIER(__doc__);
1303 PyObject *get_doc = _PyObject_GetAttrId(get, &PyId___doc__);
1301 if (get_doc) { 1304 if (get_doc) {
1302 if (Py_TYPE(self) == &PyProperty_Type) { 1305 if (Py_TYPE(self) == &PyProperty_Type) {
1303 Py_XDECREF(prop->prop_doc); 1306 Py_XDECREF(prop->prop_doc);
1304 prop->prop_doc = get_doc; 1307 prop->prop_doc = get_doc;
1305 } 1308 }
1306 else { 1309 else {
1307 /* If this is a property subclass, put __doc__ 1310 /* If this is a property subclass, put __doc__
1308 in dict of the subclass instance instead, 1311 in dict of the subclass instance instead,
1309 otherwise it gets shadowed by __doc__ in the 1312 otherwise it gets shadowed by __doc__ in the
1310 class's dict. */ 1313 class's dict. */
1311 int err = PyObject_SetAttrString(self, "__doc__", get_doc); 1314 int err = _PyObject_SetAttrId(self, &PyId___doc__, get_doc);
1312 Py_DECREF(get_doc); 1315 Py_DECREF(get_doc);
1313 if (err < 0) 1316 if (err < 0)
1314 return -1; 1317 return -1;
1315 } 1318 }
1316 prop->getter_doc = 1; 1319 prop->getter_doc = 1;
1317 } 1320 }
1318 else if (PyErr_ExceptionMatches(PyExc_Exception)) { 1321 else if (PyErr_ExceptionMatches(PyExc_Exception)) {
1319 PyErr_Clear(); 1322 PyErr_Clear();
1320 } 1323 }
1321 else { 1324 else {
1322 return -1; 1325 return -1;
1323 } 1326 }
1324 } 1327 }
1325 1328
1326 return 0; 1329 return 0;
1327 } 1330 }
1328 1331
1329 static PyObject * 1332 static PyObject *
1330 property_check_isabstract(propertyobject *self, PyObject *obj) 1333 property_get___isabstractmethod__(propertyobject *prop, void *closure)
1331 { 1334 {
1332 if (obj == NULL) 1335 int res = _PyObject_IsAbstract(prop->prop_get);
1333 return 0; 1336 if (res == -1) {
1334 1337 return NULL;
1335 PyObject* isabstract = PyObject_GetAttrString(obj, "__isabstractmethod__"); 1338 }
1336 if (isabstract == NULL) { 1339 else if (res) {
1337 PyErr_Clear();
1338 return 0;
1339 }
1340 Py_DECREF(isabstract);
durban 2011/06/20 22:40:40 It's probably not a good idea to call PyObject_IsT
1341 return PyObject_IsTrue(isabstract);
durban 2011/06/20 22:40:40 Also, PyObject_IsTrue returns an int. Its return v
dsdale24 2011/07/22 16:01:01 I don't understand the significance of this observ
durban 2011/07/23 12:47:22 You're returning an int from a function with a ret
1342 }
1343
1344 static PyObject *
1345 property_get__isabstractmethod__(PyObject *self, void *closure)
1346 {
1347 propertyobject *prop = (propertyobject *)self;
1348
1349 if (property_check_isabstract(prop, prop->prop_get))
1350 Py_RETURN_TRUE; 1340 Py_RETURN_TRUE;
1351 if (property_check_isabstract(prop, prop->prop_set)) 1341 }
1342
1343 res = _PyObject_IsAbstract(prop->prop_set);
1344 if (res == -1) {
1345 return NULL;
1346 }
1347 else if (res) {
1352 Py_RETURN_TRUE; 1348 Py_RETURN_TRUE;
1353 if (property_check_isabstract(prop, prop->prop_del)) { 1349 }
1350
1351 res = _PyObject_IsAbstract(prop->prop_del);
1352 if (res == -1) {
1353 return NULL;
1354 }
1355 else if (res) {
1354 Py_RETURN_TRUE; 1356 Py_RETURN_TRUE;
1355 } 1357 }
1356 else { 1358 Py_RETURN_FALSE;
1357 Py_RETURN_FALSE;
1358 }
1359 } 1359 }
1360 1360
1361 static PyGetSetDef property_getsetlist[] = { 1361 static PyGetSetDef property_getsetlist[] = {
1362 {"__isabstractmethod__", 1362 {"__isabstractmethod__",
1363 (getter)property_get__isabstractmethod__, NULL, 1363 (getter)property_get___isabstractmethod__, NULL,
1364 NULL, 1364 NULL,
1365 NULL}, 1365 NULL},
1366 {NULL} /* Sentinel */ 1366 {NULL} /* Sentinel */
1367 }; 1367 };
1368 1368
1369 PyDoc_STRVAR(property_doc, 1369 PyDoc_STRVAR(property_doc,
1370 "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n" 1370 "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"
1371 "\n" 1371 "\n"
1372 "fget is a function to be used for getting an attribute value, and likewise\n" 1372 "fget is a function to be used for getting an attribute value, and likewise\n"
1373 "fset is a function for setting, and fdel a function for del'ing, an\n" 1373 "fset is a function for setting, and fdel a function for del'ing, an\n"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 0, /* tp_base */ 1435 0, /* tp_base */
1436 0, /* tp_dict */ 1436 0, /* tp_dict */
1437 property_descr_get, /* tp_descr_get */ 1437 property_descr_get, /* tp_descr_get */
1438 property_descr_set, /* tp_descr_set */ 1438 property_descr_set, /* tp_descr_set */
1439 0, /* tp_dictoffset */ 1439 0, /* tp_dictoffset */
1440 property_init, /* tp_init */ 1440 property_init, /* tp_init */
1441 PyType_GenericAlloc, /* tp_alloc */ 1441 PyType_GenericAlloc, /* tp_alloc */
1442 PyType_GenericNew, /* tp_new */ 1442 PyType_GenericNew, /* tp_new */
1443 PyObject_GC_Del, /* tp_free */ 1443 PyObject_GC_Del, /* tp_free */
1444 }; 1444 };
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+