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

Delta Between Two Patch Sets: Objects/descrobject.c

Issue 11610: Improving property to accept abstract methods
Left Patch Set: Created 8 years, 8 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 argc = PyTuple_GET_SIZE(args); 219 argc = PyTuple_GET_SIZE(args);
220 if (argc < 1) { 220 if (argc < 1) {
221 PyErr_Format(PyExc_TypeError, 221 PyErr_Format(PyExc_TypeError,
222 "descriptor '%V' of '%.100s' " 222 "descriptor '%V' of '%.100s' "
223 "object needs an argument", 223 "object needs an argument",
224 descr_name((PyDescrObject *)descr), "?", 224 descr_name((PyDescrObject *)descr), "?",
225 PyDescr_TYPE(descr)->tp_name); 225 PyDescr_TYPE(descr)->tp_name);
226 return NULL; 226 return NULL;
227 } 227 }
228 self = PyTuple_GET_ITEM(args, 0); 228 self = PyTuple_GET_ITEM(args, 0);
229 if (!PyObject_IsInstance(self, (PyObject *)PyDescr_TYPE(descr))) { 229 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
230 (PyObject *)PyDescr_TYPE(descr))) {
230 PyErr_Format(PyExc_TypeError, 231 PyErr_Format(PyExc_TypeError,
231 "descriptor '%V' " 232 "descriptor '%V' "
232 "requires a '%.100s' object " 233 "requires a '%.100s' object "
233 "but received a '%.100s'", 234 "but received a '%.100s'",
234 descr_name((PyDescrObject *)descr), "?", 235 descr_name((PyDescrObject *)descr), "?",
235 PyDescr_TYPE(descr)->tp_name, 236 PyDescr_TYPE(descr)->tp_name,
236 self->ob_type->tp_name); 237 self->ob_type->tp_name);
237 return NULL; 238 return NULL;
238 } 239 }
239 240
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 argc = PyTuple_GET_SIZE(args); 278 argc = PyTuple_GET_SIZE(args);
278 if (argc < 1) { 279 if (argc < 1) {
279 PyErr_Format(PyExc_TypeError, 280 PyErr_Format(PyExc_TypeError,
280 "descriptor '%V' of '%.100s' " 281 "descriptor '%V' of '%.100s' "
281 "object needs an argument", 282 "object needs an argument",
282 descr_name((PyDescrObject *)descr), "?", 283 descr_name((PyDescrObject *)descr), "?",
283 PyDescr_TYPE(descr)->tp_name); 284 PyDescr_TYPE(descr)->tp_name);
284 return NULL; 285 return NULL;
285 } 286 }
286 self = PyTuple_GET_ITEM(args, 0); 287 self = PyTuple_GET_ITEM(args, 0);
287 if (!PyObject_IsInstance(self, (PyObject *)PyDescr_TYPE(descr))) { 288 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
289 (PyObject *)PyDescr_TYPE(descr))) {
288 PyErr_Format(PyExc_TypeError, 290 PyErr_Format(PyExc_TypeError,
289 "descriptor '%V' " 291 "descriptor '%V' "
290 "requires a '%.100s' object " 292 "requires a '%.100s' object "
291 "but received a '%.100s'", 293 "but received a '%.100s'",
292 descr_name((PyDescrObject *)descr), "?", 294 descr_name((PyDescrObject *)descr), "?",
293 PyDescr_TYPE(descr)->tp_name, 295 PyDescr_TYPE(descr)->tp_name,
294 self->ob_type->tp_name); 296 self->ob_type->tp_name);
295 return NULL; 297 return NULL;
296 } 298 }
297 299
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 0, /* sq_ass_slice */ 696 0, /* sq_ass_slice */
695 (objobjproc)proxy_contains, /* sq_contains */ 697 (objobjproc)proxy_contains, /* sq_contains */
696 0, /* sq_inplace_concat */ 698 0, /* sq_inplace_concat */
697 0, /* sq_inplace_repeat */ 699 0, /* sq_inplace_repeat */
698 }; 700 };
699 701
700 static PyObject * 702 static PyObject *
701 proxy_get(proxyobject *pp, PyObject *args) 703 proxy_get(proxyobject *pp, PyObject *args)
702 { 704 {
703 PyObject *key, *def = Py_None; 705 PyObject *key, *def = Py_None;
706 _Py_IDENTIFIER(get);
704 707
705 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) 708 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
706 return NULL; 709 return NULL;
707 return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def); 710 return _PyObject_CallMethodId(pp->dict, &PyId_get, "(OO)", key, def);
708 } 711 }
709 712
710 static PyObject * 713 static PyObject *
711 proxy_keys(proxyobject *pp) 714 proxy_keys(proxyobject *pp)
712 { 715 {
713 return PyObject_CallMethod(pp->dict, "keys", NULL); 716 _Py_IDENTIFIER(keys);
717 return _PyObject_CallMethodId(pp->dict, &PyId_keys, NULL);
714 } 718 }
715 719
716 static PyObject * 720 static PyObject *
717 proxy_values(proxyobject *pp) 721 proxy_values(proxyobject *pp)
718 { 722 {
719 return PyObject_CallMethod(pp->dict, "values", NULL); 723 _Py_IDENTIFIER(values);
724 return _PyObject_CallMethodId(pp->dict, &PyId_values, NULL);
720 } 725 }
721 726
722 static PyObject * 727 static PyObject *
723 proxy_items(proxyobject *pp) 728 proxy_items(proxyobject *pp)
724 { 729 {
725 return PyObject_CallMethod(pp->dict, "items", NULL); 730 _Py_IDENTIFIER(items);
731 return _PyObject_CallMethodId(pp->dict, &PyId_items, NULL);
726 } 732 }
727 733
728 static PyObject * 734 static PyObject *
729 proxy_copy(proxyobject *pp) 735 proxy_copy(proxyobject *pp)
730 { 736 {
731 return PyObject_CallMethod(pp->dict, "copy", NULL); 737 _Py_IDENTIFIER(copy);
738 return _PyObject_CallMethodId(pp->dict, &PyId_copy, NULL);
732 } 739 }
733 740
734 static PyMethodDef proxy_methods[] = { 741 static PyMethodDef proxy_methods[] = {
735 {"get", (PyCFunction)proxy_get, METH_VARARGS, 742 {"get", (PyCFunction)proxy_get, METH_VARARGS,
736 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."
737 " d defaults to None.")}, 744 " d defaults to None.")},
738 {"keys", (PyCFunction)proxy_keys, METH_NOARGS, 745 {"keys", (PyCFunction)proxy_keys, METH_NOARGS,
739 PyDoc_STR("D.keys() -> list of D's keys")}, 746 PyDoc_STR("D.keys() -> list of D's keys")},
740 {"values", (PyCFunction)proxy_values, METH_NOARGS, 747 {"values", (PyCFunction)proxy_values, METH_NOARGS,
741 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
837 } 844 }
838 return (PyObject *)pp; 845 return (PyObject *)pp;
839 } 846 }
840 847
841 848
842 /* --- Wrapper object for "slot" methods --- */ 849 /* --- Wrapper object for "slot" methods --- */
843 850
844 /* 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
845 bit of a pain */ 852 bit of a pain */
846 853
847 /* forward */
848 static PyTypeObject wrappertype;
849
850 typedef struct { 854 typedef struct {
851 PyObject_HEAD 855 PyObject_HEAD
852 PyWrapperDescrObject *descr; 856 PyWrapperDescrObject *descr;
853 PyObject *self; 857 PyObject *self;
854 } wrapperobject; 858 } wrapperobject;
855 859
856 #define Wrapper_Check(v) (Py_TYPE(v) == &wrappertype) 860 #define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
857 861
858 static void 862 static void
859 wrapper_dealloc(wrapperobject *wp) 863 wrapper_dealloc(wrapperobject *wp)
860 { 864 {
861 PyObject_GC_UnTrack(wp); 865 PyObject_GC_UnTrack(wp);
862 Py_TRASHCAN_SAFE_BEGIN(wp) 866 Py_TRASHCAN_SAFE_BEGIN(wp)
863 Py_XDECREF(wp->descr); 867 Py_XDECREF(wp->descr);
864 Py_XDECREF(wp->self); 868 Py_XDECREF(wp->self);
865 PyObject_GC_Del(wp); 869 PyObject_GC_Del(wp);
866 Py_TRASHCAN_SAFE_END(wp) 870 Py_TRASHCAN_SAFE_END(wp)
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 1016
1013 static int 1017 static int
1014 wrapper_traverse(PyObject *self, visitproc visit, void *arg) 1018 wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1015 { 1019 {
1016 wrapperobject *wp = (wrapperobject *)self; 1020 wrapperobject *wp = (wrapperobject *)self;
1017 Py_VISIT(wp->descr); 1021 Py_VISIT(wp->descr);
1018 Py_VISIT(wp->self); 1022 Py_VISIT(wp->self);
1019 return 0; 1023 return 0;
1020 } 1024 }
1021 1025
1022 static PyTypeObject wrappertype = { 1026 PyTypeObject _PyMethodWrapper_Type = {
1023 PyVarObject_HEAD_INIT(&PyType_Type, 0) 1027 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1024 "method-wrapper", /* tp_name */ 1028 "method-wrapper", /* tp_name */
1025 sizeof(wrapperobject), /* tp_basicsize */ 1029 sizeof(wrapperobject), /* tp_basicsize */
1026 0, /* tp_itemsize */ 1030 0, /* tp_itemsize */
1027 /* methods */ 1031 /* methods */
1028 (destructor)wrapper_dealloc, /* tp_dealloc */ 1032 (destructor)wrapper_dealloc, /* tp_dealloc */
1029 0, /* tp_print */ 1033 0, /* tp_print */
1030 0, /* tp_getattr */ 1034 0, /* tp_getattr */
1031 0, /* tp_setattr */ 1035 0, /* tp_setattr */
1032 0, /* tp_reserved */ 1036 0, /* tp_reserved */
(...skipping 25 matching lines...) Expand all
1058 }; 1062 };
1059 1063
1060 PyObject * 1064 PyObject *
1061 PyWrapper_New(PyObject *d, PyObject *self) 1065 PyWrapper_New(PyObject *d, PyObject *self)
1062 { 1066 {
1063 wrapperobject *wp; 1067 wrapperobject *wp;
1064 PyWrapperDescrObject *descr; 1068 PyWrapperDescrObject *descr;
1065 1069
1066 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); 1070 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1067 descr = (PyWrapperDescrObject *)d; 1071 descr = (PyWrapperDescrObject *)d;
1068 assert(PyObject_IsInstance(self, (PyObject *)PyDescr_TYPE(descr))); 1072 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
1069 1073 (PyObject *)PyDescr_TYPE(descr)));
1070 wp = PyObject_GC_New(wrapperobject, &wrappertype); 1074
1075 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
1071 if (wp != NULL) { 1076 if (wp != NULL) {
1072 Py_INCREF(descr); 1077 Py_INCREF(descr);
1073 wp->descr = descr; 1078 wp->descr = descr;
1074 Py_INCREF(self); 1079 Py_INCREF(self);
1075 wp->self = self; 1080 wp->self = self;
1076 _PyObject_GC_TRACK(wp); 1081 _PyObject_GC_TRACK(wp);
1077 } 1082 }
1078 return (PyObject *)wp; 1083 return (PyObject *)wp;
1079 } 1084 }
1080 1085
1081 1086
1082 /* A built-in 'property' type */ 1087 /* A built-in 'property' type */
1083 1088
1084 /* 1089 /*
1085 class property(object): 1090 class property(object):
1086 1091
1087 def __init__(self, fget=None, fset=None, fdel=None, doc=None): 1092 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1088 if doc is None and fget is not None and hasattr(fget, "__doc__"): 1093 if doc is None and fget is not None and hasattr(fget, "__doc__"):
1089 doc = fget.__doc__ 1094 doc = fget.__doc__
1090 self.__get = fget 1095 self.__get = fget
1091 self.__set = fset 1096 self.__set = fset
1092 self.__del = fdel 1097 self.__del = fdel
1093 self.__doc__ = doc 1098 self.__doc__ = doc
1094 for f in (fget, fset, fdel):
1095 if getattr(f, '__isabstractmethod__', False):
1096 self.__isabstractmethod__ = True
1097 break
1098 1099
1099 def __get__(self, inst, type=None): 1100 def __get__(self, inst, type=None):
1100 if inst is None: 1101 if inst is None:
1101 return self 1102 return self
1102 if self.__get is None: 1103 if self.__get is None:
1103 raise AttributeError, "unreadable attribute" 1104 raise AttributeError, "unreadable attribute"
1104 return self.__get(inst) 1105 return self.__get(inst)
1105 1106
1106 def __set__(self, inst, value): 1107 def __set__(self, inst, value):
1107 if self.__set is None: 1108 if self.__set is None:
1108 raise AttributeError, "can't set attribute" 1109 raise AttributeError, "can't set attribute"
1109 return self.__set(inst, value) 1110 return self.__set(inst, value)
1110 1111
1111 def __delete__(self, inst): 1112 def __delete__(self, inst):
1112 if self.__del is None: 1113 if self.__del is None:
1113 raise AttributeError, "can't delete attribute" 1114 raise AttributeError, "can't delete attribute"
1114 return self.__del(inst) 1115 return self.__del(inst)
1115 1116
1116 */ 1117 */
1117 1118
1118 typedef struct { 1119 typedef struct {
1119 PyObject_HEAD 1120 PyObject_HEAD
1120 PyObject *prop_get; 1121 PyObject *prop_get;
1121 PyObject *prop_set; 1122 PyObject *prop_set;
1122 PyObject *prop_del; 1123 PyObject *prop_del;
1123 PyObject *prop_doc; 1124 PyObject *prop_doc;
1124 PyObject *prop_isabstract;
1125 int getter_doc; 1125 int getter_doc;
1126 } propertyobject; 1126 } propertyobject;
1127 1127
1128 static PyObject * property_copy(PyObject *, PyObject *, PyObject *, 1128 static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
1129 PyObject *); 1129 PyObject *);
1130 1130
1131 static PyMemberDef property_members[] = { 1131 static PyMemberDef property_members[] = {
1132 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY}, 1132 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1133 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY}, 1133 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1134 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY}, 1134 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
1135 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), READONLY}, 1135 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
1136 {"__isabstractmethod__", T_OBJECT,
1137 offsetof(propertyobject, prop_isabstract), READONLY},
1138 {0} 1136 {0}
1139 }; 1137 };
1140 1138
1141 1139
1142 PyDoc_STRVAR(getter_doc, 1140 PyDoc_STRVAR(getter_doc,
1143 "Descriptor to change the getter on a property."); 1141 "Descriptor to change the getter on a property.");
1144 1142
1145 static PyObject * 1143 static PyObject *
1146 property_getter(PyObject *self, PyObject *getter) 1144 property_getter(PyObject *self, PyObject *getter)
1147 { 1145 {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 static void 1178 static void
1181 property_dealloc(PyObject *self) 1179 property_dealloc(PyObject *self)
1182 { 1180 {
1183 propertyobject *gs = (propertyobject *)self; 1181 propertyobject *gs = (propertyobject *)self;
1184 1182
1185 _PyObject_GC_UNTRACK(self); 1183 _PyObject_GC_UNTRACK(self);
1186 Py_XDECREF(gs->prop_get); 1184 Py_XDECREF(gs->prop_get);
1187 Py_XDECREF(gs->prop_set); 1185 Py_XDECREF(gs->prop_set);
1188 Py_XDECREF(gs->prop_del); 1186 Py_XDECREF(gs->prop_del);
1189 Py_XDECREF(gs->prop_doc); 1187 Py_XDECREF(gs->prop_doc);
1190 Py_XDECREF(gs->prop_isabstract);
1191 self->ob_type->tp_free(self); 1188 self->ob_type->tp_free(self);
1192 } 1189 }
1193 1190
1194 static PyObject * 1191 static PyObject *
1195 property_descr_get(PyObject *self, PyObject *obj, PyObject *type) 1192 property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1196 { 1193 {
1197 propertyobject *gs = (propertyobject *)self; 1194 propertyobject *gs = (propertyobject *)self;
1198 1195
1199 if (obj == NULL || obj == Py_None) { 1196 if (obj == NULL || obj == Py_None) {
1200 Py_INCREF(self); 1197 Py_INCREF(self);
(...skipping 13 matching lines...) Expand all
1214 PyObject *func, *res; 1211 PyObject *func, *res;
1215 1212
1216 if (value == NULL) 1213 if (value == NULL)
1217 func = gs->prop_del; 1214 func = gs->prop_del;
1218 else 1215 else
1219 func = gs->prop_set; 1216 func = gs->prop_set;
1220 if (func == NULL) { 1217 if (func == NULL) {
1221 PyErr_SetString(PyExc_AttributeError, 1218 PyErr_SetString(PyExc_AttributeError,
1222 value == NULL ? 1219 value == NULL ?
1223 "can't delete attribute" : 1220 "can't delete attribute" :
1224 "can't set attribute"); 1221 "can't set attribute");
1225 return -1; 1222 return -1;
1226 } 1223 }
1227 if (value == NULL) 1224 if (value == NULL)
1228 res = PyObject_CallFunctionObjArgs(func, obj, NULL); 1225 res = PyObject_CallFunctionObjArgs(func, obj, NULL);
1229 else 1226 else
1230 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL); 1227 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
1231 if (res == NULL) 1228 if (res == NULL)
1232 return -1; 1229 return -1;
1233 Py_DECREF(res); 1230 Py_DECREF(res);
1234 return 0; 1231 return 0;
(...skipping 29 matching lines...) Expand all
1264 doc = pold->prop_doc ? pold->prop_doc : Py_None; 1261 doc = pold->prop_doc ? pold->prop_doc : Py_None;
1265 } 1262 }
1266 1263
1267 new = PyObject_CallFunction(type, "OOOO", get, set, del, doc); 1264 new = PyObject_CallFunction(type, "OOOO", get, set, del, doc);
1268 Py_DECREF(type); 1265 Py_DECREF(type);
1269 if (new == NULL) 1266 if (new == NULL)
1270 return NULL; 1267 return NULL;
1271 return new; 1268 return new;
1272 } 1269 }
1273 1270
1274 static void
1275 property_identify_abstract_method(PyObject *self, PyObject *method)
1276 {
1277 /* Set self.__isabstractmethod__ if method is abstract */
1278 if (method != NULL){
1279 PyObject *is_abstract = PyObject_GetAttrString(method,
1280 "__isabstractmethod__");
1281 if (PyObject_IsTrue(is_abstract) > 0){
1282 Py_INCREF(Py_True);
1283 PyObject_SetAttrString(self, "__isabstractmethod__", Py_True);
1284 }
1285 Py_DECREF(is_abstract);
1286 }
1287 }
1288
1289 static int 1271 static int
1290 property_init(PyObject *self, PyObject *args, PyObject *kwds) 1272 property_init(PyObject *self, PyObject *args, PyObject *kwds)
1291 { 1273 {
1292 PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL; 1274 PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
1293 static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0}; 1275 static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
1294 propertyobject *prop = (propertyobject *)self; 1276 propertyobject *prop = (propertyobject *)self;
1295 1277
1296 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property", 1278 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
1297 kwlist, &get, &set, &del, &doc)) 1279 kwlist, &get, &set, &del, &doc))
1298 return -1; 1280 return -1;
1299 1281
1300 if (get == Py_None) 1282 if (get == Py_None)
1301 get = NULL; 1283 get = NULL;
1302 if (set == Py_None) 1284 if (set == Py_None)
1303 set = NULL; 1285 set = NULL;
1304 if (del == Py_None) 1286 if (del == Py_None)
1305 del = NULL; 1287 del = NULL;
1306 1288
1307 Py_XINCREF(get); 1289 Py_XINCREF(get);
1308 Py_XINCREF(set); 1290 Py_XINCREF(set);
1309 Py_XINCREF(del); 1291 Py_XINCREF(del);
1310 Py_XINCREF(doc); 1292 Py_XINCREF(doc);
1311 Py_INCREF(Py_False);
1312 1293
1313 prop->prop_get = get; 1294 prop->prop_get = get;
1314 prop->prop_set = set; 1295 prop->prop_set = set;
1315 prop->prop_del = del; 1296 prop->prop_del = del;
1316 prop->prop_doc = doc; 1297 prop->prop_doc = doc;
1317 prop->prop_isabstract = Py_False;
1318 prop->getter_doc = 0; 1298 prop->getter_doc = 0;
1319 1299
1320 /* 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 */
1321 if ((doc == NULL || doc == Py_None) && get != NULL) { 1301 if ((doc == NULL || doc == Py_None) && get != NULL) {
1322 PyObject *get_doc = PyObject_GetAttrString(get, "__doc__"); 1302 _Py_IDENTIFIER(__doc__);
1303 PyObject *get_doc = _PyObject_GetAttrId(get, &PyId___doc__);
1323 if (get_doc) { 1304 if (get_doc) {
1324 if (Py_TYPE(self) == &PyProperty_Type) { 1305 if (Py_TYPE(self) == &PyProperty_Type) {
1325 Py_XDECREF(prop->prop_doc); 1306 Py_XDECREF(prop->prop_doc);
1326 prop->prop_doc = get_doc; 1307 prop->prop_doc = get_doc;
1327 } 1308 }
1328 else { 1309 else {
1329 /* If this is a property subclass, put __doc__ 1310 /* If this is a property subclass, put __doc__
1330 in dict of the subclass instance instead, 1311 in dict of the subclass instance instead,
1331 otherwise it gets shadowed by __doc__ in the 1312 otherwise it gets shadowed by __doc__ in the
1332 class's dict. */ 1313 class's dict. */
1333 int err = PyObject_SetAttrString(self, "__doc__", get_doc); 1314 int err = _PyObject_SetAttrId(self, &PyId___doc__, get_doc);
1334 Py_DECREF(get_doc); 1315 Py_DECREF(get_doc);
1335 if (err < 0) 1316 if (err < 0)
1336 return -1; 1317 return -1;
1337 } 1318 }
1338 prop->getter_doc = 1; 1319 prop->getter_doc = 1;
1339 } 1320 }
1340 else if (PyErr_ExceptionMatches(PyExc_Exception)) { 1321 else if (PyErr_ExceptionMatches(PyExc_Exception)) {
1341 PyErr_Clear(); 1322 PyErr_Clear();
1342 } 1323 }
1343 else { 1324 else {
1344 return -1; 1325 return -1;
1345 } 1326 }
1346 } 1327 }
1347 1328
1348 /* set __isabstractmethod__ if fget, fset, or fdel are abstract methods */
1349 property_identify_abstract_method(self, get);
1350 property_identify_abstract_method(self, set);
1351 property_identify_abstract_method(self, del);
1352
1353 return 0; 1329 return 0;
1354 } 1330 }
1331
1332 static PyObject *
1333 property_get___isabstractmethod__(propertyobject *prop, void *closure)
1334 {
1335 int res = _PyObject_IsAbstract(prop->prop_get);
1336 if (res == -1) {
1337 return NULL;
1338 }
1339 else if (res) {
1340 Py_RETURN_TRUE;
1341 }
1342
1343 res = _PyObject_IsAbstract(prop->prop_set);
1344 if (res == -1) {
1345 return NULL;
1346 }
1347 else if (res) {
1348 Py_RETURN_TRUE;
1349 }
1350
1351 res = _PyObject_IsAbstract(prop->prop_del);
1352 if (res == -1) {
1353 return NULL;
1354 }
1355 else if (res) {
1356 Py_RETURN_TRUE;
1357 }
1358 Py_RETURN_FALSE;
1359 }
1360
1361 static PyGetSetDef property_getsetlist[] = {
1362 {"__isabstractmethod__",
1363 (getter)property_get___isabstractmethod__, NULL,
1364 NULL,
1365 NULL},
1366 {NULL} /* Sentinel */
1367 };
1355 1368
1356 PyDoc_STRVAR(property_doc, 1369 PyDoc_STRVAR(property_doc,
1357 "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"
1358 "\n" 1371 "\n"
1359 "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"
1360 "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"
1361 "attribute. Typical use is to define a managed attribute x:\n" 1374 "attribute. Typical use is to define a managed attribute x:\n"
1362 "class C(object):\n" 1375 "class C(object):\n"
1363 " def getx(self): return self._x\n" 1376 " def getx(self): return self._x\n"
1364 " def setx(self, value): self._x = value\n" 1377 " def setx(self, value): self._x = value\n"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 Py_TPFLAGS_BASETYPE, /* tp_flags */ 1424 Py_TPFLAGS_BASETYPE, /* tp_flags */
1412 property_doc, /* tp_doc */ 1425 property_doc, /* tp_doc */
1413 property_traverse, /* tp_traverse */ 1426 property_traverse, /* tp_traverse */
1414 0, /* tp_clear */ 1427 0, /* tp_clear */
1415 0, /* tp_richcompare */ 1428 0, /* tp_richcompare */
1416 0, /* tp_weaklistoffset */ 1429 0, /* tp_weaklistoffset */
1417 0, /* tp_iter */ 1430 0, /* tp_iter */
1418 0, /* tp_iternext */ 1431 0, /* tp_iternext */
1419 property_methods, /* tp_methods */ 1432 property_methods, /* tp_methods */
1420 property_members, /* tp_members */ 1433 property_members, /* tp_members */
1421 0, /* tp_getset */ 1434 property_getsetlist, /* tp_getset */
1422 0, /* tp_base */ 1435 0, /* tp_base */
1423 0, /* tp_dict */ 1436 0, /* tp_dict */
1424 property_descr_get, /* tp_descr_get */ 1437 property_descr_get, /* tp_descr_get */
1425 property_descr_set, /* tp_descr_set */ 1438 property_descr_set, /* tp_descr_set */
1426 0, /* tp_dictoffset */ 1439 0, /* tp_dictoffset */
1427 property_init, /* tp_init */ 1440 property_init, /* tp_init */
1428 PyType_GenericAlloc, /* tp_alloc */ 1441 PyType_GenericAlloc, /* tp_alloc */
1429 PyType_GenericNew, /* tp_new */ 1442 PyType_GenericNew, /* tp_new */
1430 PyObject_GC_Del, /* tp_free */ 1443 PyObject_GC_Del, /* tp_free */
1431 }; 1444 };
LEFTRIGHT

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