From 6f7993765ac0989b5d13084240797913627a31d8 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 20 Sep 2001 20:46:19 +0000 Subject: Add optional docstrings to member descriptors. For backwards compatibility, this required all places where an array of "struct memberlist" structures was declared that is referenced from a type's tp_members slot to change the type of the structure to PyMemberDef; "struct memberlist" is now only used by old code that still calls PyMember_Get/Set. The code in PyObject_GenericGetAttr/SetAttr now calls the new APIs PyMember_GetOne/SetOne, which take a PyMemberDef argument. As examples, I added actual docstrings to the attributes of a few types: file, complex, instance method, super, and xxsubtype.spamlist. Also converted the symtable to new style getattr. --- Include/descrobject.h | 2 +- Include/object.h | 2 +- Include/structmember.h | 16 ++ Modules/xxsubtype.c | 5 +- Objects/classobject.c | 11 +- Objects/complexobject.c | 8 +- Objects/descrobject.c | 33 ++-- Objects/fileobject.c | 11 +- Objects/frameobject.c | 2 +- Objects/funcobject.c | 2 +- Objects/moduleobject.c | 2 +- Objects/sliceobject.c | 2 +- Objects/typeobject.c | 20 +-- Python/ceval.c | 2 +- Python/compile.c | 2 +- Python/structmember.c | 415 +++++++++++++++++++++++++----------------------- Python/symtable.c | 29 ++-- 17 files changed, 313 insertions(+), 251 deletions(-) diff --git a/Include/descrobject.h b/Include/descrobject.h index a868310..3d58181 100644 --- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -21,7 +21,7 @@ struct wrapperbase { extern DL_IMPORT(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *); extern DL_IMPORT(PyObject *) PyDescr_NewMember(PyTypeObject *, - struct memberlist *); + struct PyMemberDef *); extern DL_IMPORT(PyObject *) PyDescr_NewGetSet(PyTypeObject *, struct getsetlist *); extern DL_IMPORT(PyObject *) PyDescr_NewWrapper(PyTypeObject *, diff --git a/Include/object.h b/Include/object.h index 160331e..1d0ae5f 100644 --- a/Include/object.h +++ b/Include/object.h @@ -274,7 +274,7 @@ typedef struct _typeobject { /* Attribute descriptor and subclassing stuff */ struct PyMethodDef *tp_methods; - struct memberlist *tp_members; + struct PyMemberDef *tp_members; struct getsetlist *tp_getset; struct _typeobject *tp_base; PyObject *tp_dict; diff --git a/Include/structmember.h b/Include/structmember.h index cd35fdb..2c9f41d 100644 --- a/Include/structmember.h +++ b/Include/structmember.h @@ -28,12 +28,22 @@ extern "C" { pointer is NULL. */ struct memberlist { + /* Obsolete version, for binary backwards compatibility */ char *name; int type; int offset; int flags; }; +typedef struct PyMemberDef { + /* Current version, use this */ + char *name; + int type; + int offset; + int flags; + char *doc; +} PyMemberDef; + /* Types */ #define T_SHORT 0 #define T_INT 1 @@ -66,9 +76,15 @@ struct memberlist { #define RESTRICTED (READ_RESTRICTED | WRITE_RESTRICTED) +/* Obsolete API, for binary backwards compatibility */ DL_IMPORT(PyObject *) PyMember_Get(char *, struct memberlist *, char *); DL_IMPORT(int) PyMember_Set(char *, struct memberlist *, char *, PyObject *); +/* Current API, use this */ +DL_IMPORT(PyObject *) PyMember_GetOne(char *, struct PyMemberDef *); +DL_IMPORT(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *); + + #ifdef __cplusplus } #endif diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c index c20a1c7..cdf6d07 100644 --- a/Modules/xxsubtype.c +++ b/Modules/xxsubtype.c @@ -148,8 +148,9 @@ spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds) return 0; } -static struct memberlist spamdict_members[] = { - {"state", T_INT, offsetof(spamdictobject, state), READONLY}, +static PyMemberDef spamdict_members[] = { + {"state", T_INT, offsetof(spamdictobject, state), READONLY, + "an int variable for demonstration purposes"}, {0} }; diff --git a/Objects/classobject.c b/Objects/classobject.c index 3845dfc..f8ee6fd 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -2006,10 +2006,13 @@ PyMethod_New(PyObject *func, PyObject *self, PyObject *class) #define OFF(x) offsetof(PyMethodObject, x) -static struct memberlist instancemethod_memberlist[] = { - {"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED}, - {"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED}, - {"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED}, +static PyMemberDef instancemethod_memberlist[] = { + {"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED, + "the class associated with a method"}, + {"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED, + "the function (or other callable) implementing a method"}, + {"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED, + "the instance to which a method is bound; None for unbound methods"}, {NULL} /* Sentinel */ }; diff --git a/Objects/complexobject.c b/Objects/complexobject.c index a2ccadb..191dcba 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -625,9 +625,11 @@ static PyMethodDef complex_methods[] = { {NULL, NULL} /* sentinel */ }; -static struct memberlist complex_members[] = { - {"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0}, - {"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0}, +static PyMemberDef complex_members[] = { + {"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0, + "the real part of a complex number"}, + {"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0, + "the imaginary part of a complex number"}, {0}, }; diff --git a/Objects/descrobject.c b/Objects/descrobject.c index e5b08c3..dfbb3b6 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -21,7 +21,7 @@ typedef struct { typedef struct { COMMON; - struct memberlist *d_member; + PyMemberDef *d_member; } PyMemberDescrObject; typedef struct { @@ -126,8 +126,7 @@ member_get(PyMemberDescrObject *descr, PyObject *obj, PyTypeObject *type) if (descr_check((PyDescrObject *)descr, obj, type, &res)) return res; - return PyMember_Get((char *)obj, descr->d_member, - descr->d_member->name); + return PyMember_GetOne((char *)obj, descr->d_member); } static PyObject * @@ -181,8 +180,7 @@ member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) return res; - return PyMember_Set((char *)obj, descr->d_member, - descr->d_member->name, value); + return PyMember_SetOne((char *)obj, descr->d_member, value); } static int @@ -289,7 +287,7 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) } static PyObject * -member_get_doc(PyMethodDescrObject *descr, void *closure) +method_get_doc(PyMethodDescrObject *descr, void *closure) { if (descr->d_method->ml_doc == NULL) { Py_INCREF(Py_None); @@ -298,12 +296,27 @@ member_get_doc(PyMethodDescrObject *descr, void *closure) return PyString_FromString(descr->d_method->ml_doc); } -static struct memberlist descr_members[] = { +static PyMemberDef descr_members[] = { {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY}, {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY}, {0} }; +static struct getsetlist method_getset[] = { + {"__doc__", (getter)method_get_doc}, + {0} +}; + +static PyObject * +member_get_doc(PyMemberDescrObject *descr, void *closure) +{ + if (descr->d_member->doc == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(descr->d_member->doc); +} + static struct getsetlist member_getset[] = { {"__doc__", (getter)member_get_doc}, {0} @@ -355,7 +368,7 @@ static PyTypeObject PyMethodDescr_Type = { 0, /* tp_iternext */ 0, /* tp_methods */ descr_members, /* tp_members */ - member_getset, /* tp_getset */ + method_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ (descrgetfunc)method_get, /* tp_descr_get */ @@ -393,7 +406,7 @@ static PyTypeObject PyMemberDescr_Type = { 0, /* tp_iternext */ 0, /* tp_methods */ descr_members, /* tp_members */ - 0, /* tp_getset */ + member_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ (descrgetfunc)member_get, /* tp_descr_get */ @@ -507,7 +520,7 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) } PyObject * -PyDescr_NewMember(PyTypeObject *type, struct memberlist *member) +PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member) { PyMemberDescrObject *descr; diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 6ceb83c..5c879ff 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -1383,10 +1383,13 @@ static PyMethodDef file_methods[] = { #define OFF(x) offsetof(PyFileObject, x) -static struct memberlist file_memberlist[] = { - {"softspace", T_INT, OFF(f_softspace)}, - {"mode", T_OBJECT, OFF(f_mode), RO}, - {"name", T_OBJECT, OFF(f_name), RO}, +static PyMemberDef file_memberlist[] = { + {"softspace", T_INT, OFF(f_softspace), 0, + "flag indicating that a space needs to be printed; used by print"}, + {"mode", T_OBJECT, OFF(f_mode), RO, + "file mode ('r', 'w', 'a', possibly with 'b' or '+' added)"}, + {"name", T_OBJECT, OFF(f_name), RO, + "file name"}, /* getattr(f, "closed") is implemented without this table */ {NULL} /* Sentinel */ }; diff --git a/Objects/frameobject.c b/Objects/frameobject.c index fd9a4e2..cb7e80a 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -10,7 +10,7 @@ #define OFF(x) offsetof(PyFrameObject, x) -static struct memberlist frame_memberlist[] = { +static PyMemberDef frame_memberlist[] = { {"f_back", T_OBJECT, OFF(f_back), RO}, {"f_code", T_OBJECT, OFF(f_code), RO}, {"f_builtins", T_OBJECT, OFF(f_builtins),RO}, diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 91a3127..e1cf080 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -129,7 +129,7 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure) #define RR () -static struct memberlist func_memberlist[] = { +static PyMemberDef func_memberlist[] = { {"func_closure", T_OBJECT, OFF(func_closure), RESTRICTED|READONLY}, {"func_doc", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED}, diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 6d91ecc..586785c 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -9,7 +9,7 @@ typedef struct { PyObject *md_dict; } PyModuleObject; -struct memberlist module_members[] = { +PyMemberDef module_members[] = { {"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY}, {0} }; diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 8f52f9e..81517a8 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -129,7 +129,7 @@ slice_repr(PySliceObject *r) return s; } -static struct memberlist slice_members[] = { +static PyMemberDef slice_members[] = { {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY}, {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY}, {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY}, diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 26ddabe..b53555d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4,7 +4,7 @@ #include "Python.h" #include "structmember.h" -static struct memberlist type_members[] = { +static PyMemberDef type_members[] = { {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY}, {"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY}, {"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY}, @@ -263,7 +263,7 @@ typedef struct { PyMappingMethods as_mapping; PyBufferProcs as_buffer; PyObject *name, *slots; - struct memberlist members[1]; + PyMemberDef members[1]; } etype; /* type test with subclassing support */ @@ -672,7 +672,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) PyObject *slots, *tmp; PyTypeObject *type, *base, *tmptype, *winner; etype *et; - struct memberlist *mp; + PyMemberDef *mp; int i, nbases, nslots, slotoffset, dynamic, add_dict, add_weak; /* Special case: type(x) should return x->ob_type */ @@ -1087,7 +1087,7 @@ PyTypeObject PyType_Type = { 0, /* ob_size */ "type", /* tp_name */ sizeof(etype), /* tp_basicsize */ - sizeof(struct memberlist), /* tp_itemsize */ + sizeof(PyMemberDef), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ @@ -1192,7 +1192,7 @@ object_free(PyObject *self) PyObject_Del(self); } -static struct memberlist object_members[] = { +static PyMemberDef object_members[] = { {"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY}, {0} }; @@ -1263,7 +1263,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) } static int -add_members(PyTypeObject *type, struct memberlist *memb) +add_members(PyTypeObject *type, PyMemberDef *memb) { PyObject *dict = type->tp_defined; @@ -3221,9 +3221,11 @@ typedef struct { PyObject *obj; } superobject; -static struct memberlist super_members[] = { - {"__type__", T_OBJECT, offsetof(superobject, type), READONLY}, - {"__obj__", T_OBJECT, offsetof(superobject, obj), READONLY}, +static PyMemberDef super_members[] = { + {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY, + "the class invoking super()"}, + {"__self__", T_OBJECT, offsetof(superobject, obj), READONLY, + "the instance invoking super(); may be None"}, {0} }; diff --git a/Python/ceval.c b/Python/ceval.c index bbbdcf3..3ca1e3e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -192,7 +192,7 @@ static struct PyMethodDef gen_methods[] = { {NULL, NULL} /* Sentinel */ }; -static struct memberlist gen_memberlist[] = { +static PyMemberDef gen_memberlist[] = { {"gi_frame", T_OBJECT, offsetof(genobject, gi_frame), RO}, {"gi_running", T_INT, offsetof(genobject, gi_running), RO}, {NULL} /* Sentinel */ diff --git a/Python/compile.c b/Python/compile.c index 0f10dbe..dae2a3e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -73,7 +73,7 @@ int Py_OptimizeFlag = 0; #define OFF(x) offsetof(PyCodeObject, x) -static struct memberlist code_memberlist[] = { +static PyMemberDef code_memberlist[] = { {"co_argcount", T_INT, OFF(co_argcount), READONLY}, {"co_nlocals", T_INT, OFF(co_nlocals), READONLY}, {"co_stacksize",T_INT, OFF(co_stacksize), READONLY}, diff --git a/Python/structmember.c b/Python/structmember.c index ed34783..077be70 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -32,226 +32,237 @@ PyObject * PyMember_Get(char *addr, struct memberlist *mlist, char *name) { struct memberlist *l; - + if (strcmp(name, "__members__") == 0) return listmembers(mlist); for (l = mlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) { - PyObject *v; - if ((l->flags & READ_RESTRICTED) && - PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, - "restricted attribute"); - return NULL; - } - addr += l->offset; - switch (l->type) { - case T_BYTE: - v = PyInt_FromLong((long) - (((*(char*)addr & 0xff) - ^ 0x80) - 0x80)); - break; - case T_UBYTE: - v = PyInt_FromLong((long) *(char*)addr & 0xff); - break; - case T_SHORT: - v = PyInt_FromLong((long) *(short*)addr); - break; - case T_USHORT: - v = PyInt_FromLong((long) - *(unsigned short*)addr); - break; - case T_INT: - v = PyInt_FromLong((long) *(int*)addr); - break; - case T_UINT: - v = PyInt_FromLong((long) - *(unsigned int*)addr); - break; - case T_LONG: - v = PyInt_FromLong(*(long*)addr); - break; - case T_ULONG: - v = PyLong_FromDouble((double) - *(unsigned long*)addr); - break; - case T_FLOAT: - v = PyFloat_FromDouble((double)*(float*)addr); - break; - case T_DOUBLE: - v = PyFloat_FromDouble(*(double*)addr); - break; - case T_STRING: - if (*(char**)addr == NULL) { - Py_INCREF(Py_None); - v = Py_None; - } - else - v = PyString_FromString(*(char**)addr); - break; - case T_STRING_INPLACE: - v = PyString_FromString((char*)addr); - break; -#ifdef macintosh - case T_PSTRING: - if (*(char**)addr == NULL) { - Py_INCREF(Py_None); - v = Py_None; - } - else - v = PyString_FromStringAndSize( - (*(char**)addr)+1, - **(unsigned char**)addr); - break; - case T_PSTRING_INPLACE: - v = PyString_FromStringAndSize( - ((char*)addr)+1, - *(unsigned char*)addr); - break; -#endif /* macintosh */ - case T_CHAR: - v = PyString_FromStringAndSize((char*)addr, 1); - break; - case T_OBJECT: - v = *(PyObject **)addr; - if (v == NULL) - v = Py_None; - Py_INCREF(v); - break; - default: - PyErr_SetString(PyExc_SystemError, - "bad memberlist type"); - v = NULL; - } - return v; + PyMemberDef copy; + copy.name = l->name; + copy.type = l->type; + copy.offset = l->offset; + copy.flags = l->flags; + copy.doc = NULL; + return PyMember_GetOne(addr, ©); } } - PyErr_SetString(PyExc_AttributeError, name); return NULL; } +PyObject * +PyMember_GetOne(char *addr, PyMemberDef *l) +{ + PyObject *v; + if ((l->flags & READ_RESTRICTED) && + PyEval_GetRestricted()) { + PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); + return NULL; + } + addr += l->offset; + switch (l->type) { + case T_BYTE: + v = PyInt_FromLong( + (long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80)); + break; + case T_UBYTE: + v = PyInt_FromLong((long) *(char*)addr & 0xff); + break; + case T_SHORT: + v = PyInt_FromLong((long) *(short*)addr); + break; + case T_USHORT: + v = PyInt_FromLong((long) *(unsigned short*)addr); + break; + case T_INT: + v = PyInt_FromLong((long) *(int*)addr); + break; + case T_UINT: + v = PyInt_FromLong((long) *(unsigned int*)addr); + break; + case T_LONG: + v = PyInt_FromLong(*(long*)addr); + break; + case T_ULONG: + v = PyLong_FromDouble((double) *(unsigned long*)addr); + break; + case T_FLOAT: + v = PyFloat_FromDouble((double)*(float*)addr); + break; + case T_DOUBLE: + v = PyFloat_FromDouble(*(double*)addr); + break; + case T_STRING: + if (*(char**)addr == NULL) { + Py_INCREF(Py_None); + v = Py_None; + } + else + v = PyString_FromString(*(char**)addr); + break; + case T_STRING_INPLACE: + v = PyString_FromString((char*)addr); + break; +#ifdef macintosh + case T_PSTRING: + if (*(char**)addr == NULL) { + Py_INCREF(Py_None); + v = Py_None; + } + else + v = PyString_FromStringAndSize( + (*(char**)addr)+1, + **(unsigned char**)addr); + break; + case T_PSTRING_INPLACE: + v = PyString_FromStringAndSize( + ((char*)addr)+1, + *(unsigned char*)addr); + break; +#endif /* macintosh */ + case T_CHAR: + v = PyString_FromStringAndSize((char*)addr, 1); + break; + case T_OBJECT: + v = *(PyObject **)addr; + if (v == NULL) + v = Py_None; + Py_INCREF(v); + break; + default: + PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); + v = NULL; + } + return v; +} + int PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v) { struct memberlist *l; - PyObject *oldv; - + for (l = mlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) { - if ((l->flags & READONLY) || l->type == T_STRING -#ifdef macintosh - || l->type == T_PSTRING -#endif - ) - { - PyErr_SetString(PyExc_TypeError, - "readonly attribute"); - return -1; - } - if ((l->flags & WRITE_RESTRICTED) && - PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, - "restricted attribute"); - return -1; - } - if (v == NULL && l->type != T_OBJECT) { - PyErr_SetString(PyExc_TypeError, - "can't delete numeric/char attribute"); - return -1; - } - addr += l->offset; - switch (l->type) { - case T_BYTE: - case T_UBYTE: - if (!PyInt_Check(v)) { - PyErr_BadArgument(); - return -1; - } - *(char*)addr = (char) PyInt_AsLong(v); - break; - case T_SHORT: - case T_USHORT: - if (!PyInt_Check(v)) { - PyErr_BadArgument(); - return -1; - } - *(short*)addr = (short) PyInt_AsLong(v); - break; - case T_UINT: - case T_INT: - if (!PyInt_Check(v)) { - PyErr_BadArgument(); - return -1; - } - *(int*)addr = (int) PyInt_AsLong(v); - break; - case T_LONG: - if (!PyInt_Check(v)) { - PyErr_BadArgument(); - return -1; - } - *(long*)addr = PyInt_AsLong(v); - break; - case T_ULONG: - if (PyInt_Check(v)) - *(long*)addr = PyInt_AsLong(v); - else if (PyLong_Check(v)) - *(long*)addr = PyLong_AsLong(v); - else { - PyErr_BadArgument(); - return -1; - } - break; - case T_FLOAT: - if (PyInt_Check(v)) - *(float*)addr = - (float) PyInt_AsLong(v); - else if (PyFloat_Check(v)) - *(float*)addr = - (float) PyFloat_AsDouble(v); - else { - PyErr_BadArgument(); - return -1; - } - break; - case T_DOUBLE: - if (PyInt_Check(v)) - *(double*)addr = - (double) PyInt_AsLong(v); - else if (PyFloat_Check(v)) - *(double*)addr = PyFloat_AsDouble(v); - else { - PyErr_BadArgument(); - return -1; - } - break; - case T_OBJECT: - Py_XINCREF(v); - oldv = *(PyObject **)addr; - *(PyObject **)addr = v; - Py_XDECREF(oldv); - break; - case T_CHAR: - if (PyString_Check(v) && - PyString_Size(v) == 1) { - *(char*)addr = - PyString_AsString(v)[0]; - } - else { - PyErr_BadArgument(); - return -1; - } - break; - default: - PyErr_SetString(PyExc_SystemError, - "bad memberlist type"); - return -1; - } - return 0; + PyMemberDef copy; + copy.name = l->name; + copy.type = l->type; + copy.offset = l->offset; + copy.flags = l->flags; + copy.doc = NULL; + return PyMember_SetOne(addr, ©, v); } } - + PyErr_SetString(PyExc_AttributeError, name); return -1; } + +int +PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) +{ + PyObject *oldv; + + if ((l->flags & READONLY) || l->type == T_STRING +#ifdef macintosh + || l->type == T_PSTRING +#endif + ) + { + PyErr_SetString(PyExc_TypeError, "readonly attribute"); + return -1; + } + if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) { + PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); + return -1; + } + if (v == NULL && l->type != T_OBJECT) { + PyErr_SetString(PyExc_TypeError, + "can't delete numeric/char attribute"); + return -1; + } + addr += l->offset; + switch (l->type) { + case T_BYTE: + case T_UBYTE: + if (!PyInt_Check(v)) { + PyErr_BadArgument(); + return -1; + } + *(char*)addr = (char) PyInt_AsLong(v); + break; + case T_SHORT: + case T_USHORT: + if (!PyInt_Check(v)) { + PyErr_BadArgument(); + return -1; + } + *(short*)addr = (short) PyInt_AsLong(v); + break; + case T_UINT: + case T_INT: + if (!PyInt_Check(v)) { + PyErr_BadArgument(); + return -1; + } + *(int*)addr = (int) PyInt_AsLong(v); + break; + case T_LONG: + if (!PyInt_Check(v)) { + PyErr_BadArgument(); + return -1; + } + *(long*)addr = PyInt_AsLong(v); + break; + case T_ULONG: + if (PyInt_Check(v)) + *(long*)addr = PyInt_AsLong(v); + else if (PyLong_Check(v)) + *(long*)addr = PyLong_AsLong(v); + else { + PyErr_BadArgument(); + return -1; + } + break; + case T_FLOAT: + if (PyInt_Check(v)) + *(float*)addr = + (float) PyInt_AsLong(v); + else if (PyFloat_Check(v)) + *(float*)addr = + (float) PyFloat_AsDouble(v); + else { + PyErr_BadArgument(); + return -1; + } + break; + case T_DOUBLE: + if (PyInt_Check(v)) + *(double*)addr = (double) PyInt_AsLong(v); + else if (PyFloat_Check(v)) + *(double*)addr = PyFloat_AsDouble(v); + else { + PyErr_BadArgument(); + return -1; + } + break; + case T_OBJECT: + Py_XINCREF(v); + oldv = *(PyObject **)addr; + *(PyObject **)addr = v; + Py_XDECREF(oldv); + break; + case T_CHAR: + if (PyString_Check(v) && PyString_Size(v) == 1) { + *(char*)addr = PyString_AsString(v)[0]; + } + else { + PyErr_BadArgument(); + return -1; + } + break; + default: + PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); + return -1; + } + return 0; +} diff --git a/Python/symtable.c b/Python/symtable.c index e115167..4f63ae7 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -106,7 +106,7 @@ ste_dealloc(PySymtableEntryObject *ste) #define OFF(x) offsetof(PySymtableEntryObject, x) -static struct memberlist ste_memberlist[] = { +static PyMemberDef ste_memberlist[] = { {"id", T_OBJECT, OFF(ste_id), READONLY}, {"name", T_OBJECT, OFF(ste_name), READONLY}, {"symbols", T_OBJECT, OFF(ste_symbols), READONLY}, @@ -119,12 +119,6 @@ static struct memberlist ste_memberlist[] = { {NULL} }; -static PyObject * -ste_getattr(PySymtableEntryObject *ste, char *name) -{ - return PyMember_Get((char *)ste, ste_memberlist, name); -} - PyTypeObject PySymtableEntry_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -133,7 +127,7 @@ PyTypeObject PySymtableEntry_Type = { 0, (destructor)ste_dealloc, /* tp_dealloc */ 0, /* tp_print */ - (getattrfunc)ste_getattr, /* tp_getattr */ + 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)ste_repr, /* tp_repr */ @@ -143,9 +137,26 @@ PyTypeObject PySymtableEntry_Type = { 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - 0, /* tp_getattro */ + PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + ste_memberlist, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ }; -- cgit v0.12