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