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:
Neal Norwitz 2007-08-11 06:39:53 +00:00
parent 32ca442b13
commit 8dfc4a9bac
14 changed files with 83 additions and 195 deletions

View File

@ -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}

View File

@ -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 *);

View File

@ -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__',

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

@ -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;
} }
/************************************************************************ /************************************************************************

View File

@ -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"

View File

@ -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

View File

@ -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, &copy);
}
}
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, &copy, 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) \

View File

@ -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 */
}; };

View File

@ -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);
} }