Remove support for __members__ and __methods__. There still might be
some cleanup to do on this. Particularly in Python/traceback.c with getting rid of the getattr if possible and Demo/*metaclasses/Enum.py.
This commit is contained in:
parent
32ca442b13
commit
8dfc4a9bac
|
@ -2051,16 +2051,6 @@ A dictionary or other mapping object used to store an
|
||||||
object's (writable) attributes.
|
object's (writable) attributes.
|
||||||
\end{memberdesc}
|
\end{memberdesc}
|
||||||
|
|
||||||
\begin{memberdesc}[object]{__methods__}
|
|
||||||
\deprecated{2.2}{Use the built-in function \function{dir()} to get a
|
|
||||||
list of an object's attributes. This attribute is no longer available.}
|
|
||||||
\end{memberdesc}
|
|
||||||
|
|
||||||
\begin{memberdesc}[object]{__members__}
|
|
||||||
\deprecated{2.2}{Use the built-in function \function{dir()} to get a
|
|
||||||
list of an object's attributes. This attribute is no longer available.}
|
|
||||||
\end{memberdesc}
|
|
||||||
|
|
||||||
\begin{memberdesc}[instance]{__class__}
|
\begin{memberdesc}[instance]{__class__}
|
||||||
The class to which a class instance belongs.
|
The class to which a class instance belongs.
|
||||||
\end{memberdesc}
|
\end{memberdesc}
|
||||||
|
|
|
@ -19,20 +19,12 @@ extern "C" {
|
||||||
#define offsetof(type, member) ( (int) & ((type*)0) -> member )
|
#define offsetof(type, member) ( (int) & ((type*)0) -> member )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* An array of memberlist structures defines the name, type and offset
|
/* An array of PyMemberDef structures defines the name, type and offset
|
||||||
of selected members of a C structure. These can be read by
|
of selected members of a C structure. These can be read by
|
||||||
PyMember_Get() and set by PyMember_Set() (except if their READONLY flag
|
PyMember_GetOne() and set by PyMember_SetOne() (except if their READONLY
|
||||||
is set). The array must be terminated with an entry whose name
|
flag is set). The array must be terminated with an entry whose name
|
||||||
pointer is NULL. */
|
pointer is NULL. */
|
||||||
|
|
||||||
struct memberlist {
|
|
||||||
/* Obsolete version, for binary backwards compatibility */
|
|
||||||
char *name;
|
|
||||||
int type;
|
|
||||||
int offset;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct PyMemberDef {
|
typedef struct PyMemberDef {
|
||||||
/* Current version, use this */
|
/* Current version, use this */
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -76,16 +68,11 @@ typedef struct PyMemberDef {
|
||||||
|
|
||||||
/* Flags */
|
/* Flags */
|
||||||
#define READONLY 1
|
#define READONLY 1
|
||||||
#define RO READONLY /* Shorthand */
|
|
||||||
#define READ_RESTRICTED 2
|
#define READ_RESTRICTED 2
|
||||||
#define WRITE_RESTRICTED 4
|
#define WRITE_RESTRICTED 4
|
||||||
#define RESTRICTED (READ_RESTRICTED | WRITE_RESTRICTED)
|
#define RESTRICTED (READ_RESTRICTED | WRITE_RESTRICTED)
|
||||||
|
|
||||||
|
|
||||||
/* Obsolete API, for binary backwards compatibility */
|
|
||||||
PyAPI_FUNC(PyObject *) PyMember_Get(const char *, struct memberlist *, const char *);
|
|
||||||
PyAPI_FUNC(int) PyMember_Set(char *, struct memberlist *, const char *, PyObject *);
|
|
||||||
|
|
||||||
/* Current API, use this */
|
/* Current API, use this */
|
||||||
PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *);
|
PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *);
|
||||||
PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *);
|
PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *);
|
||||||
|
|
|
@ -162,15 +162,7 @@ For instance of built-in types, x.__class__ is now the same as type(x):
|
||||||
True
|
True
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
Under the new proposal, the __methods__ attribute no longer exists:
|
You can get the information from the list type:
|
||||||
|
|
||||||
>>> [].__methods__
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
AttributeError: 'list' object has no attribute '__methods__'
|
|
||||||
>>>
|
|
||||||
|
|
||||||
Instead, you can get the same information from the list type:
|
|
||||||
|
|
||||||
>>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted
|
>>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted
|
||||||
['__add__',
|
['__add__',
|
||||||
|
|
|
@ -52,14 +52,6 @@ class TracebackCases(unittest.TestCase):
|
||||||
self.assert_("^" in err[2])
|
self.assert_("^" in err[2])
|
||||||
self.assertEqual(err[1].find(")"), err[2].find("^"))
|
self.assertEqual(err[1].find(")"), err[2].find("^"))
|
||||||
|
|
||||||
def test_members(self):
|
|
||||||
# Covers Python/structmember.c::listmembers()
|
|
||||||
try:
|
|
||||||
1/0
|
|
||||||
except:
|
|
||||||
import sys
|
|
||||||
sys.exc_info()[2].__members__
|
|
||||||
|
|
||||||
def test_base_exception(self):
|
def test_base_exception(self):
|
||||||
# Test that exceptions derived from BaseException are formatted right
|
# Test that exceptions derived from BaseException are formatted right
|
||||||
e = KeyboardInterrupt()
|
e = KeyboardInterrupt()
|
||||||
|
|
|
@ -75,6 +75,8 @@ Core and Builtins
|
||||||
its argument, if it exists. If not, it will work like before. This allows
|
its argument, if it exists. If not, it will work like before. This allows
|
||||||
customizing the output of dir() in the presence of a __getattr__().
|
customizing the output of dir() in the presence of a __getattr__().
|
||||||
|
|
||||||
|
- Removed support for __members__ and __methods__.
|
||||||
|
|
||||||
- Removed indexing/slicing on BaseException.
|
- Removed indexing/slicing on BaseException.
|
||||||
|
|
||||||
- input() became raw_input(): the name input() now implements the
|
- input() became raw_input(): the name input() now implements the
|
||||||
|
@ -219,7 +221,7 @@ C API
|
||||||
__coerce__, __div__, __idiv__, __rdiv__
|
__coerce__, __div__, __idiv__, __rdiv__
|
||||||
|
|
||||||
- Removed these C APIs:
|
- Removed these C APIs:
|
||||||
PyNumber_Coerce(), PyNumber_CoerceEx()
|
PyNumber_Coerce(), PyNumber_CoerceEx(), PyMember_Get, PyMember_Set
|
||||||
|
|
||||||
- Removed these C slots/fields:
|
- Removed these C slots/fields:
|
||||||
nb_divide, nb_inplace_divide
|
nb_divide, nb_inplace_divide
|
||||||
|
@ -229,7 +231,8 @@ C API
|
||||||
|
|
||||||
- Removed these typedefs:
|
- Removed these typedefs:
|
||||||
intargfunc, intintargfunc, intobjargproc, intintobjargproc,
|
intargfunc, intintargfunc, intobjargproc, intintobjargproc,
|
||||||
getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc
|
getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc,
|
||||||
|
memberlist
|
||||||
|
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
|
|
|
@ -17,8 +17,6 @@ Limit of NNNN is fine.
|
||||||
It ends when Python causes a segmentation fault because the limit is
|
It ends when Python causes a segmentation fault because the limit is
|
||||||
too high. On platforms like Mac and Windows, it should exit with a
|
too high. On platforms like Mac and Windows, it should exit with a
|
||||||
MemoryError.
|
MemoryError.
|
||||||
|
|
||||||
NB: A program that does not use __methods__ can set a higher limit.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1400,6 +1400,12 @@ xmlparse_getattr(xmlparseobject *self, char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Py_FindMethod(xmlparse_methods, (PyObject *)self, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
xmlparse_dir(PyObject *self, PyObject* noargs)
|
||||||
|
{
|
||||||
#define APPEND(list, str) \
|
#define APPEND(list, str) \
|
||||||
do { \
|
do { \
|
||||||
PyObject *o = PyString_FromString(str); \
|
PyObject *o = PyString_FromString(str); \
|
||||||
|
@ -1408,36 +1414,39 @@ xmlparse_getattr(xmlparseobject *self, char *name)
|
||||||
Py_XDECREF(o); \
|
Py_XDECREF(o); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
if (strcmp(name, "__members__") == 0) {
|
int i;
|
||||||
int i;
|
PyObject *rc = PyList_New(0);
|
||||||
PyObject *rc = PyList_New(0);
|
if (!rc)
|
||||||
if (!rc)
|
return NULL;
|
||||||
return NULL;
|
for (i = 0; handler_info[i].name != NULL; i++) {
|
||||||
for (i = 0; handler_info[i].name != NULL; i++) {
|
PyObject *o = get_handler_name(&handler_info[i]);
|
||||||
PyObject *o = get_handler_name(&handler_info[i]);
|
if (o != NULL)
|
||||||
if (o != NULL)
|
PyList_Append(rc, o);
|
||||||
PyList_Append(rc, o);
|
Py_XDECREF(o);
|
||||||
Py_XDECREF(o);
|
}
|
||||||
}
|
APPEND(rc, "ErrorCode");
|
||||||
APPEND(rc, "ErrorCode");
|
APPEND(rc, "ErrorLineNumber");
|
||||||
APPEND(rc, "ErrorLineNumber");
|
APPEND(rc, "ErrorColumnNumber");
|
||||||
APPEND(rc, "ErrorColumnNumber");
|
APPEND(rc, "ErrorByteIndex");
|
||||||
APPEND(rc, "ErrorByteIndex");
|
APPEND(rc, "CurrentLineNumber");
|
||||||
APPEND(rc, "CurrentLineNumber");
|
APPEND(rc, "CurrentColumnNumber");
|
||||||
APPEND(rc, "CurrentColumnNumber");
|
APPEND(rc, "CurrentByteIndex");
|
||||||
APPEND(rc, "CurrentByteIndex");
|
APPEND(rc, "buffer_size");
|
||||||
APPEND(rc, "buffer_size");
|
APPEND(rc, "buffer_text");
|
||||||
APPEND(rc, "buffer_text");
|
APPEND(rc, "buffer_used");
|
||||||
APPEND(rc, "buffer_used");
|
APPEND(rc, "namespace_prefixes");
|
||||||
APPEND(rc, "namespace_prefixes");
|
APPEND(rc, "ordered_attributes");
|
||||||
APPEND(rc, "ordered_attributes");
|
APPEND(rc, "specified_attributes");
|
||||||
APPEND(rc, "specified_attributes");
|
APPEND(rc, "intern");
|
||||||
APPEND(rc, "intern");
|
|
||||||
|
|
||||||
#undef APPEND
|
#undef APPEND
|
||||||
return rc;
|
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
Py_DECREF(rc);
|
||||||
|
rc = NULL;
|
||||||
}
|
}
|
||||||
return Py_FindMethod(xmlparse_methods, (PyObject *)self, name);
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1560,6 +1569,10 @@ xmlparse_clear(xmlparseobject *op)
|
||||||
|
|
||||||
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
|
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
|
||||||
|
|
||||||
|
static PyMethodDef xmlparse_tp_methods[] = {
|
||||||
|
{"__dir__", xmlparse_dir, METH_NOARGS}
|
||||||
|
};
|
||||||
|
|
||||||
static PyTypeObject Xmlparsetype = {
|
static PyTypeObject Xmlparsetype = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"pyexpat.xmlparser", /*tp_name*/
|
"pyexpat.xmlparser", /*tp_name*/
|
||||||
|
@ -1588,7 +1601,12 @@ static PyTypeObject Xmlparsetype = {
|
||||||
#endif
|
#endif
|
||||||
Xmlparsetype__doc__, /* tp_doc - Documentation string */
|
Xmlparsetype__doc__, /* tp_doc - Documentation string */
|
||||||
(traverseproc)xmlparse_traverse, /* tp_traverse */
|
(traverseproc)xmlparse_traverse, /* tp_traverse */
|
||||||
(inquiry)xmlparse_clear /* tp_clear */
|
(inquiry)xmlparse_clear, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
xmlparse_tp_methods /* tp_methods */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* End of code for xmlparser objects */
|
/* End of code for xmlparser objects */
|
||||||
|
|
|
@ -275,47 +275,12 @@ PyTypeObject PyCFunction_Type = {
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* List all methods in a chain -- helper for findmethodinchain */
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
listmethodchain(PyMethodChain *chain)
|
|
||||||
{
|
|
||||||
PyMethodChain *c;
|
|
||||||
PyMethodDef *ml;
|
|
||||||
int i, n;
|
|
||||||
PyObject *v;
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
for (c = chain; c != NULL; c = c->link) {
|
|
||||||
for (ml = c->methods; ml->ml_name != NULL; ml++)
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
v = PyList_New(n);
|
|
||||||
if (v == NULL)
|
|
||||||
return NULL;
|
|
||||||
i = 0;
|
|
||||||
for (c = chain; c != NULL; c = c->link) {
|
|
||||||
for (ml = c->methods; ml->ml_name != NULL; ml++) {
|
|
||||||
PyList_SetItem(v, i, PyUnicode_FromString(ml->ml_name));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyList_Sort(v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find a method in a method chain */
|
/* Find a method in a method chain */
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
|
Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
|
||||||
{
|
{
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
if (name[0] == '_' && name[1] == '_') {
|
||||||
if (strcmp(name, "__methods__") == 0)
|
|
||||||
return listmethodchain(chain);
|
|
||||||
if (strcmp(name, "__doc__") == 0) {
|
if (strcmp(name, "__doc__") == 0) {
|
||||||
const char *doc = self->ob_type->tp_doc;
|
const char *doc = self->ob_type->tp_doc;
|
||||||
if (doc != NULL)
|
if (doc != NULL)
|
||||||
|
|
|
@ -473,8 +473,8 @@ PyTypeObject PyHKEY_Type =
|
||||||
|
|
||||||
#define OFF(e) offsetof(PyHKEYObject, e)
|
#define OFF(e) offsetof(PyHKEYObject, e)
|
||||||
|
|
||||||
static struct memberlist PyHKEY_memberlist[] = {
|
static PyMemberDef PyHKEY_memberlist[] = {
|
||||||
{"handle", T_INT, OFF(hkey)},
|
{"handle", T_INT, OFF(hkey), READONLY},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -523,7 +523,10 @@ PyHKEY_getattr(PyObject *self, const char *name)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
if (strcmp(name, "handle") == 0)
|
if (strcmp(name, "handle") == 0)
|
||||||
return PyLong_FromVoidPtr(((PyHKEYObject *)self)->hkey);
|
return PyLong_FromVoidPtr(((PyHKEYObject *)self)->hkey);
|
||||||
return PyMember_Get((char *)self, PyHKEY_memberlist, name);
|
PyErr_Format(PyExc_AttributeError,
|
||||||
|
"'%.50s' object has no attribute '%.400s'",
|
||||||
|
Py_Type(self)->tp_name, name);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
|
|
@ -1091,10 +1091,8 @@ EXPORTS
|
||||||
"_Py_QnewFlag"
|
"_Py_QnewFlag"
|
||||||
|
|
||||||
; From python25_s.lib(structmember)
|
; From python25_s.lib(structmember)
|
||||||
"PyMember_Get"
|
|
||||||
"PyMember_GetOne"
|
"PyMember_GetOne"
|
||||||
"PyMember_SetOne"
|
"PyMember_SetOne"
|
||||||
"PyMember_Set"
|
|
||||||
|
|
||||||
; From python25_s.lib(symtable)
|
; From python25_s.lib(symtable)
|
||||||
"PySymtable_Build"
|
"PySymtable_Build"
|
||||||
|
|
|
@ -244,8 +244,6 @@ EXPORTS
|
||||||
PyMem_Free
|
PyMem_Free
|
||||||
PyMem_Malloc
|
PyMem_Malloc
|
||||||
PyMem_Realloc
|
PyMem_Realloc
|
||||||
PyMember_Get
|
|
||||||
PyMember_Set
|
|
||||||
PyMethod_Class
|
PyMethod_Class
|
||||||
PyMethod_Fini
|
PyMethod_Fini
|
||||||
PyMethod_Function
|
PyMethod_Function
|
||||||
|
|
|
@ -5,51 +5,6 @@
|
||||||
|
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
listmembers(struct memberlist *mlist)
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
PyObject *v;
|
|
||||||
for (n = 0; mlist[n].name != NULL; n++)
|
|
||||||
;
|
|
||||||
v = PyList_New(n);
|
|
||||||
if (v != NULL) {
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
PyList_SetItem(v, i,
|
|
||||||
PyString_FromString(mlist[i].name));
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
v = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyList_Sort(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
PyMember_Get(const char *addr, struct memberlist *mlist, const 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) {
|
|
||||||
PyMemberDef copy;
|
|
||||||
copy.name = l->name;
|
|
||||||
copy.type = l->type;
|
|
||||||
copy.offset = l->offset;
|
|
||||||
copy.flags = l->flags;
|
|
||||||
copy.doc = NULL;
|
|
||||||
return PyMember_GetOne(addr, ©);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyMember_GetOne(const char *addr, PyMemberDef *l)
|
PyMember_GetOne(const char *addr, PyMemberDef *l)
|
||||||
{
|
{
|
||||||
|
@ -135,27 +90,6 @@ PyMember_GetOne(const char *addr, PyMemberDef *l)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v)
|
|
||||||
{
|
|
||||||
struct memberlist *l;
|
|
||||||
|
|
||||||
for (l = mlist; l->name != NULL; l++) {
|
|
||||||
if (strcmp(l->name, name) == 0) {
|
|
||||||
PyMemberDef copy;
|
|
||||||
copy.name = l->name;
|
|
||||||
copy.type = l->type;
|
|
||||||
copy.offset = l->offset;
|
|
||||||
copy.flags = l->flags;
|
|
||||||
copy.doc = NULL;
|
|
||||||
return PyMember_SetOne(addr, ©, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WARN(msg) \
|
#define WARN(msg) \
|
||||||
do { \
|
do { \
|
||||||
if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
|
if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
|
||||||
|
|
|
@ -11,18 +11,28 @@
|
||||||
|
|
||||||
#define OFF(x) offsetof(PyTracebackObject, x)
|
#define OFF(x) offsetof(PyTracebackObject, x)
|
||||||
|
|
||||||
static struct memberlist tb_memberlist[] = {
|
static PyMemberDef tb_memberlist[] = {
|
||||||
{"tb_next", T_OBJECT, OFF(tb_next)},
|
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
|
||||||
{"tb_frame", T_OBJECT, OFF(tb_frame)},
|
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
|
||||||
{"tb_lasti", T_INT, OFF(tb_lasti)},
|
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
|
||||||
{"tb_lineno", T_INT, OFF(tb_lineno)},
|
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* XXX(nnorwitz): can we get rid of tb_getattr and use tp_members? */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
tb_getattr(PyTracebackObject *tb, char *name)
|
tb_getattr(PyTracebackObject *tb, char *name)
|
||||||
{
|
{
|
||||||
return PyMember_Get((char *)tb, tb_memberlist, name);
|
int i;
|
||||||
|
for (i = 0; tb_memberlist[i].name != NULL; i++) {
|
||||||
|
if (strcmp(name, tb_memberlist[i].name) == 0)
|
||||||
|
return PyMember_GetOne((const char *)tb,
|
||||||
|
tb_memberlist + i);
|
||||||
|
}
|
||||||
|
PyErr_Format(PyExc_AttributeError,
|
||||||
|
"'%.50s' object has no attribute '%.400s'",
|
||||||
|
Py_Type(tb)->tp_name, name);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -80,8 +90,8 @@ PyTypeObject PyTraceBack_Type = {
|
||||||
0, /* tp_iter */
|
0, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
0, /* tp_methods */
|
0, /* tp_methods */
|
||||||
0, /* tp_members */
|
0, /* tp_members */
|
||||||
0, /* tp_getset */
|
0, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
#define OFF(x) offsetof(XXXXobject, x)
|
#define OFF(x) offsetof(XXXXobject, x)
|
||||||
|
|
||||||
static struct memberlist $abbrev$_memberlist[] = {
|
static PyMemberDef $abbrev$_memberlist[] = {
|
||||||
/* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
|
/* XXXX Add lines like { "foo", T_INT, OFF(foo), READONLY } */
|
||||||
|
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,7 @@ $abbrev$_getattr($abbrev$object *self, char *name)
|
||||||
PyObject *rv;
|
PyObject *rv;
|
||||||
|
|
||||||
/* XXXX Add your own getattr code here */
|
/* XXXX Add your own getattr code here */
|
||||||
rv = PyMember_Get((char *)/*XXXX*/0, $abbrev$_memberlist, name);
|
rv = PyMember_GetOne((char *)/*XXXX*/0, &$abbrev$_memberlist[i]);
|
||||||
if (rv)
|
if (rv)
|
||||||
return rv;
|
return rv;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
@ -33,5 +33,5 @@ $abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
|
||||||
PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
|
PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return PyMember_Set((char *)/*XXXX*/0, $abbrev$_memberlist, name, v);
|
return PyMember_SetOne((char *)/*XXXX*/0, &$abbrev$_memberlist[i], v);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue