PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/Objects/descrobject.c

https://gitlab.com/unofficial-mirrors/cpython
C | 1491 lines | 1269 code | 169 blank | 53 comment | 150 complexity | 2362ba6609b2962d5fc978b9e2324825 MD5 | raw file
  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 *kwargs)
  189. {
  190. Py_ssize_t nargs;
  191. PyObject *self, *result;
  192. /* Make sure that the first argument is acceptable as 'self' */
  193. assert(PyTuple_Check(args));
  194. nargs = PyTuple_GET_SIZE(args);
  195. if (nargs < 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. result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
  216. &PyTuple_GET_ITEM(args, 1), nargs - 1,
  217. kwargs);
  218. result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
  219. return result;
  220. }
  221. // same to methoddescr_call(), but use FASTCALL convention.
  222. PyObject *
  223. _PyMethodDescr_FastCallKeywords(PyObject *descrobj,
  224. PyObject **args, Py_ssize_t nargs,
  225. PyObject *kwnames)
  226. {
  227. assert(Py_TYPE(descrobj) == &PyMethodDescr_Type);
  228. PyMethodDescrObject *descr = (PyMethodDescrObject *)descrobj;
  229. PyObject *self, *result;
  230. /* Make sure that the first argument is acceptable as 'self' */
  231. if (nargs < 1) {
  232. PyErr_Format(PyExc_TypeError,
  233. "descriptor '%V' of '%.100s' "
  234. "object needs an argument",
  235. descr_name((PyDescrObject *)descr), "?",
  236. PyDescr_TYPE(descr)->tp_name);
  237. return NULL;
  238. }
  239. self = args[0];
  240. if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
  241. (PyObject *)PyDescr_TYPE(descr))) {
  242. PyErr_Format(PyExc_TypeError,
  243. "descriptor '%V' "
  244. "requires a '%.100s' object "
  245. "but received a '%.100s'",
  246. descr_name((PyDescrObject *)descr), "?",
  247. PyDescr_TYPE(descr)->tp_name,
  248. self->ob_type->tp_name);
  249. return NULL;
  250. }
  251. result = _PyMethodDef_RawFastCallKeywords(descr->d_method, self,
  252. args+1, nargs-1, kwnames);
  253. result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
  254. return result;
  255. }
  256. static PyObject *
  257. classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
  258. PyObject *kwds)
  259. {
  260. Py_ssize_t argc;
  261. PyObject *self, *func, *result, **stack;
  262. /* Make sure that the first argument is acceptable as 'self' */
  263. assert(PyTuple_Check(args));
  264. argc = PyTuple_GET_SIZE(args);
  265. if (argc < 1) {
  266. PyErr_Format(PyExc_TypeError,
  267. "descriptor '%V' of '%.100s' "
  268. "object needs an argument",
  269. descr_name((PyDescrObject *)descr), "?",
  270. PyDescr_TYPE(descr)->tp_name);
  271. return NULL;
  272. }
  273. self = PyTuple_GET_ITEM(args, 0);
  274. if (!PyType_Check(self)) {
  275. PyErr_Format(PyExc_TypeError,
  276. "descriptor '%V' requires a type "
  277. "but received a '%.100s'",
  278. descr_name((PyDescrObject *)descr), "?",
  279. PyDescr_TYPE(descr)->tp_name,
  280. self->ob_type->tp_name);
  281. return NULL;
  282. }
  283. if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
  284. PyErr_Format(PyExc_TypeError,
  285. "descriptor '%V' "
  286. "requires a subtype of '%.100s' "
  287. "but received '%.100s",
  288. descr_name((PyDescrObject *)descr), "?",
  289. PyDescr_TYPE(descr)->tp_name,
  290. self->ob_type->tp_name);
  291. return NULL;
  292. }
  293. func = PyCFunction_NewEx(descr->d_method, self, NULL);
  294. if (func == NULL)
  295. return NULL;
  296. stack = &PyTuple_GET_ITEM(args, 1);
  297. result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
  298. Py_DECREF(func);
  299. return result;
  300. }
  301. static PyObject *
  302. wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
  303. {
  304. Py_ssize_t argc;
  305. PyObject *self, *func, *result, **stack;
  306. /* Make sure that the first argument is acceptable as 'self' */
  307. assert(PyTuple_Check(args));
  308. argc = PyTuple_GET_SIZE(args);
  309. if (argc < 1) {
  310. PyErr_Format(PyExc_TypeError,
  311. "descriptor '%V' of '%.100s' "
  312. "object needs an argument",
  313. descr_name((PyDescrObject *)descr), "?",
  314. PyDescr_TYPE(descr)->tp_name);
  315. return NULL;
  316. }
  317. self = PyTuple_GET_ITEM(args, 0);
  318. if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
  319. (PyObject *)PyDescr_TYPE(descr))) {
  320. PyErr_Format(PyExc_TypeError,
  321. "descriptor '%V' "
  322. "requires a '%.100s' object "
  323. "but received a '%.100s'",
  324. descr_name((PyDescrObject *)descr), "?",
  325. PyDescr_TYPE(descr)->tp_name,
  326. self->ob_type->tp_name);
  327. return NULL;
  328. }
  329. func = PyWrapper_New((PyObject *)descr, self);
  330. if (func == NULL)
  331. return NULL;
  332. stack = &PyTuple_GET_ITEM(args, 1);
  333. result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
  334. Py_DECREF(func);
  335. return result;
  336. }
  337. static PyObject *
  338. method_get_doc(PyMethodDescrObject *descr, void *closure)
  339. {
  340. return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
  341. }
  342. static PyObject *
  343. method_get_text_signature(PyMethodDescrObject *descr, void *closure)
  344. {
  345. return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
  346. }
  347. static PyObject *
  348. calculate_qualname(PyDescrObject *descr)
  349. {
  350. PyObject *type_qualname, *res;
  351. _Py_IDENTIFIER(__qualname__);
  352. if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
  353. PyErr_SetString(PyExc_TypeError,
  354. "<descriptor>.__name__ is not a unicode object");
  355. return NULL;
  356. }
  357. type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
  358. &PyId___qualname__);
  359. if (type_qualname == NULL)
  360. return NULL;
  361. if (!PyUnicode_Check(type_qualname)) {
  362. PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
  363. "__qualname__ is not a unicode object");
  364. Py_XDECREF(type_qualname);
  365. return NULL;
  366. }
  367. res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
  368. Py_DECREF(type_qualname);
  369. return res;
  370. }
  371. static PyObject *
  372. descr_get_qualname(PyDescrObject *descr)
  373. {
  374. if (descr->d_qualname == NULL)
  375. descr->d_qualname = calculate_qualname(descr);
  376. Py_XINCREF(descr->d_qualname);
  377. return descr->d_qualname;
  378. }
  379. static PyObject *
  380. descr_reduce(PyDescrObject *descr)
  381. {
  382. PyObject *builtins;
  383. PyObject *getattr;
  384. _Py_IDENTIFIER(getattr);
  385. builtins = PyEval_GetBuiltins();
  386. getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
  387. return Py_BuildValue("O(OO)", getattr, PyDescr_TYPE(descr),
  388. PyDescr_NAME(descr));
  389. }
  390. static PyMethodDef descr_methods[] = {
  391. {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
  392. {NULL, NULL}
  393. };
  394. static PyMemberDef descr_members[] = {
  395. {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
  396. {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
  397. {0}
  398. };
  399. static PyGetSetDef method_getset[] = {
  400. {"__doc__", (getter)method_get_doc},
  401. {"__qualname__", (getter)descr_get_qualname},
  402. {"__text_signature__", (getter)method_get_text_signature},
  403. {0}
  404. };
  405. static PyObject *
  406. member_get_doc(PyMemberDescrObject *descr, void *closure)
  407. {
  408. if (descr->d_member->doc == NULL) {
  409. Py_RETURN_NONE;
  410. }
  411. return PyUnicode_FromString(descr->d_member->doc);
  412. }
  413. static PyGetSetDef member_getset[] = {
  414. {"__doc__", (getter)member_get_doc},
  415. {"__qualname__", (getter)descr_get_qualname},
  416. {0}
  417. };
  418. static PyObject *
  419. getset_get_doc(PyGetSetDescrObject *descr, void *closure)
  420. {
  421. if (descr->d_getset->doc == NULL) {
  422. Py_RETURN_NONE;
  423. }
  424. return PyUnicode_FromString(descr->d_getset->doc);
  425. }
  426. static PyGetSetDef getset_getset[] = {
  427. {"__doc__", (getter)getset_get_doc},
  428. {"__qualname__", (getter)descr_get_qualname},
  429. {0}
  430. };
  431. static PyObject *
  432. wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
  433. {
  434. return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
  435. }
  436. static PyObject *
  437. wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
  438. {
  439. return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
  440. }
  441. static PyGetSetDef wrapperdescr_getset[] = {
  442. {"__doc__", (getter)wrapperdescr_get_doc},
  443. {"__qualname__", (getter)descr_get_qualname},
  444. {"__text_signature__", (getter)wrapperdescr_get_text_signature},
  445. {0}
  446. };
  447. static int
  448. descr_traverse(PyObject *self, visitproc visit, void *arg)
  449. {
  450. PyDescrObject *descr = (PyDescrObject *)self;
  451. Py_VISIT(descr->d_type);
  452. return 0;
  453. }
  454. PyTypeObject PyMethodDescr_Type = {
  455. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  456. "method_descriptor",
  457. sizeof(PyMethodDescrObject),
  458. 0,
  459. (destructor)descr_dealloc, /* tp_dealloc */
  460. 0, /* tp_print */
  461. 0, /* tp_getattr */
  462. 0, /* tp_setattr */
  463. 0, /* tp_reserved */
  464. (reprfunc)method_repr, /* tp_repr */
  465. 0, /* tp_as_number */
  466. 0, /* tp_as_sequence */
  467. 0, /* tp_as_mapping */
  468. 0, /* tp_hash */
  469. (ternaryfunc)methoddescr_call, /* tp_call */
  470. 0, /* tp_str */
  471. PyObject_GenericGetAttr, /* tp_getattro */
  472. 0, /* tp_setattro */
  473. 0, /* tp_as_buffer */
  474. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  475. 0, /* tp_doc */
  476. descr_traverse, /* tp_traverse */
  477. 0, /* tp_clear */
  478. 0, /* tp_richcompare */
  479. 0, /* tp_weaklistoffset */
  480. 0, /* tp_iter */
  481. 0, /* tp_iternext */
  482. descr_methods, /* tp_methods */
  483. descr_members, /* tp_members */
  484. method_getset, /* tp_getset */
  485. 0, /* tp_base */
  486. 0, /* tp_dict */
  487. (descrgetfunc)method_get, /* tp_descr_get */
  488. 0, /* tp_descr_set */
  489. };
  490. /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
  491. PyTypeObject PyClassMethodDescr_Type = {
  492. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  493. "classmethod_descriptor",
  494. sizeof(PyMethodDescrObject),
  495. 0,
  496. (destructor)descr_dealloc, /* tp_dealloc */
  497. 0, /* tp_print */
  498. 0, /* tp_getattr */
  499. 0, /* tp_setattr */
  500. 0, /* tp_reserved */
  501. (reprfunc)method_repr, /* tp_repr */
  502. 0, /* tp_as_number */
  503. 0, /* tp_as_sequence */
  504. 0, /* tp_as_mapping */
  505. 0, /* tp_hash */
  506. (ternaryfunc)classmethoddescr_call, /* tp_call */
  507. 0, /* tp_str */
  508. PyObject_GenericGetAttr, /* tp_getattro */
  509. 0, /* tp_setattro */
  510. 0, /* tp_as_buffer */
  511. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  512. 0, /* tp_doc */
  513. descr_traverse, /* tp_traverse */
  514. 0, /* tp_clear */
  515. 0, /* tp_richcompare */
  516. 0, /* tp_weaklistoffset */
  517. 0, /* tp_iter */
  518. 0, /* tp_iternext */
  519. descr_methods, /* tp_methods */
  520. descr_members, /* tp_members */
  521. method_getset, /* tp_getset */
  522. 0, /* tp_base */
  523. 0, /* tp_dict */
  524. (descrgetfunc)classmethod_get, /* tp_descr_get */
  525. 0, /* tp_descr_set */
  526. };
  527. PyTypeObject PyMemberDescr_Type = {
  528. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  529. "member_descriptor",
  530. sizeof(PyMemberDescrObject),
  531. 0,
  532. (destructor)descr_dealloc, /* tp_dealloc */
  533. 0, /* tp_print */
  534. 0, /* tp_getattr */
  535. 0, /* tp_setattr */
  536. 0, /* tp_reserved */
  537. (reprfunc)member_repr, /* tp_repr */
  538. 0, /* tp_as_number */
  539. 0, /* tp_as_sequence */
  540. 0, /* tp_as_mapping */
  541. 0, /* tp_hash */
  542. 0, /* tp_call */
  543. 0, /* tp_str */
  544. PyObject_GenericGetAttr, /* tp_getattro */
  545. 0, /* tp_setattro */
  546. 0, /* tp_as_buffer */
  547. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  548. 0, /* tp_doc */
  549. descr_traverse, /* tp_traverse */
  550. 0, /* tp_clear */
  551. 0, /* tp_richcompare */
  552. 0, /* tp_weaklistoffset */
  553. 0, /* tp_iter */
  554. 0, /* tp_iternext */
  555. descr_methods, /* tp_methods */
  556. descr_members, /* tp_members */
  557. member_getset, /* tp_getset */
  558. 0, /* tp_base */
  559. 0, /* tp_dict */
  560. (descrgetfunc)member_get, /* tp_descr_get */
  561. (descrsetfunc)member_set, /* tp_descr_set */
  562. };
  563. PyTypeObject PyGetSetDescr_Type = {
  564. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  565. "getset_descriptor",
  566. sizeof(PyGetSetDescrObject),
  567. 0,
  568. (destructor)descr_dealloc, /* tp_dealloc */
  569. 0, /* tp_print */
  570. 0, /* tp_getattr */
  571. 0, /* tp_setattr */
  572. 0, /* tp_reserved */
  573. (reprfunc)getset_repr, /* tp_repr */
  574. 0, /* tp_as_number */
  575. 0, /* tp_as_sequence */
  576. 0, /* tp_as_mapping */
  577. 0, /* tp_hash */
  578. 0, /* tp_call */
  579. 0, /* tp_str */
  580. PyObject_GenericGetAttr, /* tp_getattro */
  581. 0, /* tp_setattro */
  582. 0, /* tp_as_buffer */
  583. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  584. 0, /* tp_doc */
  585. descr_traverse, /* tp_traverse */
  586. 0, /* tp_clear */
  587. 0, /* tp_richcompare */
  588. 0, /* tp_weaklistoffset */
  589. 0, /* tp_iter */
  590. 0, /* tp_iternext */
  591. 0, /* tp_methods */
  592. descr_members, /* tp_members */
  593. getset_getset, /* tp_getset */
  594. 0, /* tp_base */
  595. 0, /* tp_dict */
  596. (descrgetfunc)getset_get, /* tp_descr_get */
  597. (descrsetfunc)getset_set, /* tp_descr_set */
  598. };
  599. PyTypeObject PyWrapperDescr_Type = {
  600. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  601. "wrapper_descriptor",
  602. sizeof(PyWrapperDescrObject),
  603. 0,
  604. (destructor)descr_dealloc, /* tp_dealloc */
  605. 0, /* tp_print */
  606. 0, /* tp_getattr */
  607. 0, /* tp_setattr */
  608. 0, /* tp_reserved */
  609. (reprfunc)wrapperdescr_repr, /* tp_repr */
  610. 0, /* tp_as_number */
  611. 0, /* tp_as_sequence */
  612. 0, /* tp_as_mapping */
  613. 0, /* tp_hash */
  614. (ternaryfunc)wrapperdescr_call, /* tp_call */
  615. 0, /* tp_str */
  616. PyObject_GenericGetAttr, /* tp_getattro */
  617. 0, /* tp_setattro */
  618. 0, /* tp_as_buffer */
  619. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  620. 0, /* tp_doc */
  621. descr_traverse, /* tp_traverse */
  622. 0, /* tp_clear */
  623. 0, /* tp_richcompare */
  624. 0, /* tp_weaklistoffset */
  625. 0, /* tp_iter */
  626. 0, /* tp_iternext */
  627. descr_methods, /* tp_methods */
  628. descr_members, /* tp_members */
  629. wrapperdescr_getset, /* tp_getset */
  630. 0, /* tp_base */
  631. 0, /* tp_dict */
  632. (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
  633. 0, /* tp_descr_set */
  634. };
  635. static PyDescrObject *
  636. descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
  637. {
  638. PyDescrObject *descr;
  639. descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
  640. if (descr != NULL) {
  641. Py_XINCREF(type);
  642. descr->d_type = type;
  643. descr->d_name = PyUnicode_InternFromString(name);
  644. if (descr->d_name == NULL) {
  645. Py_DECREF(descr);
  646. descr = NULL;
  647. }
  648. else {
  649. descr->d_qualname = NULL;
  650. }
  651. }
  652. return descr;
  653. }
  654. PyObject *
  655. PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
  656. {
  657. PyMethodDescrObject *descr;
  658. descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
  659. type, method->ml_name);
  660. if (descr != NULL)
  661. descr->d_method = method;
  662. return (PyObject *)descr;
  663. }
  664. PyObject *
  665. PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
  666. {
  667. PyMethodDescrObject *descr;
  668. descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
  669. type, method->ml_name);
  670. if (descr != NULL)
  671. descr->d_method = method;
  672. return (PyObject *)descr;
  673. }
  674. PyObject *
  675. PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
  676. {
  677. PyMemberDescrObject *descr;
  678. descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
  679. type, member->name);
  680. if (descr != NULL)
  681. descr->d_member = member;
  682. return (PyObject *)descr;
  683. }
  684. PyObject *
  685. PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
  686. {
  687. PyGetSetDescrObject *descr;
  688. descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
  689. type, getset->name);
  690. if (descr != NULL)
  691. descr->d_getset = getset;
  692. return (PyObject *)descr;
  693. }
  694. PyObject *
  695. PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
  696. {
  697. PyWrapperDescrObject *descr;
  698. descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
  699. type, base->name);
  700. if (descr != NULL) {
  701. descr->d_base = base;
  702. descr->d_wrapped = wrapped;
  703. }
  704. return (PyObject *)descr;
  705. }
  706. /* --- mappingproxy: read-only proxy for mappings --- */
  707. /* This has no reason to be in this file except that adding new files is a
  708. bit of a pain */
  709. typedef struct {
  710. PyObject_HEAD
  711. PyObject *mapping;
  712. } mappingproxyobject;
  713. static Py_ssize_t
  714. mappingproxy_len(mappingproxyobject *pp)
  715. {
  716. return PyObject_Size(pp->mapping);
  717. }
  718. static PyObject *
  719. mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
  720. {
  721. return PyObject_GetItem(pp->mapping, key);
  722. }
  723. static PyMappingMethods mappingproxy_as_mapping = {
  724. (lenfunc)mappingproxy_len, /* mp_length */
  725. (binaryfunc)mappingproxy_getitem, /* mp_subscript */
  726. 0, /* mp_ass_subscript */
  727. };
  728. static int
  729. mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
  730. {
  731. if (PyDict_CheckExact(pp->mapping))
  732. return PyDict_Contains(pp->mapping, key);
  733. else
  734. return PySequence_Contains(pp->mapping, key);
  735. }
  736. static PySequenceMethods mappingproxy_as_sequence = {
  737. 0, /* sq_length */
  738. 0, /* sq_concat */
  739. 0, /* sq_repeat */
  740. 0, /* sq_item */
  741. 0, /* sq_slice */
  742. 0, /* sq_ass_item */
  743. 0, /* sq_ass_slice */
  744. (objobjproc)mappingproxy_contains, /* sq_contains */
  745. 0, /* sq_inplace_concat */
  746. 0, /* sq_inplace_repeat */
  747. };
  748. static PyObject *
  749. mappingproxy_get(mappingproxyobject *pp, PyObject *args)
  750. {
  751. PyObject *key, *def = Py_None;
  752. _Py_IDENTIFIER(get);
  753. if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
  754. return NULL;
  755. return _PyObject_CallMethodIdObjArgs(pp->mapping, &PyId_get,
  756. key, def, NULL);
  757. }
  758. static PyObject *
  759. mappingproxy_keys(mappingproxyobject *pp)
  760. {
  761. _Py_IDENTIFIER(keys);
  762. return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL);
  763. }
  764. static PyObject *
  765. mappingproxy_values(mappingproxyobject *pp)
  766. {
  767. _Py_IDENTIFIER(values);
  768. return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL);
  769. }
  770. static PyObject *
  771. mappingproxy_items(mappingproxyobject *pp)
  772. {
  773. _Py_IDENTIFIER(items);
  774. return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL);
  775. }
  776. static PyObject *
  777. mappingproxy_copy(mappingproxyobject *pp)
  778. {
  779. _Py_IDENTIFIER(copy);
  780. return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL);
  781. }
  782. /* WARNING: mappingproxy methods must not give access
  783. to the underlying mapping */
  784. static PyMethodDef mappingproxy_methods[] = {
  785. {"get", (PyCFunction)mappingproxy_get, METH_VARARGS,
  786. PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
  787. " d defaults to None.")},
  788. {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
  789. PyDoc_STR("D.keys() -> list of D's keys")},
  790. {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
  791. PyDoc_STR("D.values() -> list of D's values")},
  792. {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
  793. PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
  794. {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
  795. PyDoc_STR("D.copy() -> a shallow copy of D")},
  796. {0}
  797. };
  798. static void
  799. mappingproxy_dealloc(mappingproxyobject *pp)
  800. {
  801. _PyObject_GC_UNTRACK(pp);
  802. Py_DECREF(pp->mapping);
  803. PyObject_GC_Del(pp);
  804. }
  805. static PyObject *
  806. mappingproxy_getiter(mappingproxyobject *pp)
  807. {
  808. return PyObject_GetIter(pp->mapping);
  809. }
  810. static PyObject *
  811. mappingproxy_str(mappingproxyobject *pp)
  812. {
  813. return PyObject_Str(pp->mapping);
  814. }
  815. static PyObject *
  816. mappingproxy_repr(mappingproxyobject *pp)
  817. {
  818. return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
  819. }
  820. static int
  821. mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
  822. {
  823. mappingproxyobject *pp = (mappingproxyobject *)self;
  824. Py_VISIT(pp->mapping);
  825. return 0;
  826. }
  827. static PyObject *
  828. mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
  829. {
  830. return PyObject_RichCompare(v->mapping, w, op);
  831. }
  832. static int
  833. mappingproxy_check_mapping(PyObject *mapping)
  834. {
  835. if (!PyMapping_Check(mapping)
  836. || PyList_Check(mapping)
  837. || PyTuple_Check(mapping)) {
  838. PyErr_Format(PyExc_TypeError,
  839. "mappingproxy() argument must be a mapping, not %s",
  840. Py_TYPE(mapping)->tp_name);
  841. return -1;
  842. }
  843. return 0;
  844. }
  845. static PyObject*
  846. mappingproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  847. {
  848. static char *kwlist[] = {"mapping", NULL};
  849. PyObject *mapping;
  850. mappingproxyobject *mappingproxy;
  851. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:mappingproxy",
  852. kwlist, &mapping))
  853. return NULL;
  854. if (mappingproxy_check_mapping(mapping) == -1)
  855. return NULL;
  856. mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
  857. if (mappingproxy == NULL)
  858. return NULL;
  859. Py_INCREF(mapping);
  860. mappingproxy->mapping = mapping;
  861. _PyObject_GC_TRACK(mappingproxy);
  862. return (PyObject *)mappingproxy;
  863. }
  864. PyTypeObject PyDictProxy_Type = {
  865. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  866. "mappingproxy", /* tp_name */
  867. sizeof(mappingproxyobject), /* tp_basicsize */
  868. 0, /* tp_itemsize */
  869. /* methods */
  870. (destructor)mappingproxy_dealloc, /* tp_dealloc */
  871. 0, /* tp_print */
  872. 0, /* tp_getattr */
  873. 0, /* tp_setattr */
  874. 0, /* tp_reserved */
  875. (reprfunc)mappingproxy_repr, /* tp_repr */
  876. 0, /* tp_as_number */
  877. &mappingproxy_as_sequence, /* tp_as_sequence */
  878. &mappingproxy_as_mapping, /* tp_as_mapping */
  879. 0, /* tp_hash */
  880. 0, /* tp_call */
  881. (reprfunc)mappingproxy_str, /* tp_str */
  882. PyObject_GenericGetAttr, /* tp_getattro */
  883. 0, /* tp_setattro */
  884. 0, /* tp_as_buffer */
  885. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  886. 0, /* tp_doc */
  887. mappingproxy_traverse, /* tp_traverse */
  888. 0, /* tp_clear */
  889. (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
  890. 0, /* tp_weaklistoffset */
  891. (getiterfunc)mappingproxy_getiter, /* tp_iter */
  892. 0, /* tp_iternext */
  893. mappingproxy_methods, /* tp_methods */
  894. 0, /* tp_members */
  895. 0, /* tp_getset */
  896. 0, /* tp_base */
  897. 0, /* tp_dict */
  898. 0, /* tp_descr_get */
  899. 0, /* tp_descr_set */
  900. 0, /* tp_dictoffset */
  901. 0, /* tp_init */
  902. 0, /* tp_alloc */
  903. mappingproxy_new, /* tp_new */
  904. };
  905. PyObject *
  906. PyDictProxy_New(PyObject *mapping)
  907. {
  908. mappingproxyobject *pp;
  909. if (mappingproxy_check_mapping(mapping) == -1)
  910. return NULL;
  911. pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
  912. if (pp != NULL) {
  913. Py_INCREF(mapping);
  914. pp->mapping = mapping;
  915. _PyObject_GC_TRACK(pp);
  916. }
  917. return (PyObject *)pp;
  918. }
  919. /* --- Wrapper object for "slot" methods --- */
  920. /* This has no reason to be in this file except that adding new files is a
  921. bit of a pain */
  922. typedef struct {
  923. PyObject_HEAD
  924. PyWrapperDescrObject *descr;
  925. PyObject *self;
  926. } wrapperobject;
  927. #define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
  928. static void
  929. wrapper_dealloc(wrapperobject *wp)
  930. {
  931. PyObject_GC_UnTrack(wp);
  932. Py_TRASHCAN_SAFE_BEGIN(wp)
  933. Py_XDECREF(wp->descr);
  934. Py_XDECREF(wp->self);
  935. PyObject_GC_Del(wp);
  936. Py_TRASHCAN_SAFE_END(wp)
  937. }
  938. #define TEST_COND(cond) ((cond) ? Py_True : Py_False)
  939. static PyObject *
  940. wrapper_richcompare(PyObject *a, PyObject *b, int op)
  941. {
  942. intptr_t result;
  943. PyObject *v;
  944. PyWrapperDescrObject *a_descr, *b_descr;
  945. assert(a != NULL && b != NULL);
  946. /* both arguments should be wrapperobjects */
  947. if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
  948. v = Py_NotImplemented;
  949. Py_INCREF(v);
  950. return v;
  951. }
  952. /* compare by descriptor address; if the descriptors are the same,
  953. compare by the objects they're bound to */
  954. a_descr = ((wrapperobject *)a)->descr;
  955. b_descr = ((wrapperobject *)b)->descr;
  956. if (a_descr == b_descr) {
  957. a = ((wrapperobject *)a)->self;
  958. b = ((wrapperobject *)b)->self;
  959. return PyObject_RichCompare(a, b, op);
  960. }
  961. result = a_descr - b_descr;
  962. switch (op) {
  963. case Py_EQ:
  964. v = TEST_COND(result == 0);
  965. break;
  966. case Py_NE:
  967. v = TEST_COND(result != 0);
  968. break;
  969. case Py_LE:
  970. v = TEST_COND(result <= 0);
  971. break;
  972. case Py_GE:
  973. v = TEST_COND(result >= 0);
  974. break;
  975. case Py_LT:
  976. v = TEST_COND(result < 0);
  977. break;
  978. case Py_GT:
  979. v = TEST_COND(result > 0);
  980. break;
  981. default:
  982. PyErr_BadArgument();
  983. return NULL;
  984. }
  985. Py_INCREF(v);
  986. return v;
  987. }
  988. static Py_hash_t
  989. wrapper_hash(wrapperobject *wp)
  990. {
  991. Py_hash_t x, y;
  992. x = _Py_HashPointer(wp->descr);
  993. if (x == -1)
  994. return -1;
  995. y = PyObject_Hash(wp->self);
  996. if (y == -1)
  997. return -1;
  998. x = x ^ y;
  999. if (x == -1)
  1000. x = -2;
  1001. return x;
  1002. }
  1003. static PyObject *
  1004. wrapper_repr(wrapperobject *wp)
  1005. {
  1006. return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
  1007. wp->descr->d_base->name,
  1008. wp->self->ob_type->tp_name,
  1009. wp->self);
  1010. }
  1011. static PyObject *
  1012. wrapper_reduce(wrapperobject *wp)
  1013. {
  1014. PyObject *builtins;
  1015. PyObject *getattr;
  1016. _Py_IDENTIFIER(getattr);
  1017. builtins = PyEval_GetBuiltins();
  1018. getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
  1019. return Py_BuildValue("O(OO)", getattr, wp->self, PyDescr_NAME(wp->descr));
  1020. }
  1021. static PyMethodDef wrapper_methods[] = {
  1022. {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
  1023. {NULL, NULL}
  1024. };
  1025. static PyMemberDef wrapper_members[] = {
  1026. {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
  1027. {0}
  1028. };
  1029. static PyObject *
  1030. wrapper_objclass(wrapperobject *wp)
  1031. {
  1032. PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
  1033. Py_INCREF(c);
  1034. return c;
  1035. }
  1036. static PyObject *
  1037. wrapper_name(wrapperobject *wp)
  1038. {
  1039. const char *s = wp->descr->d_base->name;
  1040. return PyUnicode_FromString(s);
  1041. }
  1042. static PyObject *
  1043. wrapper_doc(wrapperobject *wp, void *closure)
  1044. {
  1045. return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
  1046. }
  1047. static PyObject *
  1048. wrapper_text_signature(wrapperobject *wp, void *closure)
  1049. {
  1050. return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
  1051. }
  1052. static PyObject *
  1053. wrapper_qualname(wrapperobject *wp)
  1054. {
  1055. return descr_get_qualname((PyDescrObject *)wp->descr);
  1056. }
  1057. static PyGetSetDef wrapper_getsets[] = {
  1058. {"__objclass__", (getter)wrapper_objclass},
  1059. {"__name__", (getter)wrapper_name},
  1060. {"__qualname__", (getter)wrapper_qualname},
  1061. {"__doc__", (getter)wrapper_doc},
  1062. {"__text_signature__", (getter)wrapper_text_signature},
  1063. {0}
  1064. };
  1065. static PyObject *
  1066. wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
  1067. {
  1068. wrapperfunc wrapper = wp->descr->d_base->wrapper;
  1069. PyObject *self = wp->self;
  1070. if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
  1071. wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
  1072. return (*wk)(self, args, wp->descr->d_wrapped, kwds);
  1073. }
  1074. if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
  1075. PyErr_Format(PyExc_TypeError,
  1076. "wrapper %s doesn't take keyword arguments",
  1077. wp->descr->d_base->name);
  1078. return NULL;
  1079. }
  1080. return (*wrapper)(self, args, wp->descr->d_wrapped);
  1081. }
  1082. static int
  1083. wrapper_traverse(PyObject *self, visitproc visit, void *arg)
  1084. {
  1085. wrapperobject *wp = (wrapperobject *)self;
  1086. Py_VISIT(wp->descr);
  1087. Py_VISIT(wp->self);
  1088. return 0;
  1089. }
  1090. PyTypeObject _PyMethodWrapper_Type = {
  1091. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  1092. "method-wrapper", /* tp_name */
  1093. sizeof(wrapperobject), /* tp_basicsize */
  1094. 0, /* tp_itemsize */
  1095. /* methods */
  1096. (destructor)wrapper_dealloc, /* tp_dealloc */
  1097. 0, /* tp_print */
  1098. 0, /* tp_getattr */
  1099. 0, /* tp_setattr */
  1100. 0, /* tp_reserved */
  1101. (reprfunc)wrapper_repr, /* tp_repr */
  1102. 0, /* tp_as_number */
  1103. 0, /* tp_as_sequence */
  1104. 0, /* tp_as_mapping */
  1105. (hashfunc)wrapper_hash, /* tp_hash */
  1106. (ternaryfunc)wrapper_call, /* tp_call */
  1107. 0, /* tp_str */
  1108. PyObject_GenericGetAttr, /* tp_getattro */
  1109. 0, /* tp_setattro */
  1110. 0, /* tp_as_buffer */
  1111. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  1112. 0, /* tp_doc */
  1113. wrapper_traverse, /* tp_traverse */
  1114. 0, /* tp_clear */
  1115. wrapper_richcompare, /* tp_richcompare */
  1116. 0, /* tp_weaklistoffset */
  1117. 0, /* tp_iter */
  1118. 0, /* tp_iternext */
  1119. wrapper_methods, /* tp_methods */
  1120. wrapper_members, /* tp_members */
  1121. wrapper_getsets, /* tp_getset */
  1122. 0, /* tp_base */
  1123. 0, /* tp_dict */
  1124. 0, /* tp_descr_get */
  1125. 0, /* tp_descr_set */
  1126. };
  1127. PyObject *
  1128. PyWrapper_New(PyObject *d, PyObject *self)
  1129. {
  1130. wrapperobject *wp;
  1131. PyWrapperDescrObject *descr;
  1132. assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
  1133. descr = (PyWrapperDescrObject *)d;
  1134. assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
  1135. (PyObject *)PyDescr_TYPE(descr)));
  1136. wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
  1137. if (wp != NULL) {
  1138. Py_INCREF(descr);
  1139. wp->descr = descr;
  1140. Py_INCREF(self);
  1141. wp->self = self;
  1142. _PyObject_GC_TRACK(wp);
  1143. }
  1144. return (PyObject *)wp;
  1145. }
  1146. /* A built-in 'property' type */
  1147. /*
  1148. class property(object):
  1149. def __init__(self, fget=None, fset=None, fdel=None, doc=None):
  1150. if doc is None and fget is not None and hasattr(fget, "__doc__"):
  1151. doc = fget.__doc__
  1152. self.__get = fget
  1153. self.__set = fset
  1154. self.__del = fdel
  1155. self.__doc__ = doc
  1156. def __get__(self, inst, type=None):
  1157. if inst is None:
  1158. return self
  1159. if self.__get is None:
  1160. raise AttributeError, "unreadable attribute"
  1161. return self.__get(inst)
  1162. def __set__(self, inst, value):
  1163. if self.__set is None:
  1164. raise AttributeError, "can't set attribute"
  1165. return self.__set(inst, value)
  1166. def __delete__(self, inst):
  1167. if self.__del is None:
  1168. raise AttributeError, "can't delete attribute"
  1169. return self.__del(inst)
  1170. */
  1171. typedef struct {
  1172. PyObject_HEAD
  1173. PyObject *prop_get;
  1174. PyObject *prop_set;
  1175. PyObject *prop_del;
  1176. PyObject *prop_doc;
  1177. int getter_doc;
  1178. } propertyobject;
  1179. static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
  1180. PyObject *);
  1181. static PyMemberDef property_members[] = {
  1182. {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
  1183. {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
  1184. {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
  1185. {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
  1186. {0}
  1187. };
  1188. PyDoc_STRVAR(getter_doc,
  1189. "Descriptor to change the getter on a property.");
  1190. static PyObject *
  1191. property_getter(PyObject *self, PyObject *getter)
  1192. {
  1193. return property_copy(self, getter, NULL, NULL);
  1194. }
  1195. PyDoc_STRVAR(setter_doc,
  1196. "Descriptor to change the setter on a property.");
  1197. static PyObject *
  1198. property_setter(PyObject *self, PyObject *setter)
  1199. {
  1200. return property_copy(self, NULL, setter, NULL);
  1201. }
  1202. PyDoc_STRVAR(deleter_doc,
  1203. "Descriptor to change the deleter on a property.");
  1204. static PyObject *
  1205. property_deleter(PyObject *self, PyObject *deleter)
  1206. {
  1207. return property_copy(self, NULL, NULL, deleter);
  1208. }
  1209. static PyMethodDef property_methods[] = {
  1210. {"getter", property_getter, METH_O, getter_doc},
  1211. {"setter", property_setter, METH_O, setter_doc},
  1212. {"deleter", property_deleter, METH_O, deleter_doc},
  1213. {0}
  1214. };
  1215. static void
  1216. property_dealloc(PyObject *self)
  1217. {
  1218. propertyobject *gs = (propertyobject *)self;
  1219. _PyObject_GC_UNTRACK(self);
  1220. Py_XDECREF(gs->prop_get);
  1221. Py_XDECREF(gs->prop_set);
  1222. Py_XDECREF(gs->prop_del);
  1223. Py_XDECREF(gs->prop_doc);
  1224. self->ob_type->tp_free(self);
  1225. }
  1226. static PyObject *
  1227. property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
  1228. {
  1229. static PyObject * volatile cached_args = NULL;
  1230. PyObject *args;
  1231. PyObject *ret;
  1232. propertyobject *gs = (propertyobject *)self;
  1233. if (obj == NULL || obj == Py_None) {
  1234. Py_INCREF(self);
  1235. return self;
  1236. }
  1237. if (gs->prop_get == NULL) {
  1238. PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
  1239. return NULL;
  1240. }
  1241. args = cached_args;
  1242. cached_args = NULL;
  1243. if (!args) {
  1244. args = PyTuple_New(1);
  1245. if (!args)
  1246. return NULL;
  1247. _PyObject_GC_UNTRACK(args);
  1248. }
  1249. Py_INCREF(obj);
  1250. PyTuple_SET_ITEM(args, 0, obj);
  1251. ret = PyObject_Call(gs->prop_get, args, NULL);
  1252. if (cached_args == NULL && Py_REFCNT(args) == 1) {
  1253. assert(Py_SIZE(args) == 1);
  1254. assert(PyTuple_GET_ITEM(args, 0) == obj);
  1255. cached_args = args;
  1256. Py_DECREF(obj);
  1257. }
  1258. else {
  1259. assert(Py_REFCNT(args) >= 1);
  1260. _PyObject_GC_TRACK(args);
  1261. Py_DECREF(args);
  1262. }
  1263. return ret;
  1264. }
  1265. static int
  1266. property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
  1267. {
  1268. propertyobject *gs = (propertyobject *)self;
  1269. PyObject *func, *res;
  1270. if (value == NULL)
  1271. func = gs->prop_del;
  1272. else
  1273. func = gs->prop_set;
  1274. if (func == NULL) {
  1275. PyErr_SetString(PyExc_AttributeError,
  1276. value == NULL ?
  1277. "can't delete attribute" :
  1278. "can't set attribute");
  1279. return -1;
  1280. }
  1281. if (value == NULL)
  1282. res = PyObject_CallFunctionObjArgs(func, obj, NULL);
  1283. else
  1284. res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
  1285. if (res == NULL)
  1286. return -1;
  1287. Py_DECREF(res);
  1288. return 0;
  1289. }
  1290. static PyObject *
  1291. property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
  1292. {
  1293. propertyobject *pold = (propertyobject *)old;
  1294. PyObject *new, *type, *doc;
  1295. type = PyObject_Type(old);
  1296. if (type == NULL)
  1297. return NULL;
  1298. if (get == NULL || get == Py_None) {
  1299. Py_XDECREF(get);
  1300. get = pold->prop_get ? pold->prop_get : Py_None;
  1301. }
  1302. if (set == NULL || set == Py_None) {
  1303. Py_XDECREF(set);
  1304. set = pold->prop_set ? pold->prop_set : Py_None;
  1305. }
  1306. if (del == NULL || del == Py_None) {
  1307. Py_XDECREF(del);
  1308. del = pold->prop_del ? pold->prop_del : Py_None;
  1309. }
  1310. if (pold->getter_doc && get != Py_None) {
  1311. /* make _init use __doc__ from getter */
  1312. doc = Py_None;
  1313. }
  1314. else {
  1315. doc = pold->prop_doc ? pold->prop_doc : Py_None;
  1316. }
  1317. new = PyObj