diff options
Diffstat (limited to 'Objects/descrobject.c')
| -rw-r--r-- | Objects/descrobject.c | 293 |
1 files changed, 148 insertions, 145 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 7bf1859..9934f23 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -12,48 +12,50 @@ descr_dealloc(PyDescrObject *descr) PyObject_GC_Del(descr); } -static char * +static PyObject * descr_name(PyDescrObject *descr) { - if (descr->d_name != NULL && PyString_Check(descr->d_name)) - return PyString_AS_STRING(descr->d_name); - else - return "?"; + if (descr->d_name != NULL && PyUnicode_Check(descr->d_name)) + return descr->d_name; + return NULL; } static PyObject * descr_repr(PyDescrObject *descr, char *format) { - return PyString_FromFormat(format, descr_name(descr), - descr->d_type->tp_name); + PyObject *name = NULL; + if (descr->d_name != NULL && PyUnicode_Check(descr->d_name)) + name = descr->d_name; + + return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name); } static PyObject * method_repr(PyMethodDescrObject *descr) { return descr_repr((PyDescrObject *)descr, - "<method '%s' of '%s' objects>"); + "<method '%V' of '%s' objects>"); } static PyObject * member_repr(PyMemberDescrObject *descr) { return descr_repr((PyDescrObject *)descr, - "<member '%s' of '%s' objects>"); + "<member '%V' of '%s' objects>"); } static PyObject * getset_repr(PyGetSetDescrObject *descr) { return descr_repr((PyDescrObject *)descr, - "<attribute '%s' of '%s' objects>"); + "<attribute '%V' of '%s' objects>"); } static PyObject * wrapperdescr_repr(PyWrapperDescrObject *descr) { return descr_repr((PyDescrObject *)descr, - "<slot wrapper '%s' of '%s' objects>"); + "<slot wrapper '%V' of '%s' objects>"); } static int @@ -66,9 +68,9 @@ descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres) } if (!PyObject_TypeCheck(obj, descr->d_type)) { PyErr_Format(PyExc_TypeError, - "descriptor '%s' for '%s' objects " + "descriptor '%V' for '%s' objects " "doesn't apply to '%s' object", - descr_name((PyDescrObject *)descr), + descr_name((PyDescrObject *)descr), "?", descr->d_type->tp_name, obj->ob_type->tp_name); *pres = NULL; @@ -87,28 +89,28 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) else { /* Wot - no type?! */ PyErr_Format(PyExc_TypeError, - "descriptor '%s' for type '%s' " + "descriptor '%V' for type '%s' " "needs either an object or a type", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name); + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); return NULL; } } if (!PyType_Check(type)) { PyErr_Format(PyExc_TypeError, - "descriptor '%s' for type '%s' " + "descriptor '%V' for type '%s' " "needs a type, not a '%s' as arg 2", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name, + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, type->ob_type->tp_name); return NULL; } - if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) { + if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, - "descriptor '%s' for type '%s' " + "descriptor '%V' for type '%s' " "doesn't apply to type '%s'", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name, + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, ((PyTypeObject *)type)->tp_name); return NULL; } @@ -145,9 +147,9 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) if (descr->d_getset->get != NULL) return descr->d_getset->get(obj, descr->d_getset->closure); PyErr_Format(PyExc_AttributeError, - "attribute '%.300s' of '%.100s' objects is not readable", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name); + "attribute '%V' of '%.100s' objects is not readable", + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); return NULL; } @@ -168,9 +170,9 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, assert(obj != NULL); if (!PyObject_TypeCheck(obj, descr->d_type)) { PyErr_Format(PyExc_TypeError, - "descriptor '%.200s' for '%.100s' objects " + "descriptor '%V' for '%.100s' objects " "doesn't apply to '%.100s' object", - descr_name(descr), + descr_name(descr), "?", descr->d_type->tp_name, obj->ob_type->tp_name); *pres = -1; @@ -200,9 +202,9 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) return descr->d_getset->set(obj, value, descr->d_getset->closure); PyErr_Format(PyExc_AttributeError, - "attribute '%.300s' of '%.100s' objects is not writable", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name); + "attribute '%V' of '%.100s' objects is not writable", + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); return -1; } @@ -217,21 +219,21 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) argc = PyTuple_GET_SIZE(args); if (argc < 1) { PyErr_Format(PyExc_TypeError, - "descriptor '%.300s' of '%.100s' " + "descriptor '%V' of '%.100s' " "object needs an argument", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name); + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), - (PyObject *)(descr->d_type))) { + (PyObject *)PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, - "descriptor '%.200s' " + "descriptor '%V' " "requires a '%.100s' object " "but received a '%.100s'", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name, + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, self->ob_type->tp_name); return NULL; } @@ -262,28 +264,29 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, argc = PyTuple_GET_SIZE(args); if (argc < 1) { PyErr_Format(PyExc_TypeError, - "descriptor '%s' of '%.100s' " + "descriptor '%V' of '%.100s' " "object needs an argument", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name); + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); if (!PyType_Check(self)) { PyErr_Format(PyExc_TypeError, - "descriptor '%s' requires a type " + "descriptor '%V' requires a type " "but received a '%.100s'", - descr_name((PyDescrObject *)descr), + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, self->ob_type->tp_name); return NULL; } - if (!PyType_IsSubtype((PyTypeObject *)self, descr->d_type)) { + if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, - "descriptor '%s' " + "descriptor '%V' " "requires a subtype of '%.100s' " "but received '%.100s", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name, + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, self->ob_type->tp_name); return NULL; } @@ -313,21 +316,21 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) argc = PyTuple_GET_SIZE(args); if (argc < 1) { PyErr_Format(PyExc_TypeError, - "descriptor '%.300s' of '%.100s' " + "descriptor '%V' of '%.100s' " "object needs an argument", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name); + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), - (PyObject *)(descr->d_type))) { + (PyObject *)PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, - "descriptor '%.200s' " + "descriptor '%V' " "requires a '%.100s' object " "but received a '%.100s'", - descr_name((PyDescrObject *)descr), - descr->d_type->tp_name, + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, self->ob_type->tp_name); return NULL; } @@ -353,7 +356,7 @@ method_get_doc(PyMethodDescrObject *descr, void *closure) Py_INCREF(Py_None); return Py_None; } - return PyString_FromString(descr->d_method->ml_doc); + return PyUnicode_FromString(descr->d_method->ml_doc); } static PyMemberDef descr_members[] = { @@ -374,7 +377,7 @@ member_get_doc(PyMemberDescrObject *descr, void *closure) Py_INCREF(Py_None); return Py_None; } - return PyString_FromString(descr->d_member->doc); + return PyUnicode_FromString(descr->d_member->doc); } static PyGetSetDef member_getset[] = { @@ -389,7 +392,7 @@ getset_get_doc(PyGetSetDescrObject *descr, void *closure) Py_INCREF(Py_None); return Py_None; } - return PyString_FromString(descr->d_getset->doc); + return PyUnicode_FromString(descr->d_getset->doc); } static PyGetSetDef getset_getset[] = { @@ -404,7 +407,7 @@ wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure) Py_INCREF(Py_None); return Py_None; } - return PyString_FromString(descr->d_base->doc); + return PyUnicode_FromString(descr->d_base->doc); } static PyGetSetDef wrapperdescr_getset[] = { @@ -420,7 +423,7 @@ descr_traverse(PyObject *self, visitproc visit, void *arg) return 0; } -static PyTypeObject PyMethodDescr_Type = { +PyTypeObject PyMethodDescr_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "method_descriptor", sizeof(PyMethodDescrObject), @@ -429,7 +432,7 @@ static PyTypeObject PyMethodDescr_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)method_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -458,7 +461,7 @@ static PyTypeObject PyMethodDescr_Type = { }; /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */ -static PyTypeObject PyClassMethodDescr_Type = { +PyTypeObject PyClassMethodDescr_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "classmethod_descriptor", sizeof(PyMethodDescrObject), @@ -467,7 +470,7 @@ static PyTypeObject PyClassMethodDescr_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)method_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -504,7 +507,7 @@ PyTypeObject PyMemberDescr_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)member_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -541,7 +544,7 @@ PyTypeObject PyGetSetDescr_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)getset_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -578,7 +581,7 @@ PyTypeObject PyWrapperDescr_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)wrapperdescr_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -615,7 +618,7 @@ descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) if (descr != NULL) { Py_XINCREF(type); descr->d_type = type; - descr->d_name = PyString_InternFromString(name); + descr->d_name = PyUnicode_InternFromString(name); if (descr->d_name == NULL) { Py_DECREF(descr); descr = NULL; @@ -735,15 +738,6 @@ static PySequenceMethods proxy_as_sequence = { }; static PyObject * -proxy_has_key(proxyobject *pp, PyObject *key) -{ - int res = PyDict_Contains(pp->dict, key); - if (res < 0) - return NULL; - return PyBool_FromLong(res); -} - -static PyObject * proxy_get(proxyobject *pp, PyObject *args) { PyObject *key, *def = Py_None; @@ -756,49 +750,30 @@ proxy_get(proxyobject *pp, PyObject *args) static PyObject * proxy_keys(proxyobject *pp) { - return PyMapping_Keys(pp->dict); + return PyObject_CallMethod(pp->dict, "keys", NULL); } static PyObject * proxy_values(proxyobject *pp) { - return PyMapping_Values(pp->dict); + return PyObject_CallMethod(pp->dict, "values", NULL); } static PyObject * proxy_items(proxyobject *pp) { - return PyMapping_Items(pp->dict); -} - -static PyObject * -proxy_iterkeys(proxyobject *pp) -{ - return PyObject_CallMethod(pp->dict, "iterkeys", NULL); + return PyObject_CallMethod(pp->dict, "items", NULL); } static PyObject * -proxy_itervalues(proxyobject *pp) -{ - return PyObject_CallMethod(pp->dict, "itervalues", NULL); -} - -static PyObject * -proxy_iteritems(proxyobject *pp) -{ - return PyObject_CallMethod(pp->dict, "iteritems", NULL); -} -static PyObject * proxy_copy(proxyobject *pp) { return PyObject_CallMethod(pp->dict, "copy", NULL); } static PyMethodDef proxy_methods[] = { - {"has_key", (PyCFunction)proxy_has_key, METH_O, - PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")}, {"get", (PyCFunction)proxy_get, METH_VARARGS, - PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d." + PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." " d defaults to None.")}, {"keys", (PyCFunction)proxy_keys, METH_NOARGS, PyDoc_STR("D.keys() -> list of D's keys")}, @@ -806,13 +781,6 @@ static PyMethodDef proxy_methods[] = { PyDoc_STR("D.values() -> list of D's values")}, {"items", (PyCFunction)proxy_items, METH_NOARGS, PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")}, - {"iterkeys", (PyCFunction)proxy_iterkeys, METH_NOARGS, - PyDoc_STR("D.iterkeys() -> an iterator over the keys of D")}, - {"itervalues",(PyCFunction)proxy_itervalues, METH_NOARGS, - PyDoc_STR("D.itervalues() -> an iterator over the values of D")}, - {"iteritems", (PyCFunction)proxy_iteritems, METH_NOARGS, - PyDoc_STR("D.iteritems() ->" - " an iterator over the (key, value) items of D")}, {"copy", (PyCFunction)proxy_copy, METH_NOARGS, PyDoc_STR("D.copy() -> a shallow copy of D")}, {0} @@ -841,15 +809,7 @@ proxy_str(proxyobject *pp) static PyObject * proxy_repr(proxyobject *pp) { - PyObject *dictrepr; - PyObject *result; - - dictrepr = PyObject_Repr(pp->dict); - if (dictrepr == NULL) - return NULL; - result = PyString_FromFormat("dict_proxy(%s)", PyString_AS_STRING(dictrepr)); - Py_DECREF(dictrepr); - return result; + return PyUnicode_FromFormat("dict_proxy(%R)", pp->dict); } static int @@ -860,12 +820,6 @@ proxy_traverse(PyObject *self, visitproc visit, void *arg) return 0; } -static int -proxy_compare(proxyobject *v, PyObject *w) -{ - return PyObject_Compare(v->dict, w); -} - static PyObject * proxy_richcompare(proxyobject *v, PyObject *w, int op) { @@ -874,7 +828,7 @@ proxy_richcompare(proxyobject *v, PyObject *w, int op) PyTypeObject PyDictProxy_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dictproxy", /* tp_name */ + "dict_proxy", /* tp_name */ sizeof(proxyobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -882,7 +836,7 @@ PyTypeObject PyDictProxy_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - (cmpfunc)proxy_compare, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)proxy_repr, /* tp_repr */ 0, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ @@ -936,6 +890,8 @@ typedef struct { PyObject *self; } wrapperobject; +#define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type) + static void wrapper_dealloc(wrapperobject *wp) { @@ -947,19 +903,66 @@ wrapper_dealloc(wrapperobject *wp) Py_TRASHCAN_SAFE_END(wp) } -static int -wrapper_compare(wrapperobject *a, wrapperobject *b) +#define TEST_COND(cond) ((cond) ? Py_True : Py_False) + +static PyObject * +wrapper_richcompare(PyObject *a, PyObject *b, int op) { - if (a->descr == b->descr) - return PyObject_Compare(a->self, b->self); - else - return (a->descr < b->descr) ? -1 : 1; + int result; + PyObject *v; + PyWrapperDescrObject *a_descr, *b_descr; + + assert(a != NULL && b != NULL); + + /* both arguments should be wrapperobjects */ + if (!Wrapper_Check(a) || !Wrapper_Check(b)) { + v = Py_NotImplemented; + Py_INCREF(v); + return v; + } + + /* compare by descriptor address; if the descriptors are the same, + compare by the objects they're bound to */ + a_descr = ((wrapperobject *)a)->descr; + b_descr = ((wrapperobject *)b)->descr; + if (a_descr == b_descr) { + a = ((wrapperobject *)a)->self; + b = ((wrapperobject *)b)->self; + return PyObject_RichCompare(a, b, op); + } + + result = a_descr - b_descr; + switch (op) { + case Py_EQ: + v = TEST_COND(result == 0); + break; + case Py_NE: + v = TEST_COND(result != 0); + break; + case Py_LE: + v = TEST_COND(result <= 0); + break; + case Py_GE: + v = TEST_COND(result >= 0); + break; + case Py_LT: + v = TEST_COND(result < 0); + break; + case Py_GT: + v = TEST_COND(result > 0); + break; + default: + PyErr_BadArgument(); + return NULL; + } + Py_INCREF(v); + return v; } -static long +static Py_hash_t wrapper_hash(wrapperobject *wp) { - int x, y; + Py_hash_t x, y; x = _Py_HashPointer(wp->descr); if (x == -1) return -1; @@ -975,7 +978,7 @@ wrapper_hash(wrapperobject *wp) static PyObject * wrapper_repr(wrapperobject *wp) { - return PyString_FromFormat("<method-wrapper '%s' of %s object at %p>", + return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>", wp->descr->d_base->name, wp->self->ob_type->tp_name, wp->self); @@ -989,7 +992,7 @@ static PyMemberDef wrapper_members[] = { static PyObject * wrapper_objclass(wrapperobject *wp) { - PyObject *c = (PyObject *)wp->descr->d_type; + PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr); Py_INCREF(c); return c; @@ -998,22 +1001,22 @@ wrapper_objclass(wrapperobject *wp) static PyObject * wrapper_name(wrapperobject *wp) { - char *s = wp->descr->d_base->name; + const char *s = wp->descr->d_base->name; - return PyString_FromString(s); + return PyUnicode_FromString(s); } static PyObject * wrapper_doc(wrapperobject *wp) { - char *s = wp->descr->d_base->doc; + const char *s = wp->descr->d_base->doc; if (s == NULL) { Py_INCREF(Py_None); return Py_None; } else { - return PyString_FromString(s); + return PyUnicode_FromString(s); } } @@ -1053,7 +1056,7 @@ wrapper_traverse(PyObject *self, visitproc visit, void *arg) return 0; } -static PyTypeObject wrappertype = { +PyTypeObject _PyMethodWrapper_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "method-wrapper", /* tp_name */ sizeof(wrapperobject), /* tp_basicsize */ @@ -1063,7 +1066,7 @@ static PyTypeObject wrappertype = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - (cmpfunc)wrapper_compare, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)wrapper_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -1078,7 +1081,7 @@ static PyTypeObject wrappertype = { 0, /* tp_doc */ wrapper_traverse, /* tp_traverse */ 0, /* tp_clear */ - 0, /* tp_richcompare */ + wrapper_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ @@ -1100,9 +1103,9 @@ PyWrapper_New(PyObject *d, PyObject *self) assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); descr = (PyWrapperDescrObject *)d; assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), - (PyObject *)(descr->d_type))); + (PyObject *)PyDescr_TYPE(descr))); - wp = PyObject_GC_New(wrapperobject, &wrappertype); + wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type); if (wp != NULL) { Py_INCREF(descr); wp->descr = descr; @@ -1231,7 +1234,7 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type) PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); return NULL; } - return PyObject_CallFunction(gs->prop_get, "(O)", obj); + return PyObject_CallFunctionObjArgs(gs->prop_get, obj, NULL); } static int @@ -1252,9 +1255,9 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value) return -1; } if (value == NULL) - res = PyObject_CallFunction(func, "(O)", obj); + res = PyObject_CallFunctionObjArgs(func, obj, NULL); else - res = PyObject_CallFunction(func, "(OO)", obj, value); + res = PyObject_CallFunctionObjArgs(func, obj, value, NULL); if (res == NULL) return -1; Py_DECREF(res); @@ -1401,7 +1404,7 @@ PyTypeObject PyProperty_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ |
