PageRenderTime 62ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Objects/descrobject.c

https://bitbucket.org/mirror/cpython/
C | 1661 lines | 1424 code | 180 blank | 57 comment | 190 complexity | 9bd35c395c4d32e020c50dac70067372 MD5 | raw file
Possible License(s): Unlicense, 0BSD, BSD-3-Clause
  1. /* Descriptors -- a new, flexible way to describe attributes */
  2. #include "Python.h"
  3. #include "structmember.h" /* Why is this not included in Python.h? */
  4. static void
  5. descr_dealloc(PyDescrObject *descr)
  6. {
  7. _PyObject_GC_UNTRACK(descr);
  8. Py_XDECREF(descr->d_type);
  9. Py_XDECREF(descr->d_name);
  10. Py_XDECREF(descr->d_qualname);
  11. PyObject_GC_Del(descr);
  12. }
  13. static PyObject *
  14. descr_name(PyDescrObject *descr)
  15. {
  16. if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
  17. return descr->d_name;
  18. return NULL;
  19. }
  20. static PyObject *
  21. descr_repr(PyDescrObject *descr, const char *format)
  22. {
  23. PyObject *name = NULL;
  24. if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
  25. name = descr->d_name;
  26. return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
  27. }
  28. static PyObject *
  29. method_repr(PyMethodDescrObject *descr)
  30. {
  31. return descr_repr((PyDescrObject *)descr,
  32. "<method '%V' of '%s' objects>");
  33. }
  34. static PyObject *
  35. member_repr(PyMemberDescrObject *descr)
  36. {
  37. return descr_repr((PyDescrObject *)descr,
  38. "<member '%V' of '%s' objects>");
  39. }
  40. static PyObject *
  41. getset_repr(PyGetSetDescrObject *descr)
  42. {
  43. return descr_repr((PyDescrObject *)descr,
  44. "<attribute '%V' of '%s' objects>");
  45. }
  46. static PyObject *
  47. wrapperdescr_repr(PyWrapperDescrObject *descr)
  48. {
  49. return descr_repr((PyDescrObject *)descr,
  50. "<slot wrapper '%V' of '%s' objects>");
  51. }
  52. static int
  53. descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
  54. {
  55. if (obj == NULL) {
  56. Py_INCREF(descr);
  57. *pres = (PyObject *)descr;
  58. return 1;
  59. }
  60. if (!PyObject_TypeCheck(obj, descr->d_type)) {
  61. PyErr_Format(PyExc_TypeError,
  62. "descriptor '%V' for '%s' objects "
  63. "doesn't apply to '%s' object",
  64. descr_name((PyDescrObject *)descr), "?",
  65. descr->d_type->tp_name,
  66. obj->ob_type->tp_name);
  67. *pres = NULL;
  68. return 1;
  69. }
  70. return 0;
  71. }
  72. static PyObject *
  73. classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
  74. {
  75. /* Ensure a valid type. Class methods ignore obj. */
  76. if (type == NULL) {
  77. if (obj != NULL)
  78. type = (PyObject *)obj->ob_type;
  79. else {
  80. /* Wot - no type?! */
  81. PyErr_Format(PyExc_TypeError,
  82. "descriptor '%V' for type '%s' "
  83. "needs either an object or a type",
  84. descr_name((PyDescrObject *)descr), "?",
  85. PyDescr_TYPE(descr)->tp_name);
  86. return NULL;
  87. }
  88. }
  89. if (!PyType_Check(type)) {
  90. PyErr_Format(PyExc_TypeError,
  91. "descriptor '%V' for type '%s' "
  92. "needs a type, not a '%s' as arg 2",
  93. descr_name((PyDescrObject *)descr), "?",
  94. PyDescr_TYPE(descr)->tp_name,
  95. type->ob_type->tp_name);
  96. return NULL;
  97. }
  98. if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
  99. PyErr_Format(PyExc_TypeError,
  100. "descriptor '%V' for type '%s' "
  101. "doesn't apply to type '%s'",
  102. descr_name((PyDescrObject *)descr), "?",
  103. PyDescr_TYPE(descr)->tp_name,
  104. ((PyTypeObject *)type)->tp_name);
  105. return NULL;
  106. }
  107. return PyCFunction_NewEx(descr->d_method, type, NULL);
  108. }
  109. static PyObject *
  110. method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
  111. {
  112. PyObject *res;
  113. if (descr_check((PyDescrObject *)descr, obj, &res))
  114. return res;
  115. return PyCFunction_NewEx(descr->d_method, obj, NULL);
  116. }
  117. static PyObject *
  118. member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
  119. {
  120. PyObject *res;
  121. if (descr_check((PyDescrObject *)descr, obj, &res))
  122. return res;
  123. return PyMember_GetOne((char *)obj, descr->d_member);
  124. }
  125. static PyObject *
  126. getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
  127. {
  128. PyObject *res;
  129. if (descr_check((PyDescrObject *)descr, obj, &res))
  130. return res;
  131. if (descr->d_getset->get != NULL)
  132. return descr->d_getset->get(obj, descr->d_getset->closure);
  133. PyErr_Format(PyExc_AttributeError,
  134. "attribute '%V' of '%.100s' objects is not readable",
  135. descr_name((PyDescrObject *)descr), "?",
  136. PyDescr_TYPE(descr)->tp_name);
  137. return NULL;
  138. }
  139. static PyObject *
  140. wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
  141. {
  142. PyObject *res;
  143. if (descr_check((PyDescrObject *)descr, obj, &res))
  144. return res;
  145. return PyWrapper_New((PyObject *)descr, obj);
  146. }
  147. static int
  148. descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
  149. int *pres)
  150. {
  151. assert(obj != NULL);
  152. if (!PyObject_TypeCheck(obj, descr->d_type)) {
  153. PyErr_Format(PyExc_TypeError,
  154. "descriptor '%V' for '%.100s' objects "
  155. "doesn't apply to '%.100s' object",
  156. descr_name(descr), "?",
  157. descr->d_type->tp_name,
  158. obj->ob_type->tp_name);
  159. *pres = -1;
  160. return 1;
  161. }
  162. return 0;
  163. }
  164. static int
  165. member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
  166. {
  167. int res;
  168. if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
  169. return res;
  170. return PyMember_SetOne((char *)obj, descr->d_member, value);
  171. }
  172. static int
  173. getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
  174. {
  175. int res;
  176. if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
  177. return res;
  178. if (descr->d_getset->set != NULL)
  179. return descr->d_getset->set(obj, value,
  180. descr->d_getset->closure);
  181. PyErr_Format(PyExc_AttributeError,
  182. "attribute '%V' of '%.100s' objects is not writable",
  183. descr_name((PyDescrObject *)descr), "?",
  184. PyDescr_TYPE(descr)->tp_name);
  185. return -1;
  186. }
  187. static PyObject *
  188. methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
  189. {
  190. Py_ssize_t argc;
  191. PyObject *self, *func, *result;
  192. /* Make sure that the first argument is acceptable as 'self' */
  193. assert(PyTuple_Check(args));
  194. argc = PyTuple_GET_SIZE(args);
  195. if (argc < 1) {
  196. PyErr_Format(PyExc_TypeError,
  197. "descriptor '%V' of '%.100s' "
  198. "object needs an argument",
  199. descr_name((PyDescrObject *)descr), "?",
  200. PyDescr_TYPE(descr)->tp_name);
  201. return NULL;
  202. }
  203. self = PyTuple_GET_ITEM(args, 0);
  204. if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
  205. (PyObject *)PyDescr_TYPE(descr))) {
  206. PyErr_Format(PyExc_TypeError,
  207. "descriptor '%V' "
  208. "requires a '%.100s' object "
  209. "but received a '%.100s'",
  210. descr_name((PyDescrObject *)descr), "?",
  211. PyDescr_TYPE(descr)->tp_name,
  212. self->ob_type->tp_name);
  213. return NULL;
  214. }
  215. func = PyCFunction_NewEx(descr->d_method, self, NULL);
  216. if (func == NULL)
  217. return NULL;
  218. args = PyTuple_GetSlice(args, 1, argc);
  219. if (args == NULL) {
  220. Py_DECREF(func);
  221. return NULL;
  222. }
  223. result = PyEval_CallObjectWithKeywords(func, args, kwds);
  224. Py_DECREF(args);
  225. Py_DECREF(func);
  226. return result;
  227. }
  228. static PyObject *
  229. classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
  230. PyObject *kwds)
  231. {
  232. Py_ssize_t argc;
  233. PyObject *self, *func, *result;
  234. /* Make sure that the first argument is acceptable as 'self' */
  235. assert(PyTuple_Check(args));
  236. argc = PyTuple_GET_SIZE(args);
  237. if (argc < 1) {
  238. PyErr_Format(PyExc_TypeError,
  239. "descriptor '%V' of '%.100s' "
  240. "object needs an argument",
  241. descr_name((PyDescrObject *)descr), "?",
  242. PyDescr_TYPE(descr)->tp_name);
  243. return NULL;
  244. }
  245. self = PyTuple_GET_ITEM(args, 0);
  246. if (!PyType_Check(self)) {
  247. PyErr_Format(PyExc_TypeError,
  248. "descriptor '%V' requires a type "
  249. "but received a '%.100s'",
  250. descr_name((PyDescrObject *)descr), "?",
  251. PyDescr_TYPE(descr)->tp_name,
  252. self->ob_type->tp_name);
  253. return NULL;
  254. }
  255. if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
  256. PyErr_Format(PyExc_TypeError,
  257. "descriptor '%V' "
  258. "requires a subtype of '%.100s' "
  259. "but received '%.100s",
  260. descr_name((PyDescrObject *)descr), "?",
  261. PyDescr_TYPE(descr)->tp_name,
  262. self->ob_type->tp_name);
  263. return NULL;
  264. }
  265. func = PyCFunction_NewEx(descr->d_method, self, NULL);
  266. if (func == NULL)
  267. return NULL;
  268. args = PyTuple_GetSlice(args, 1, argc);
  269. if (args == NULL) {
  270. Py_DECREF(func);
  271. return NULL;
  272. }
  273. result = PyEval_CallObjectWithKeywords(func, args, kwds);
  274. Py_DECREF(func);
  275. Py_DECREF(args);
  276. return result;
  277. }
  278. static PyObject *
  279. wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
  280. {
  281. Py_ssize_t argc;
  282. PyObject *self, *func, *result;
  283. /* Make sure that the first argument is acceptable as 'self' */
  284. assert(PyTuple_Check(args));
  285. argc = PyTuple_GET_SIZE(args);
  286. if (argc < 1) {
  287. PyErr_Format(PyExc_TypeError,
  288. "descriptor '%V' of '%.100s' "
  289. "object needs an argument",
  290. descr_name((PyDescrObject *)descr), "?",
  291. PyDescr_TYPE(descr)->tp_name);
  292. return NULL;
  293. }
  294. self = PyTuple_GET_ITEM(args, 0);
  295. if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
  296. (PyObject *)PyDescr_TYPE(descr))) {
  297. PyErr_Format(PyExc_TypeError,
  298. "descriptor '%V' "
  299. "requires a '%.100s' object "
  300. "but received a '%.100s'",
  301. descr_name((PyDescrObject *)descr), "?",
  302. PyDescr_TYPE(descr)->tp_name,
  303. self->ob_type->tp_name);
  304. return NULL;
  305. }
  306. func = PyWrapper_New((PyObject *)descr, self);
  307. if (func == NULL)
  308. return NULL;
  309. args = PyTuple_GetSlice(args, 1, argc);
  310. if (args == NULL) {
  311. Py_DECREF(func);
  312. return NULL;
  313. }
  314. result = PyEval_CallObjectWithKeywords(func, args, kwds);
  315. Py_DECREF(args);
  316. Py_DECREF(func);
  317. return result;
  318. }
  319. static PyObject *
  320. method_get_doc(PyMethodDescrObject *descr, void *closure)
  321. {
  322. return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
  323. }
  324. static PyObject *
  325. method_get_text_signature(PyMethodDescrObject *descr, void *closure)
  326. {
  327. return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
  328. }
  329. static PyObject *
  330. calculate_qualname(PyDescrObject *descr)
  331. {
  332. PyObject *type_qualname, *res;
  333. _Py_IDENTIFIER(__qualname__);
  334. if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
  335. PyErr_SetString(PyExc_TypeError,
  336. "<descriptor>.__name__ is not a unicode object");
  337. return NULL;
  338. }
  339. type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
  340. &PyId___qualname__);
  341. if (type_qualname == NULL)
  342. return NULL;
  343. if (!PyUnicode_Check(type_qualname)) {
  344. PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
  345. "__qualname__ is not a unicode object");
  346. Py_XDECREF(type_qualname);
  347. return NULL;
  348. }
  349. res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
  350. Py_DECREF(type_qualname);
  351. return res;
  352. }
  353. static PyObject *
  354. descr_get_qualname(PyDescrObject *descr)
  355. {
  356. if (descr->d_qualname == NULL)
  357. descr->d_qualname = calculate_qualname(descr);
  358. Py_XINCREF(descr->d_qualname);
  359. return descr->d_qualname;
  360. }
  361. static PyObject *
  362. descr_reduce(PyDescrObject *descr)
  363. {
  364. PyObject *builtins;
  365. PyObject *getattr;
  366. _Py_IDENTIFIER(getattr);
  367. builtins = PyEval_GetBuiltins();
  368. getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
  369. return Py_BuildValue("O(OO)", getattr, PyDescr_TYPE(descr),
  370. PyDescr_NAME(descr));
  371. }
  372. static PyMethodDef descr_methods[] = {
  373. {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
  374. {NULL, NULL}
  375. };
  376. static PyMemberDef descr_members[] = {
  377. {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
  378. {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
  379. {0}
  380. };
  381. static PyGetSetDef method_getset[] = {
  382. {"__doc__", (getter)method_get_doc},
  383. {"__qualname__", (getter)descr_get_qualname},
  384. {"__text_signature__", (getter)method_get_text_signature},
  385. {0}
  386. };
  387. static PyObject *
  388. member_get_doc(PyMemberDescrObject *descr, void *closure)
  389. {
  390. if (descr->d_member->doc == NULL) {
  391. Py_INCREF(Py_None);
  392. return Py_None;
  393. }
  394. return PyUnicode_FromString(descr->d_member->doc);
  395. }
  396. static PyGetSetDef member_getset[] = {
  397. {"__doc__", (getter)member_get_doc},
  398. {"__qualname__", (getter)descr_get_qualname},
  399. {0}
  400. };
  401. static PyObject *
  402. getset_get_doc(PyGetSetDescrObject *descr, void *closure)
  403. {
  404. if (descr->d_getset->doc == NULL) {
  405. Py_INCREF(Py_None);
  406. return Py_None;
  407. }
  408. return PyUnicode_FromString(descr->d_getset->doc);
  409. }
  410. static PyGetSetDef getset_getset[] = {
  411. {"__doc__", (getter)getset_get_doc},
  412. {"__qualname__", (getter)descr_get_qualname},
  413. {0}
  414. };
  415. static PyObject *
  416. wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
  417. {
  418. return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
  419. }
  420. static PyObject *
  421. wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
  422. {
  423. return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
  424. }
  425. static PyGetSetDef wrapperdescr_getset[] = {
  426. {"__doc__", (getter)wrapperdescr_get_doc},
  427. {"__qualname__", (getter)descr_get_qualname},
  428. {"__text_signature__", (getter)wrapperdescr_get_text_signature},
  429. {0}
  430. };
  431. static int
  432. descr_traverse(PyObject *self, visitproc visit, void *arg)
  433. {
  434. PyDescrObject *descr = (PyDescrObject *)self;
  435. Py_VISIT(descr->d_type);
  436. return 0;
  437. }
  438. PyTypeObject PyMethodDescr_Type = {
  439. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  440. "method_descriptor",
  441. sizeof(PyMethodDescrObject),
  442. 0,
  443. (destructor)descr_dealloc, /* tp_dealloc */
  444. 0, /* tp_print */
  445. 0, /* tp_getattr */
  446. 0, /* tp_setattr */
  447. 0, /* tp_reserved */
  448. (reprfunc)method_repr, /* tp_repr */
  449. 0, /* tp_as_number */
  450. 0, /* tp_as_sequence */
  451. 0, /* tp_as_mapping */
  452. 0, /* tp_hash */
  453. (ternaryfunc)methoddescr_call, /* tp_call */
  454. 0, /* tp_str */
  455. PyObject_GenericGetAttr, /* tp_getattro */
  456. 0, /* tp_setattro */
  457. 0, /* tp_as_buffer */
  458. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  459. 0, /* tp_doc */
  460. descr_traverse, /* tp_traverse */
  461. 0, /* tp_clear */
  462. 0, /* tp_richcompare */
  463. 0, /* tp_weaklistoffset */
  464. 0, /* tp_iter */
  465. 0, /* tp_iternext */
  466. descr_methods, /* tp_methods */
  467. descr_members, /* tp_members */
  468. method_getset, /* tp_getset */
  469. 0, /* tp_base */
  470. 0, /* tp_dict */
  471. (descrgetfunc)method_get, /* tp_descr_get */
  472. 0, /* tp_descr_set */
  473. };
  474. /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
  475. PyTypeObject PyClassMethodDescr_Type = {
  476. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  477. "classmethod_descriptor",
  478. sizeof(PyMethodDescrObject),
  479. 0,
  480. (destructor)descr_dealloc, /* tp_dealloc */
  481. 0, /* tp_print */
  482. 0, /* tp_getattr */
  483. 0, /* tp_setattr */
  484. 0, /* tp_reserved */
  485. (reprfunc)method_repr, /* tp_repr */
  486. 0, /* tp_as_number */
  487. 0, /* tp_as_sequence */
  488. 0, /* tp_as_mapping */
  489. 0, /* tp_hash */
  490. (ternaryfunc)classmethoddescr_call, /* tp_call */
  491. 0, /* tp_str */
  492. PyObject_GenericGetAttr, /* tp_getattro */
  493. 0, /* tp_setattro */
  494. 0, /* tp_as_buffer */
  495. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  496. 0, /* tp_doc */
  497. descr_traverse, /* tp_traverse */
  498. 0, /* tp_clear */
  499. 0, /* tp_richcompare */
  500. 0, /* tp_weaklistoffset */
  501. 0, /* tp_iter */
  502. 0, /* tp_iternext */
  503. descr_methods, /* tp_methods */
  504. descr_members, /* tp_members */
  505. method_getset, /* tp_getset */
  506. 0, /* tp_base */
  507. 0, /* tp_dict */
  508. (descrgetfunc)classmethod_get, /* tp_descr_get */
  509. 0, /* tp_descr_set */
  510. };
  511. PyTypeObject PyMemberDescr_Type = {
  512. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  513. "member_descriptor",
  514. sizeof(PyMemberDescrObject),
  515. 0,
  516. (destructor)descr_dealloc, /* tp_dealloc */
  517. 0, /* tp_print */
  518. 0, /* tp_getattr */
  519. 0, /* tp_setattr */
  520. 0, /* tp_reserved */
  521. (reprfunc)member_repr, /* tp_repr */
  522. 0, /* tp_as_number */
  523. 0, /* tp_as_sequence */
  524. 0, /* tp_as_mapping */
  525. 0, /* tp_hash */
  526. 0, /* tp_call */
  527. 0, /* tp_str */
  528. PyObject_GenericGetAttr, /* tp_getattro */
  529. 0, /* tp_setattro */
  530. 0, /* tp_as_buffer */
  531. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  532. 0, /* tp_doc */
  533. descr_traverse, /* tp_traverse */
  534. 0, /* tp_clear */
  535. 0, /* tp_richcompare */
  536. 0, /* tp_weaklistoffset */
  537. 0, /* tp_iter */
  538. 0, /* tp_iternext */
  539. descr_methods, /* tp_methods */
  540. descr_members, /* tp_members */
  541. member_getset, /* tp_getset */
  542. 0, /* tp_base */
  543. 0, /* tp_dict */
  544. (descrgetfunc)member_get, /* tp_descr_get */
  545. (descrsetfunc)member_set, /* tp_descr_set */
  546. };
  547. PyTypeObject PyGetSetDescr_Type = {
  548. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  549. "getset_descriptor",
  550. sizeof(PyGetSetDescrObject),
  551. 0,
  552. (destructor)descr_dealloc, /* tp_dealloc */
  553. 0, /* tp_print */
  554. 0, /* tp_getattr */
  555. 0, /* tp_setattr */
  556. 0, /* tp_reserved */
  557. (reprfunc)getset_repr, /* tp_repr */
  558. 0, /* tp_as_number */
  559. 0, /* tp_as_sequence */
  560. 0, /* tp_as_mapping */
  561. 0, /* tp_hash */
  562. 0, /* tp_call */
  563. 0, /* tp_str */
  564. PyObject_GenericGetAttr, /* tp_getattro */
  565. 0, /* tp_setattro */
  566. 0, /* tp_as_buffer */
  567. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  568. 0, /* tp_doc */
  569. descr_traverse, /* tp_traverse */
  570. 0, /* tp_clear */
  571. 0, /* tp_richcompare */
  572. 0, /* tp_weaklistoffset */
  573. 0, /* tp_iter */
  574. 0, /* tp_iternext */
  575. 0, /* tp_methods */
  576. descr_members, /* tp_members */
  577. getset_getset, /* tp_getset */
  578. 0, /* tp_base */
  579. 0, /* tp_dict */
  580. (descrgetfunc)getset_get, /* tp_descr_get */
  581. (descrsetfunc)getset_set, /* tp_descr_set */
  582. };
  583. PyTypeObject PyWrapperDescr_Type = {
  584. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  585. "wrapper_descriptor",
  586. sizeof(PyWrapperDescrObject),
  587. 0,
  588. (destructor)descr_dealloc, /* tp_dealloc */
  589. 0, /* tp_print */
  590. 0, /* tp_getattr */
  591. 0, /* tp_setattr */
  592. 0, /* tp_reserved */
  593. (reprfunc)wrapperdescr_repr, /* tp_repr */
  594. 0, /* tp_as_number */
  595. 0, /* tp_as_sequence */
  596. 0, /* tp_as_mapping */
  597. 0, /* tp_hash */
  598. (ternaryfunc)wrapperdescr_call, /* tp_call */
  599. 0, /* tp_str */
  600. PyObject_GenericGetAttr, /* tp_getattro */
  601. 0, /* tp_setattro */
  602. 0, /* tp_as_buffer */
  603. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  604. 0, /* tp_doc */
  605. descr_traverse, /* tp_traverse */
  606. 0, /* tp_clear */
  607. 0, /* tp_richcompare */
  608. 0, /* tp_weaklistoffset */
  609. 0, /* tp_iter */
  610. 0, /* tp_iternext */
  611. descr_methods, /* tp_methods */
  612. descr_members, /* tp_members */
  613. wrapperdescr_getset, /* tp_getset */
  614. 0, /* tp_base */
  615. 0, /* tp_dict */
  616. (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
  617. 0, /* tp_descr_set */
  618. };
  619. static PyDescrObject *
  620. descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
  621. {
  622. PyDescrObject *descr;
  623. descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
  624. if (descr != NULL) {
  625. Py_XINCREF(type);
  626. descr->d_type = type;
  627. descr->d_name = PyUnicode_InternFromString(name);
  628. if (descr->d_name == NULL) {
  629. Py_DECREF(descr);
  630. descr = NULL;
  631. }
  632. else {
  633. descr->d_qualname = NULL;
  634. }
  635. }
  636. return descr;
  637. }
  638. PyObject *
  639. PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
  640. {
  641. PyMethodDescrObject *descr;
  642. descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
  643. type, method->ml_name);
  644. if (descr != NULL)
  645. descr->d_method = method;
  646. return (PyObject *)descr;
  647. }
  648. PyObject *
  649. PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
  650. {
  651. PyMethodDescrObject *descr;
  652. descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
  653. type, method->ml_name);
  654. if (descr != NULL)
  655. descr->d_method = method;
  656. return (PyObject *)descr;
  657. }
  658. PyObject *
  659. PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
  660. {
  661. PyMemberDescrObject *descr;
  662. descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
  663. type, member->name);
  664. if (descr != NULL)
  665. descr->d_member = member;
  666. return (PyObject *)descr;
  667. }
  668. PyObject *
  669. PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
  670. {
  671. PyGetSetDescrObject *descr;
  672. descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
  673. type, getset->name);
  674. if (descr != NULL)
  675. descr->d_getset = getset;
  676. return (PyObject *)descr;
  677. }
  678. PyObject *
  679. PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
  680. {
  681. PyWrapperDescrObject *descr;
  682. descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
  683. type, base->name);
  684. if (descr != NULL) {
  685. descr->d_base = base;
  686. descr->d_wrapped = wrapped;
  687. }
  688. return (PyObject *)descr;
  689. }
  690. /* --- mappingproxy: read-only proxy for mappings --- */
  691. /* This has no reason to be in this file except that adding new files is a
  692. bit of a pain */
  693. typedef struct {
  694. PyObject_HEAD
  695. PyObject *mapping;
  696. } mappingproxyobject;
  697. static Py_ssize_t
  698. mappingproxy_len(mappingproxyobject *pp)
  699. {
  700. return PyObject_Size(pp->mapping);
  701. }
  702. static PyObject *
  703. mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
  704. {
  705. return PyObject_GetItem(pp->mapping, key);
  706. }
  707. static PyMappingMethods mappingproxy_as_mapping = {
  708. (lenfunc)mappingproxy_len, /* mp_length */
  709. (binaryfunc)mappingproxy_getitem, /* mp_subscript */
  710. 0, /* mp_ass_subscript */
  711. };
  712. static int
  713. mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
  714. {
  715. if (PyDict_CheckExact(pp->mapping))
  716. return PyDict_Contains(pp->mapping, key);
  717. else
  718. return PySequence_Contains(pp->mapping, key);
  719. }
  720. static PySequenceMethods mappingproxy_as_sequence = {
  721. 0, /* sq_length */
  722. 0, /* sq_concat */
  723. 0, /* sq_repeat */
  724. 0, /* sq_item */
  725. 0, /* sq_slice */
  726. 0, /* sq_ass_item */
  727. 0, /* sq_ass_slice */
  728. (objobjproc)mappingproxy_contains, /* sq_contains */
  729. 0, /* sq_inplace_concat */
  730. 0, /* sq_inplace_repeat */
  731. };
  732. static PyObject *
  733. mappingproxy_get(mappingproxyobject *pp, PyObject *args)
  734. {
  735. PyObject *key, *def = Py_None;
  736. _Py_IDENTIFIER(get);
  737. if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
  738. return NULL;
  739. return _PyObject_CallMethodId(pp->mapping, &PyId_get, "(OO)", key, def);
  740. }
  741. static PyObject *
  742. mappingproxy_keys(mappingproxyobject *pp)
  743. {
  744. _Py_IDENTIFIER(keys);
  745. return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL);
  746. }
  747. static PyObject *
  748. mappingproxy_values(mappingproxyobject *pp)
  749. {
  750. _Py_IDENTIFIER(values);
  751. return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL);
  752. }
  753. static PyObject *
  754. mappingproxy_items(mappingproxyobject *pp)
  755. {
  756. _Py_IDENTIFIER(items);
  757. return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL);
  758. }
  759. static PyObject *
  760. mappingproxy_copy(mappingproxyobject *pp)
  761. {
  762. _Py_IDENTIFIER(copy);
  763. return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL);
  764. }
  765. /* WARNING: mappingproxy methods must not give access
  766. to the underlying mapping */
  767. static PyMethodDef mappingproxy_methods[] = {
  768. {"get", (PyCFunction)mappingproxy_get, METH_VARARGS,
  769. PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
  770. " d defaults to None.")},
  771. {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
  772. PyDoc_STR("D.keys() -> list of D's keys")},
  773. {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
  774. PyDoc_STR("D.values() -> list of D's values")},
  775. {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
  776. PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
  777. {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
  778. PyDoc_STR("D.copy() -> a shallow copy of D")},
  779. {0}
  780. };
  781. static void
  782. mappingproxy_dealloc(mappingproxyobject *pp)
  783. {
  784. _PyObject_GC_UNTRACK(pp);
  785. Py_DECREF(pp->mapping);
  786. PyObject_GC_Del(pp);
  787. }
  788. static PyObject *
  789. mappingproxy_getiter(mappingproxyobject *pp)
  790. {
  791. return PyObject_GetIter(pp->mapping);
  792. }
  793. static PyObject *
  794. mappingproxy_str(mappingproxyobject *pp)
  795. {
  796. return PyObject_Str(pp->mapping);
  797. }
  798. static PyObject *
  799. mappingproxy_repr(mappingproxyobject *pp)
  800. {
  801. return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
  802. }
  803. static int
  804. mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
  805. {
  806. mappingproxyobject *pp = (mappingproxyobject *)self;
  807. Py_VISIT(pp->mapping);
  808. return 0;
  809. }
  810. static PyObject *
  811. mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
  812. {
  813. return PyObject_RichCompare(v->mapping, w, op);
  814. }
  815. static int
  816. mappingproxy_check_mapping(PyObject *mapping)
  817. {
  818. if (!PyMapping_Check(mapping)
  819. || PyList_Check(mapping)
  820. || PyTuple_Check(mapping)) {
  821. PyErr_Format(PyExc_TypeError,
  822. "mappingproxy() argument must be a mapping, not %s",
  823. Py_TYPE(mapping)->tp_name);
  824. return -1;
  825. }
  826. return 0;
  827. }
  828. static PyObject*
  829. mappingproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  830. {
  831. static char *kwlist[] = {"mapping", NULL};
  832. PyObject *mapping;
  833. mappingproxyobject *mappingproxy;
  834. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:mappingproxy",
  835. kwlist, &mapping))
  836. return NULL;
  837. if (mappingproxy_check_mapping(mapping) == -1)
  838. return NULL;
  839. mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
  840. if (mappingproxy == NULL)
  841. return NULL;
  842. Py_INCREF(mapping);
  843. mappingproxy->mapping = mapping;
  844. _PyObject_GC_TRACK(mappingproxy);
  845. return (PyObject *)mappingproxy;
  846. }
  847. PyTypeObject PyDictProxy_Type = {
  848. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  849. "mappingproxy", /* tp_name */
  850. sizeof(mappingproxyobject), /* tp_basicsize */
  851. 0, /* tp_itemsize */
  852. /* methods */
  853. (destructor)mappingproxy_dealloc, /* tp_dealloc */
  854. 0, /* tp_print */
  855. 0, /* tp_getattr */
  856. 0, /* tp_setattr */
  857. 0, /* tp_reserved */
  858. (reprfunc)mappingproxy_repr, /* tp_repr */
  859. 0, /* tp_as_number */
  860. &mappingproxy_as_sequence, /* tp_as_sequence */
  861. &mappingproxy_as_mapping, /* tp_as_mapping */
  862. 0, /* tp_hash */
  863. 0, /* tp_call */
  864. (reprfunc)mappingproxy_str, /* tp_str */
  865. PyObject_GenericGetAttr, /* tp_getattro */
  866. 0, /* tp_setattro */
  867. 0, /* tp_as_buffer */
  868. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  869. 0, /* tp_doc */
  870. mappingproxy_traverse, /* tp_traverse */
  871. 0, /* tp_clear */
  872. (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
  873. 0, /* tp_weaklistoffset */
  874. (getiterfunc)mappingproxy_getiter, /* tp_iter */
  875. 0, /* tp_iternext */
  876. mappingproxy_methods, /* tp_methods */
  877. 0, /* tp_members */
  878. 0, /* tp_getset */
  879. 0, /* tp_base */
  880. 0, /* tp_dict */
  881. 0, /* tp_descr_get */
  882. 0, /* tp_descr_set */
  883. 0, /* tp_dictoffset */
  884. 0, /* tp_init */
  885. 0, /* tp_alloc */
  886. mappingproxy_new, /* tp_new */
  887. };
  888. PyObject *
  889. PyDictProxy_New(PyObject *mapping)
  890. {
  891. mappingproxyobject *pp;
  892. if (mappingproxy_check_mapping(mapping) == -1)
  893. return NULL;
  894. pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
  895. if (pp != NULL) {
  896. Py_INCREF(mapping);
  897. pp->mapping = mapping;
  898. _PyObject_GC_TRACK(pp);
  899. }
  900. return (PyObject *)pp;
  901. }
  902. /* --- Wrapper object for "slot" methods --- */
  903. /* This has no reason to be in this file except that adding new files is a
  904. bit of a pain */
  905. typedef struct {
  906. PyObject_HEAD
  907. PyWrapperDescrObject *descr;
  908. PyObject *self;
  909. } wrapperobject;
  910. #define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
  911. static void
  912. wrapper_dealloc(wrapperobject *wp)
  913. {
  914. PyObject_GC_UnTrack(wp);
  915. Py_TRASHCAN_SAFE_BEGIN(wp)
  916. Py_XDECREF(wp->descr);
  917. Py_XDECREF(wp->self);
  918. PyObject_GC_Del(wp);
  919. Py_TRASHCAN_SAFE_END(wp)
  920. }
  921. #define TEST_COND(cond) ((cond) ? Py_True : Py_False)
  922. static PyObject *
  923. wrapper_richcompare(PyObject *a, PyObject *b, int op)
  924. {
  925. Py_intptr_t result;
  926. PyObject *v;
  927. PyWrapperDescrObject *a_descr, *b_descr;
  928. assert(a != NULL && b != NULL);
  929. /* both arguments should be wrapperobjects */
  930. if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
  931. v = Py_NotImplemented;
  932. Py_INCREF(v);
  933. return v;
  934. }
  935. /* compare by descriptor address; if the descriptors are the same,
  936. compare by the objects they're bound to */
  937. a_descr = ((wrapperobject *)a)->descr;
  938. b_descr = ((wrapperobject *)b)->descr;
  939. if (a_descr == b_descr) {
  940. a = ((wrapperobject *)a)->self;
  941. b = ((wrapperobject *)b)->self;
  942. return PyObject_RichCompare(a, b, op);
  943. }
  944. result = a_descr - b_descr;
  945. switch (op) {
  946. case Py_EQ:
  947. v = TEST_COND(result == 0);
  948. break;
  949. case Py_NE:
  950. v = TEST_COND(result != 0);
  951. break;
  952. case Py_LE:
  953. v = TEST_COND(result <= 0);
  954. break;
  955. case Py_GE:
  956. v = TEST_COND(result >= 0);
  957. break;
  958. case Py_LT:
  959. v = TEST_COND(result < 0);
  960. break;
  961. case Py_GT:
  962. v = TEST_COND(result > 0);
  963. break;
  964. default:
  965. PyErr_BadArgument();
  966. return NULL;
  967. }
  968. Py_INCREF(v);
  969. return v;
  970. }
  971. static Py_hash_t
  972. wrapper_hash(wrapperobject *wp)
  973. {
  974. Py_hash_t x, y;
  975. x = _Py_HashPointer(wp->descr);
  976. if (x == -1)
  977. return -1;
  978. y = PyObject_Hash(wp->self);
  979. if (y == -1)
  980. return -1;
  981. x = x ^ y;
  982. if (x == -1)
  983. x = -2;
  984. return x;
  985. }
  986. static PyObject *
  987. wrapper_repr(wrapperobject *wp)
  988. {
  989. return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
  990. wp->descr->d_base->name,
  991. wp->self->ob_type->tp_name,
  992. wp->self);
  993. }
  994. static PyObject *
  995. wrapper_reduce(wrapperobject *wp)
  996. {
  997. PyObject *builtins;
  998. PyObject *getattr;
  999. _Py_IDENTIFIER(getattr);
  1000. builtins = PyEval_GetBuiltins();
  1001. getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
  1002. return Py_BuildValue("O(OO)", getattr, wp->self, PyDescr_NAME(wp->descr));
  1003. }
  1004. static PyMethodDef wrapper_methods[] = {
  1005. {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
  1006. {NULL, NULL}
  1007. };
  1008. static PyMemberDef wrapper_members[] = {
  1009. {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
  1010. {0}
  1011. };
  1012. static PyObject *
  1013. wrapper_objclass(wrapperobject *wp)
  1014. {
  1015. PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
  1016. Py_INCREF(c);
  1017. return c;
  1018. }
  1019. static PyObject *
  1020. wrapper_name(wrapperobject *wp)
  1021. {
  1022. const char *s = wp->descr->d_base->name;
  1023. return PyUnicode_FromString(s);
  1024. }
  1025. static PyObject *
  1026. wrapper_doc(wrapperobject *wp, void *closure)
  1027. {
  1028. return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
  1029. }
  1030. static PyObject *
  1031. wrapper_text_signature(wrapperobject *wp, void *closure)
  1032. {
  1033. return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
  1034. }
  1035. static PyObject *
  1036. wrapper_qualname(wrapperobject *wp)
  1037. {
  1038. return descr_get_qualname((PyDescrObject *)wp->descr);
  1039. }
  1040. static PyGetSetDef wrapper_getsets[] = {
  1041. {"__objclass__", (getter)wrapper_objclass},
  1042. {"__name__", (getter)wrapper_name},
  1043. {"__qualname__", (getter)wrapper_qualname},
  1044. {"__doc__", (getter)wrapper_doc},
  1045. {"__text_signature__", (getter)wrapper_text_signature},
  1046. {0}
  1047. };
  1048. static PyObject *
  1049. wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
  1050. {
  1051. wrapperfunc wrapper = wp->descr->d_base->wrapper;
  1052. PyObject *self = wp->self;
  1053. if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
  1054. wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
  1055. return (*wk)(self, args, wp->descr->d_wrapped, kwds);
  1056. }
  1057. if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) {
  1058. PyErr_Format(PyExc_TypeError,
  1059. "wrapper %s doesn't take keyword arguments",
  1060. wp->descr->d_base->name);
  1061. return NULL;
  1062. }
  1063. return (*wrapper)(self, args, wp->descr->d_wrapped);
  1064. }
  1065. static int
  1066. wrapper_traverse(PyObject *self, visitproc visit, void *arg)
  1067. {
  1068. wrapperobject *wp = (wrapperobject *)self;
  1069. Py_VISIT(wp->descr);
  1070. Py_VISIT(wp->self);
  1071. return 0;
  1072. }
  1073. PyTypeObject _PyMethodWrapper_Type = {
  1074. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  1075. "method-wrapper", /* tp_name */
  1076. sizeof(wrapperobject), /* tp_basicsize */
  1077. 0, /* tp_itemsize */
  1078. /* methods */
  1079. (destructor)wrapper_dealloc, /* tp_dealloc */
  1080. 0, /* tp_print */
  1081. 0, /* tp_getattr */
  1082. 0, /* tp_setattr */
  1083. 0, /* tp_reserved */
  1084. (reprfunc)wrapper_repr, /* tp_repr */
  1085. 0, /* tp_as_number */
  1086. 0, /* tp_as_sequence */
  1087. 0, /* tp_as_mapping */
  1088. (hashfunc)wrapper_hash, /* tp_hash */
  1089. (ternaryfunc)wrapper_call, /* tp_call */
  1090. 0, /* tp_str */
  1091. PyObject_GenericGetAttr, /* tp_getattro */
  1092. 0, /* tp_setattro */
  1093. 0, /* tp_as_buffer */
  1094. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  1095. 0, /* tp_doc */
  1096. wrapper_traverse, /* tp_traverse */
  1097. 0, /* tp_clear */
  1098. wrapper_richcompare, /* tp_richcompare */
  1099. 0, /* tp_weaklistoffset */
  1100. 0, /* tp_iter */
  1101. 0, /* tp_iternext */
  1102. wrapper_methods, /* tp_methods */
  1103. wrapper_members, /* tp_members */
  1104. wrapper_getsets, /* tp_getset */
  1105. 0, /* tp_base */
  1106. 0, /* tp_dict */
  1107. 0, /* tp_descr_get */
  1108. 0, /* tp_descr_set */
  1109. };
  1110. PyObject *
  1111. PyWrapper_New(PyObject *d, PyObject *self)
  1112. {
  1113. wrapperobject *wp;
  1114. PyWrapperDescrObject *descr;
  1115. assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
  1116. descr = (PyWrapperDescrObject *)d;
  1117. assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
  1118. (PyObject *)PyDescr_TYPE(descr)));
  1119. wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
  1120. if (wp != NULL) {
  1121. Py_INCREF(descr);
  1122. wp->descr = descr;
  1123. Py_INCREF(self);
  1124. wp->self = self;
  1125. _PyObject_GC_TRACK(wp);
  1126. }
  1127. return (PyObject *)wp;
  1128. }
  1129. /* A built-in 'property' type */
  1130. /*
  1131. class property(object):
  1132. def __init__(self, fget=None, fset=None, fdel=None, doc=None):
  1133. if doc is None and fget is not None and hasattr(fget, "__doc__"):
  1134. doc = fget.__doc__
  1135. self.__get = fget
  1136. self.__set = fset
  1137. self.__del = fdel
  1138. self.__doc__ = doc
  1139. def __get__(self, inst, type=None):
  1140. if inst is None:
  1141. return self
  1142. if self.__get is None:
  1143. raise AttributeError, "unreadable attribute"
  1144. return self.__get(inst)
  1145. def __set__(self, inst, value):
  1146. if self.__set is None:
  1147. raise AttributeError, "can't set attribute"
  1148. return self.__set(inst, value)
  1149. def __delete__(self, inst):
  1150. if self.__del is None:
  1151. raise AttributeError, "can't delete attribute"
  1152. return self.__del(inst)
  1153. */
  1154. typedef struct {
  1155. PyObject_HEAD
  1156. PyObject *prop_get;
  1157. PyObject *prop_set;
  1158. PyObject *prop_del;
  1159. PyObject *prop_doc;
  1160. int getter_doc;
  1161. } propertyobject;
  1162. static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
  1163. PyObject *);
  1164. static PyMemberDef property_members[] = {
  1165. {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
  1166. {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
  1167. {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
  1168. {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
  1169. {0}
  1170. };
  1171. PyDoc_STRVAR(getter_doc,
  1172. "Descriptor to change the getter on a property.");
  1173. static PyObject *
  1174. property_getter(PyObject *self, PyObject *getter)
  1175. {
  1176. return property_copy(self, getter, NULL, NULL);
  1177. }
  1178. PyDoc_STRVAR(setter_doc,
  1179. "Descriptor to change the setter on a property.");
  1180. static PyObject *
  1181. property_setter(PyObject *self, PyObject *setter)
  1182. {
  1183. return property_copy(self, NULL, setter, NULL);
  1184. }
  1185. PyDoc_STRVAR(deleter_doc,
  1186. "Descriptor to change the deleter on a property.");
  1187. static PyObject *
  1188. property_deleter(PyObject *self, PyObject *deleter)
  1189. {
  1190. return property_copy(self, NULL, NULL, deleter);
  1191. }
  1192. static PyMethodDef property_methods[] = {
  1193. {"getter", property_getter, METH_O, getter_doc},
  1194. {"setter", property_setter, METH_O, setter_doc},
  1195. {"deleter", property_deleter, METH_O, deleter_doc},
  1196. {0}
  1197. };
  1198. static void
  1199. property_dealloc(PyObject *self)
  1200. {
  1201. propertyobject *gs = (propertyobject *)self;
  1202. _PyObject_GC_UNTRACK(self);
  1203. Py_XDECREF(gs->prop_get);
  1204. Py_XDECREF(gs->prop_set);
  1205. Py_XDECREF(gs->prop_del);
  1206. Py_XDECREF(gs->prop_doc);
  1207. self->ob_type->tp_free(self);
  1208. }
  1209. static PyObject *
  1210. property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
  1211. {
  1212. static PyObject * volatile cached_args = NULL;
  1213. PyObject *args;
  1214. PyObject *ret;
  1215. propertyobject *gs = (propertyobject *)self;
  1216. if (obj == NULL || obj == Py_None) {
  1217. Py_INCREF(self);
  1218. return self;
  1219. }
  1220. if (gs->prop_get == NULL) {
  1221. PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
  1222. return NULL;
  1223. }
  1224. args = cached_args;
  1225. cached_args = NULL;
  1226. if (!args) {
  1227. args = PyTuple_New(1);
  1228. if (!args)
  1229. return NULL;
  1230. _PyObject_GC_UNTRACK(args);
  1231. }
  1232. Py_INCREF(obj);
  1233. PyTuple_SET_ITEM(args, 0, obj);
  1234. ret = PyObject_Call(gs->prop_get, args, NULL);
  1235. if (cached_args == NULL && Py_REFCNT(args) == 1) {
  1236. assert(Py_SIZE(args) == 1);
  1237. assert(PyTuple_GET_ITEM(args, 0) == obj);
  1238. cached_args = args;
  1239. Py_DECREF(obj);
  1240. }
  1241. else {
  1242. assert(Py_REFCNT(args) >= 1);
  1243. _PyObject_GC_TRACK(args);
  1244. Py_DECREF(args);
  1245. }
  1246. return ret;
  1247. }
  1248. static int
  1249. property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
  1250. {
  1251. propertyobject *gs = (propertyobject *)self;
  1252. PyObject *func, *res;
  1253. if (value == NULL)
  1254. func = gs->prop_del;
  1255. else
  1256. func = gs->prop_set;
  1257. if (func == NULL) {
  1258. PyErr_SetString(PyExc_AttributeError,
  1259. value == NULL ?
  1260. "can't delete attribute" :
  1261. "can't set attribute");
  1262. return -1;
  1263. }
  1264. if (value == NULL)
  1265. res = PyObject_CallFunctionObjArgs(func, obj, NULL);
  1266. else
  1267. res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
  1268. if (res == NULL)
  1269. return -1;
  1270. Py_DECREF(res);
  1271. return 0;
  1272. }
  1273. static PyObject *
  1274. property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
  1275. {
  1276. propertyobject *pold = (propertyobject *)old;
  1277. PyObject *new, *type, *doc;
  1278. type = PyObject_Type(old);
  1279. if (type == NULL)
  1280. return NULL;
  1281. if (get == NULL || get == Py_None) {
  1282. Py_XDECREF(get);
  1283. get = pold->prop_get ? pold->prop_get : Py_None;
  1284. }
  1285. if (set == NULL || set == Py_None) {
  1286. Py_XDECREF(set);
  1287. set = pold->prop_set ? pold->prop_set : Py_None;
  1288. }
  1289. if (del == NULL || del == Py_None) {
  1290. Py_XDECREF(del);
  1291. del = pold->prop_del ? pold->prop_del : Py_None;
  1292. }
  1293. if (pold->getter_doc && get != Py_None) {
  1294. /* make _init use __doc__ from getter */
  1295. doc = Py_None;
  1296. }
  1297. else {
  1298. doc = pold->prop_doc ? pold->prop_doc : Py_None;
  1299. }
  1300. new = PyObject_CallFunction(type, "OOOO", get, set, del, doc);
  1301. Py_DECREF(type);
  1302. if (new == NULL)
  1303. return NULL;
  1304. return new;
  1305. }
  1306. static int
  1307. property_init(PyObject *self, PyObject *args, PyObject *kwds)
  1308. {
  1309. PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
  1310. static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
  1311. propertyobject *prop = (propertyobject *)self;
  1312. if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
  1313. kwlist, &get, &set, &del, &doc))
  1314. return -1;
  1315. if (get == Py_None)
  1316. get = NULL;
  1317. if (set == Py_None)
  1318. set = NULL;
  1319. if (del == Py_None)
  1320. del = NULL;
  1321. Py_XINCREF(get);
  1322. Py_XINCREF(set);
  1323. Py_XINCREF(del);
  1324. Py_XINCREF(doc);
  1325. prop->prop_get = get;
  1326. prop->prop_set = set;
  1327. prop->prop_del = del;
  1328. prop->prop_doc = doc;
  1329. prop->getter_doc = 0;
  1330. /* if no docstring given and the getter has one, use that one */
  1331. if ((doc == NULL || doc == Py_None) && get != NULL) {
  1332. _Py_IDENTIFIER(__doc__);
  1333. PyObject *get_doc = _PyObject_GetAttrId(get, &PyId___doc__);
  1334. if (get_doc) {
  1335. if (Py_TYPE(self) == &PyProperty_Type) {
  1336. Py_XSETREF(prop->prop_doc, get_doc);
  1337. }
  1338. else {
  1339. /* If this is a property subclass, put __doc__
  1340. in dict of the subclass instance instead,
  1341. otherwise it gets shadowed by __doc__ in the
  1342. class's dict. */
  1343. int err = _PyObject_SetAttrId(self, &PyId___doc__, get_doc);
  1344. Py_DECREF(get_doc);
  1345. if (err < 0)
  1346. return -1;
  1347. }
  1348. prop->getter_doc = 1;
  1349. }
  1350. else if (PyErr_ExceptionMatches(PyExc_Exception)) {
  1351. PyErr_Clear();
  1352. }
  1353. else {
  1354. return -1;
  1355. }
  1356. }
  1357. return 0;
  1358. }
  1359. static PyObject *
  1360. property_get___isabstractmethod__(propertyobject *prop, void *closure)
  1361. {
  1362. int res = _PyObject_IsAbstract(prop->prop_get);
  1363. if (res == -1) {
  1364. return NULL;
  1365. }
  1366. else if (res) {
  1367. Py_RETURN_TRUE;
  1368. }
  1369. res = _PyObject_IsAbstract(prop->prop_set);
  1370. if (res == -1) {
  1371. return NULL;
  1372. }
  1373. else if (res) {
  1374. Py_RETURN_TRUE;
  1375. }
  1376. res = _PyObject_IsAbstract(prop->prop_del);
  1377. if (res == -1) {
  1378. return NULL;
  1379. }
  1380. else if (res) {
  1381. Py_RETURN_TRUE;
  1382. }
  1383. Py_RETURN_FALSE;
  1384. }
  1385. static PyGetSetDef property_getsetlist[] = {
  1386. {"__isabstractmethod__",
  1387. (getter)property_get___isabstractmethod__, NULL,
  1388. NULL,
  1389. NULL},
  1390. {NULL} /* Sentinel */
  1391. };
  1392. PyDoc_STRVAR(property_doc,
  1393. "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"
  1394. "\n"
  1395. "fget is a function to be used for getting an attribute value, and likewise\n"
  1396. "fset is a function for setting, and fdel a function for del'ing, an\n"
  1397. "attribute. Typical use is to define a managed attribute x:\n\n"
  1398. "class C(object):\n"
  1399. " def getx(self): return self._x\n"
  1400. " def setx(self, value): self._x = value\n"
  1401. " def delx(self): del self._x\n"
  1402. " x = property(getx, setx, delx, \"I'm the 'x' property.\")\n"
  1403. "\n"
  1404. "Decorators make defining new properties or modifying existing ones easy:\n\n"
  1405. "class C(object):\n"
  1406. " @property\n"
  1407. " def x(self):\n"
  1408. " \"I am the 'x' property.\"\n"
  1409. " return self._x\n"
  1410. " @x.setter\n"
  1411. " def x(self, value):\n"
  1412. " self._x = value\n"
  1413. " @x.deleter\n"
  1414. " def x(self):\n"
  1415. " del self._x\n"
  1416. );
  1417. static int
  1418. property_traverse(PyObject *self, visitproc visit, void *arg)
  1419. {
  1420. propertyobject *pp = (propertyobject *)self;
  1421. Py_VISIT(pp->prop_get);
  1422. Py_VISIT(pp->prop_set);
  1423. Py_VISIT(pp->prop_del);
  1424. Py_VISIT(pp->prop_doc);
  1425. return 0;
  1426. }
  1427. static int
  1428. property_clear(PyObject *self)
  1429. {
  1430. propertyobject *pp = (propertyobject *)self;
  1431. Py_CLEAR(pp->prop_doc);
  1432. return 0;
  1433. }
  1434. PyTypeObject PyProperty_Type = {
  1435. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  1436. "property", /* tp_name */
  1437. sizeof(propertyobject), /* tp_basicsize */
  1438. 0, /* tp_itemsize */
  1439. /* methods */
  1440. property_dealloc, /* tp_dealloc */
  1441. 0, /* tp_print */
  1442. 0, /* tp_getattr */
  1443. 0, /* tp_setattr */
  1444. 0, /* tp_reserved */
  1445. 0, /* tp_repr */
  1446. 0, /* tp_as_number */
  1447. 0, /* tp_as_sequence */
  1448. 0, /* tp_as_mapping */
  1449. 0, /* tp_hash */
  1450. 0, /* tp_call */
  1451. 0, /* tp_str */
  1452. PyObject_GenericGetAttr, /* tp_getattro */
  1453. 0, /* tp_setattro */
  1454. 0, /* tp_as_buffer */
  1455. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
  1456. Py_TPFLAGS_BASETYPE, /* tp_flags */
  1457. property_doc, /* tp_doc */
  1458. property_traverse, /* tp_traverse */
  1459. (inquiry)property_clear, /* tp_clear */
  1460. 0, /* tp_richcompare */
  1461. 0, /* tp_weaklistoffset */
  1462. 0, /* tp_iter */
  1463. 0, /* tp_iternext */
  1464. property_methods, /* tp_methods */
  1465. property_members, /* tp_members */
  1466. property_getsetlist, /* tp_getset */
  1467. 0, /* tp_base */
  1468. 0, /* tp_dict */
  1469. property_descr_get, /* tp_descr_get */
  1470. property_descr_set, /* tp_descr_set */
  1471. 0, /* tp_dictoffset */
  1472. property_init, /* tp_init */
  1473. PyType_GenericAlloc, /* tp_alloc */
  1474. PyType_GenericNew, /* tp_new */
  1475. PyObject_GC_Del, /* tp_free */
  1476. };