Commit 6f799376 authored by Guido van Rossum's avatar Guido van Rossum

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.
parent e0af35eb
......@@ -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 *,
......
......@@ -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;
......
......@@ -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
......
......@@ -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}
};
......
......@@ -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 */
};
......
......@@ -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},
};
......
......@@ -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;
......
......@@ -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 */
};
......
......@@ -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},
......
......@@ -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},
......
......@@ -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}
};
......
......@@ -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},
......
......@@ -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}
};
......
......@@ -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 */
......
......@@ -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},
......
......@@ -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;
}
......@@ -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 */
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment