mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
e0af35eb69
commit
6f7993765a
|
@ -21,7 +21,7 @@ struct wrapperbase {
|
||||||
|
|
||||||
extern DL_IMPORT(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *);
|
extern DL_IMPORT(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *);
|
||||||
extern DL_IMPORT(PyObject *) PyDescr_NewMember(PyTypeObject *,
|
extern DL_IMPORT(PyObject *) PyDescr_NewMember(PyTypeObject *,
|
||||||
struct memberlist *);
|
struct PyMemberDef *);
|
||||||
extern DL_IMPORT(PyObject *) PyDescr_NewGetSet(PyTypeObject *,
|
extern DL_IMPORT(PyObject *) PyDescr_NewGetSet(PyTypeObject *,
|
||||||
struct getsetlist *);
|
struct getsetlist *);
|
||||||
extern DL_IMPORT(PyObject *) PyDescr_NewWrapper(PyTypeObject *,
|
extern DL_IMPORT(PyObject *) PyDescr_NewWrapper(PyTypeObject *,
|
||||||
|
|
|
@ -274,7 +274,7 @@ typedef struct _typeobject {
|
||||||
|
|
||||||
/* Attribute descriptor and subclassing stuff */
|
/* Attribute descriptor and subclassing stuff */
|
||||||
struct PyMethodDef *tp_methods;
|
struct PyMethodDef *tp_methods;
|
||||||
struct memberlist *tp_members;
|
struct PyMemberDef *tp_members;
|
||||||
struct getsetlist *tp_getset;
|
struct getsetlist *tp_getset;
|
||||||
struct _typeobject *tp_base;
|
struct _typeobject *tp_base;
|
||||||
PyObject *tp_dict;
|
PyObject *tp_dict;
|
||||||
|
|
|
@ -28,12 +28,22 @@ extern "C" {
|
||||||
pointer is NULL. */
|
pointer is NULL. */
|
||||||
|
|
||||||
struct memberlist {
|
struct memberlist {
|
||||||
|
/* Obsolete version, for binary backwards compatibility */
|
||||||
char *name;
|
char *name;
|
||||||
int type;
|
int type;
|
||||||
int offset;
|
int offset;
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct PyMemberDef {
|
||||||
|
/* Current version, use this */
|
||||||
|
char *name;
|
||||||
|
int type;
|
||||||
|
int offset;
|
||||||
|
int flags;
|
||||||
|
char *doc;
|
||||||
|
} PyMemberDef;
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
#define T_SHORT 0
|
#define T_SHORT 0
|
||||||
#define T_INT 1
|
#define T_INT 1
|
||||||
|
@ -66,9 +76,15 @@ struct memberlist {
|
||||||
#define RESTRICTED (READ_RESTRICTED | WRITE_RESTRICTED)
|
#define RESTRICTED (READ_RESTRICTED | WRITE_RESTRICTED)
|
||||||
|
|
||||||
|
|
||||||
|
/* Obsolete API, for binary backwards compatibility */
|
||||||
DL_IMPORT(PyObject *) PyMember_Get(char *, struct memberlist *, char *);
|
DL_IMPORT(PyObject *) PyMember_Get(char *, struct memberlist *, char *);
|
||||||
DL_IMPORT(int) PyMember_Set(char *, struct memberlist *, char *, PyObject *);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -148,8 +148,9 @@ spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct memberlist spamdict_members[] = {
|
static PyMemberDef spamdict_members[] = {
|
||||||
{"state", T_INT, offsetof(spamdictobject, state), READONLY},
|
{"state", T_INT, offsetof(spamdictobject, state), READONLY,
|
||||||
|
"an int variable for demonstration purposes"},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2006,10 +2006,13 @@ PyMethod_New(PyObject *func, PyObject *self, PyObject *class)
|
||||||
|
|
||||||
#define OFF(x) offsetof(PyMethodObject, x)
|
#define OFF(x) offsetof(PyMethodObject, x)
|
||||||
|
|
||||||
static struct memberlist instancemethod_memberlist[] = {
|
static PyMemberDef instancemethod_memberlist[] = {
|
||||||
{"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED},
|
{"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED,
|
||||||
{"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED},
|
"the class associated with a method"},
|
||||||
{"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED},
|
{"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 */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -625,9 +625,11 @@ static PyMethodDef complex_methods[] = {
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct memberlist complex_members[] = {
|
static PyMemberDef complex_members[] = {
|
||||||
{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0},
|
{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0,
|
||||||
{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0},
|
"the real part of a complex number"},
|
||||||
|
{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0,
|
||||||
|
"the imaginary part of a complex number"},
|
||||||
{0},
|
{0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
COMMON;
|
COMMON;
|
||||||
struct memberlist *d_member;
|
PyMemberDef *d_member;
|
||||||
} PyMemberDescrObject;
|
} PyMemberDescrObject;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -126,8 +126,7 @@ member_get(PyMemberDescrObject *descr, PyObject *obj, PyTypeObject *type)
|
||||||
|
|
||||||
if (descr_check((PyDescrObject *)descr, obj, type, &res))
|
if (descr_check((PyDescrObject *)descr, obj, type, &res))
|
||||||
return res;
|
return res;
|
||||||
return PyMember_Get((char *)obj, descr->d_member,
|
return PyMember_GetOne((char *)obj, descr->d_member);
|
||||||
descr->d_member->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -181,8 +180,7 @@ member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
|
||||||
|
|
||||||
if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
|
if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
|
||||||
return res;
|
return res;
|
||||||
return PyMember_Set((char *)obj, descr->d_member,
|
return PyMember_SetOne((char *)obj, descr->d_member, value);
|
||||||
descr->d_member->name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -289,7 +287,7 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
member_get_doc(PyMethodDescrObject *descr, void *closure)
|
method_get_doc(PyMethodDescrObject *descr, void *closure)
|
||||||
{
|
{
|
||||||
if (descr->d_method->ml_doc == NULL) {
|
if (descr->d_method->ml_doc == NULL) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
@ -298,12 +296,27 @@ member_get_doc(PyMethodDescrObject *descr, void *closure)
|
||||||
return PyString_FromString(descr->d_method->ml_doc);
|
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},
|
{"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
|
||||||
{"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
|
{"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
|
||||||
{0}
|
{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[] = {
|
static struct getsetlist member_getset[] = {
|
||||||
{"__doc__", (getter)member_get_doc},
|
{"__doc__", (getter)member_get_doc},
|
||||||
{0}
|
{0}
|
||||||
|
@ -355,7 +368,7 @@ static PyTypeObject PyMethodDescr_Type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
0, /* tp_methods */
|
0, /* tp_methods */
|
||||||
descr_members, /* tp_members */
|
descr_members, /* tp_members */
|
||||||
member_getset, /* tp_getset */
|
method_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
(descrgetfunc)method_get, /* tp_descr_get */
|
(descrgetfunc)method_get, /* tp_descr_get */
|
||||||
|
@ -393,7 +406,7 @@ static PyTypeObject PyMemberDescr_Type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
0, /* tp_methods */
|
0, /* tp_methods */
|
||||||
descr_members, /* tp_members */
|
descr_members, /* tp_members */
|
||||||
0, /* tp_getset */
|
member_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
(descrgetfunc)member_get, /* tp_descr_get */
|
(descrgetfunc)member_get, /* tp_descr_get */
|
||||||
|
@ -507,7 +520,7 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyDescr_NewMember(PyTypeObject *type, struct memberlist *member)
|
PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
|
||||||
{
|
{
|
||||||
PyMemberDescrObject *descr;
|
PyMemberDescrObject *descr;
|
||||||
|
|
||||||
|
|
|
@ -1383,10 +1383,13 @@ static PyMethodDef file_methods[] = {
|
||||||
|
|
||||||
#define OFF(x) offsetof(PyFileObject, x)
|
#define OFF(x) offsetof(PyFileObject, x)
|
||||||
|
|
||||||
static struct memberlist file_memberlist[] = {
|
static PyMemberDef file_memberlist[] = {
|
||||||
{"softspace", T_INT, OFF(f_softspace)},
|
{"softspace", T_INT, OFF(f_softspace), 0,
|
||||||
{"mode", T_OBJECT, OFF(f_mode), RO},
|
"flag indicating that a space needs to be printed; used by print"},
|
||||||
{"name", T_OBJECT, OFF(f_name), RO},
|
{"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 */
|
/* getattr(f, "closed") is implemented without this table */
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#define OFF(x) offsetof(PyFrameObject, x)
|
#define OFF(x) offsetof(PyFrameObject, x)
|
||||||
|
|
||||||
static struct memberlist frame_memberlist[] = {
|
static PyMemberDef frame_memberlist[] = {
|
||||||
{"f_back", T_OBJECT, OFF(f_back), RO},
|
{"f_back", T_OBJECT, OFF(f_back), RO},
|
||||||
{"f_code", T_OBJECT, OFF(f_code), RO},
|
{"f_code", T_OBJECT, OFF(f_code), RO},
|
||||||
{"f_builtins", T_OBJECT, OFF(f_builtins),RO},
|
{"f_builtins", T_OBJECT, OFF(f_builtins),RO},
|
||||||
|
|
|
@ -129,7 +129,7 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure)
|
||||||
|
|
||||||
#define RR ()
|
#define RR ()
|
||||||
|
|
||||||
static struct memberlist func_memberlist[] = {
|
static PyMemberDef func_memberlist[] = {
|
||||||
{"func_closure", T_OBJECT, OFF(func_closure),
|
{"func_closure", T_OBJECT, OFF(func_closure),
|
||||||
RESTRICTED|READONLY},
|
RESTRICTED|READONLY},
|
||||||
{"func_doc", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
|
{"func_doc", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
|
||||||
|
|
|
@ -9,7 +9,7 @@ typedef struct {
|
||||||
PyObject *md_dict;
|
PyObject *md_dict;
|
||||||
} PyModuleObject;
|
} PyModuleObject;
|
||||||
|
|
||||||
struct memberlist module_members[] = {
|
PyMemberDef module_members[] = {
|
||||||
{"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
|
{"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
|
@ -129,7 +129,7 @@ slice_repr(PySliceObject *r)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct memberlist slice_members[] = {
|
static PyMemberDef slice_members[] = {
|
||||||
{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
|
{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
|
||||||
{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
|
{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
|
||||||
{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
|
{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
static struct memberlist type_members[] = {
|
static PyMemberDef type_members[] = {
|
||||||
{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
|
{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
|
||||||
{"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY},
|
{"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY},
|
||||||
{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
|
{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
|
||||||
|
@ -263,7 +263,7 @@ typedef struct {
|
||||||
PyMappingMethods as_mapping;
|
PyMappingMethods as_mapping;
|
||||||
PyBufferProcs as_buffer;
|
PyBufferProcs as_buffer;
|
||||||
PyObject *name, *slots;
|
PyObject *name, *slots;
|
||||||
struct memberlist members[1];
|
PyMemberDef members[1];
|
||||||
} etype;
|
} etype;
|
||||||
|
|
||||||
/* type test with subclassing support */
|
/* type test with subclassing support */
|
||||||
|
@ -672,7 +672,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
|
||||||
PyObject *slots, *tmp;
|
PyObject *slots, *tmp;
|
||||||
PyTypeObject *type, *base, *tmptype, *winner;
|
PyTypeObject *type, *base, *tmptype, *winner;
|
||||||
etype *et;
|
etype *et;
|
||||||
struct memberlist *mp;
|
PyMemberDef *mp;
|
||||||
int i, nbases, nslots, slotoffset, dynamic, add_dict, add_weak;
|
int i, nbases, nslots, slotoffset, dynamic, add_dict, add_weak;
|
||||||
|
|
||||||
/* Special case: type(x) should return x->ob_type */
|
/* Special case: type(x) should return x->ob_type */
|
||||||
|
@ -1087,7 +1087,7 @@ PyTypeObject PyType_Type = {
|
||||||
0, /* ob_size */
|
0, /* ob_size */
|
||||||
"type", /* tp_name */
|
"type", /* tp_name */
|
||||||
sizeof(etype), /* tp_basicsize */
|
sizeof(etype), /* tp_basicsize */
|
||||||
sizeof(struct memberlist), /* tp_itemsize */
|
sizeof(PyMemberDef), /* tp_itemsize */
|
||||||
(destructor)type_dealloc, /* tp_dealloc */
|
(destructor)type_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
|
@ -1192,7 +1192,7 @@ object_free(PyObject *self)
|
||||||
PyObject_Del(self);
|
PyObject_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct memberlist object_members[] = {
|
static PyMemberDef object_members[] = {
|
||||||
{"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY},
|
{"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
@ -1263,7 +1263,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_members(PyTypeObject *type, struct memberlist *memb)
|
add_members(PyTypeObject *type, PyMemberDef *memb)
|
||||||
{
|
{
|
||||||
PyObject *dict = type->tp_defined;
|
PyObject *dict = type->tp_defined;
|
||||||
|
|
||||||
|
@ -3221,9 +3221,11 @@ typedef struct {
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
} superobject;
|
} superobject;
|
||||||
|
|
||||||
static struct memberlist super_members[] = {
|
static PyMemberDef super_members[] = {
|
||||||
{"__type__", T_OBJECT, offsetof(superobject, type), READONLY},
|
{"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY,
|
||||||
{"__obj__", T_OBJECT, offsetof(superobject, obj), READONLY},
|
"the class invoking super()"},
|
||||||
|
{"__self__", T_OBJECT, offsetof(superobject, obj), READONLY,
|
||||||
|
"the instance invoking super(); may be None"},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ static struct PyMethodDef gen_methods[] = {
|
||||||
{NULL, NULL} /* Sentinel */
|
{NULL, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct memberlist gen_memberlist[] = {
|
static PyMemberDef gen_memberlist[] = {
|
||||||
{"gi_frame", T_OBJECT, offsetof(genobject, gi_frame), RO},
|
{"gi_frame", T_OBJECT, offsetof(genobject, gi_frame), RO},
|
||||||
{"gi_running", T_INT, offsetof(genobject, gi_running), RO},
|
{"gi_running", T_INT, offsetof(genobject, gi_running), RO},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
|
|
@ -73,7 +73,7 @@ int Py_OptimizeFlag = 0;
|
||||||
|
|
||||||
#define OFF(x) offsetof(PyCodeObject, x)
|
#define OFF(x) offsetof(PyCodeObject, x)
|
||||||
|
|
||||||
static struct memberlist code_memberlist[] = {
|
static PyMemberDef code_memberlist[] = {
|
||||||
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
||||||
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
||||||
{"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
|
{"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
|
||||||
|
|
|
@ -32,226 +32,237 @@ PyObject *
|
||||||
PyMember_Get(char *addr, struct memberlist *mlist, char *name)
|
PyMember_Get(char *addr, struct memberlist *mlist, char *name)
|
||||||
{
|
{
|
||||||
struct memberlist *l;
|
struct memberlist *l;
|
||||||
|
|
||||||
if (strcmp(name, "__members__") == 0)
|
if (strcmp(name, "__members__") == 0)
|
||||||
return listmembers(mlist);
|
return listmembers(mlist);
|
||||||
for (l = mlist; l->name != NULL; l++) {
|
for (l = mlist; l->name != NULL; l++) {
|
||||||
if (strcmp(l->name, name) == 0) {
|
if (strcmp(l->name, name) == 0) {
|
||||||
PyObject *v;
|
PyMemberDef copy;
|
||||||
if ((l->flags & READ_RESTRICTED) &&
|
copy.name = l->name;
|
||||||
PyEval_GetRestricted()) {
|
copy.type = l->type;
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
copy.offset = l->offset;
|
||||||
"restricted attribute");
|
copy.flags = l->flags;
|
||||||
return NULL;
|
copy.doc = NULL;
|
||||||
}
|
return PyMember_GetOne(addr, ©);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
PyErr_SetString(PyExc_AttributeError, name);
|
||||||
return NULL;
|
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
|
int
|
||||||
PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
|
PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
|
||||||
{
|
{
|
||||||
struct memberlist *l;
|
struct memberlist *l;
|
||||||
PyObject *oldv;
|
|
||||||
|
|
||||||
for (l = mlist; l->name != NULL; l++) {
|
for (l = mlist; l->name != NULL; l++) {
|
||||||
if (strcmp(l->name, name) == 0) {
|
if (strcmp(l->name, name) == 0) {
|
||||||
if ((l->flags & READONLY) || l->type == T_STRING
|
PyMemberDef copy;
|
||||||
#ifdef macintosh
|
copy.name = l->name;
|
||||||
|| l->type == T_PSTRING
|
copy.type = l->type;
|
||||||
#endif
|
copy.offset = l->offset;
|
||||||
)
|
copy.flags = l->flags;
|
||||||
{
|
copy.doc = NULL;
|
||||||
PyErr_SetString(PyExc_TypeError,
|
return PyMember_SetOne(addr, ©, v);
|
||||||
"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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
PyErr_SetString(PyExc_AttributeError, name);
|
||||||
return -1;
|
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)
|
#define OFF(x) offsetof(PySymtableEntryObject, x)
|
||||||
|
|
||||||
static struct memberlist ste_memberlist[] = {
|
static PyMemberDef ste_memberlist[] = {
|
||||||
{"id", T_OBJECT, OFF(ste_id), READONLY},
|
{"id", T_OBJECT, OFF(ste_id), READONLY},
|
||||||
{"name", T_OBJECT, OFF(ste_name), READONLY},
|
{"name", T_OBJECT, OFF(ste_name), READONLY},
|
||||||
{"symbols", T_OBJECT, OFF(ste_symbols), READONLY},
|
{"symbols", T_OBJECT, OFF(ste_symbols), READONLY},
|
||||||
|
@ -119,12 +119,6 @@ static struct memberlist ste_memberlist[] = {
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
ste_getattr(PySymtableEntryObject *ste, char *name)
|
|
||||||
{
|
|
||||||
return PyMember_Get((char *)ste, ste_memberlist, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyTypeObject PySymtableEntry_Type = {
|
PyTypeObject PySymtableEntry_Type = {
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
PyObject_HEAD_INIT(&PyType_Type)
|
||||||
0,
|
0,
|
||||||
|
@ -133,7 +127,7 @@ PyTypeObject PySymtableEntry_Type = {
|
||||||
0,
|
0,
|
||||||
(destructor)ste_dealloc, /* tp_dealloc */
|
(destructor)ste_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
(getattrfunc)ste_getattr, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /* tp_compare */
|
0, /* tp_compare */
|
||||||
(reprfunc)ste_repr, /* tp_repr */
|
(reprfunc)ste_repr, /* tp_repr */
|
||||||
|
@ -143,9 +137,26 @@ PyTypeObject PySymtableEntry_Type = {
|
||||||
0, /* tp_hash */
|
0, /* tp_hash */
|
||||||
0, /* tp_call */
|
0, /* tp_call */
|
||||||
0, /* tp_str */
|
0, /* tp_str */
|
||||||
0, /* tp_getattro */
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||||
0, /* tp_doc */
|
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 */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue