]> granicus.if.org Git - python/commitdiff
Add optional docstrings to member descriptors. For backwards
authorGuido van Rossum <guido@python.org>
Thu, 20 Sep 2001 20:46:19 +0000 (20:46 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 20 Sep 2001 20:46:19 +0000 (20:46 +0000)
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.

17 files changed:
Include/descrobject.h
Include/object.h
Include/structmember.h
Modules/xxsubtype.c
Objects/classobject.c
Objects/complexobject.c
Objects/descrobject.c
Objects/fileobject.c
Objects/frameobject.c
Objects/funcobject.c
Objects/moduleobject.c
Objects/sliceobject.c
Objects/typeobject.c
Python/ceval.c
Python/compile.c
Python/structmember.c
Python/symtable.c

index a86831051f98df8acef5554d825df7e28ea62c16..3d581818f5969a66a93dec462cd3f0f54d57fbda 100644 (file)
@@ -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 *,
index 160331ed23c83a975efca9e2bbc0c33674fa777c..1d0ae5f0953732b7b69fb88fc300fdbe3712fabd 100644 (file)
@@ -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;
index cd35fdb17474a42e10ca66fa4645afaccff6bcc3..2c9f41d3dc1a88cd14fa779ff65d0bb540d3f3ef 100644 (file)
@@ -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
index c20a1c711403f5a112b09bc81dd68f0aa9afb654..cdf6d07329c1b8e5fc002da0270b750e03e6a4fd 100644 (file)
@@ -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}
 };
 
index 3845dfcf74fb033404f0323929573d09ab64908f..f8ee6fddad9d9115a821b25a7c4605219b0c5dd4 100644 (file)
@@ -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 */
 };
 
index a2ccadb78ad67f43999bdbd690335ff0e4ec9214..191dcba73eec33a6d669f8c3b8ea255b67cf19f0 100644 (file)
@@ -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},
 };
 
index e5b08c375b032ddb55dcd5ed4a82c32f445da40a..dfbb3b628f6dd59de17e04869df4334a18f62868 100644 (file)
@@ -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;
 
index 6ceb83cca3315f1ba5ac1adf52b3744b89e28b8d..5c879ff1d4ca2d8075dc22a03c86624468778357 100644 (file)
@@ -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 */
 };
index fd9a4e2de62b4feba28d123e372143f3f0ca8fa9..cb7e80a3fe2bf1e62b7b98de6faa8cf70bc87519 100644 (file)
@@ -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},
index 91a312759fc54b3406fbe25216aed0052ccc335c..e1cf0808620fc3a35878a76f3f0b2d0ad630b01a 100644 (file)
@@ -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},
index 6d91eccce258e58421dc4f386f0ebd952e23a552..586785c81e33b5448f597e2c63b85d7c75970e63 100644 (file)
@@ -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}
 };
index 8f52f9ec1722157a5d286a5ecd80814ec123f50e..81517a88c905eb886c8b37335329bb250e151fd3 100644 (file)
@@ -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},
index 26ddabe0c267f23647174a21943e5e0bc5669045..b53555d6678cdd0e98d9f448e3d4234dc4038116 100644 (file)
@@ -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}
 };
 
index bbbdcf3455a7928b04a15ee3aabc3d61306a1a7b..3ca1e3e283444b56801b1f5306641d47d612da06 100644 (file)
@@ -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 */
index 0f10dbe2ce78119baddd01a9333dc6d743aa77bf..dae2a3eeb84b76b8903766de5e14b2873beddef1 100644 (file)
@@ -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},
index ed347834fae7c66c029411ecbd252def742c0ee7..077be708854ab7943b025eda37d5d33f47a0fdf2 100644 (file)
@@ -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, &copy);
                }
        }
-       
        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, &copy, 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;
+}
index e1151671ca9b79836f67730457a376edac84f727..4f63ae798f02d82c825cf39026642338e10251e7 100644 (file)
@@ -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 */
 };