From 8dfc4a9baca7b039048b6e1dab3e4eb09f7af463 Mon Sep 17 00:00:00 2001 From: Neal Norwitz Date: Sat, 11 Aug 2007 06:39:53 +0000 Subject: 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. --- Doc/lib/libstdtypes.tex | 10 ---- Include/structmember.h | 19 ++------ Lib/test/test_descrtut.py | 10 +--- Lib/test/test_traceback.py | 8 ---- Misc/NEWS | 7 ++- Misc/find_recursionlimit.py | 2 - Modules/pyexpat.c | 74 +++++++++++++++++++----------- Objects/methodobject.c | 35 -------------- PC/_winreg.c | 9 ++-- PC/os2emx/python25.def | 2 - PC/os2vacpp/python.def | 2 - Python/structmember.c | 66 -------------------------- Python/traceback.c | 26 +++++++---- Tools/modulator/Templates/object_structure | 8 ++-- 14 files changed, 83 insertions(+), 195 deletions(-) diff --git a/Doc/lib/libstdtypes.tex b/Doc/lib/libstdtypes.tex index ef84157..99c54d8 100644 --- a/Doc/lib/libstdtypes.tex +++ b/Doc/lib/libstdtypes.tex @@ -2051,16 +2051,6 @@ A dictionary or other mapping object used to store an object's (writable) attributes. \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__} The class to which a class instance belongs. \end{memberdesc} diff --git a/Include/structmember.h b/Include/structmember.h index b7d00b7..10555b1 100644 --- a/Include/structmember.h +++ b/Include/structmember.h @@ -19,20 +19,12 @@ extern "C" { #define offsetof(type, member) ( (int) & ((type*)0) -> member ) #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 - PyMember_Get() and set by PyMember_Set() (except if their READONLY flag - is set). The array must be terminated with an entry whose name + PyMember_GetOne() and set by PyMember_SetOne() (except if their READONLY + flag is set). The array must be terminated with an entry whose name 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; @@ -76,16 +68,11 @@ typedef struct PyMemberDef { /* Flags */ #define READONLY 1 -#define RO READONLY /* Shorthand */ #define READ_RESTRICTED 2 #define WRITE_RESTRICTED 4 #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 */ PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *); PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *); diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py index 5b11666..fe29f34 100644 --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -162,15 +162,7 @@ For instance of built-in types, x.__class__ is now the same as type(x): True >>> -Under the new proposal, the __methods__ attribute no longer exists: - - >>> [].__methods__ - Traceback (most recent call last): - File "", line 1, in ? - AttributeError: 'list' object has no attribute '__methods__' - >>> - -Instead, you can get the same information from the list type: +You can get the information from the list type: >>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted ['__add__', diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 5cd300a..84d7290 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -52,14 +52,6 @@ class TracebackCases(unittest.TestCase): self.assert_("^" in err[2]) 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): # Test that exceptions derived from BaseException are formatted right e = KeyboardInterrupt() diff --git a/Misc/NEWS b/Misc/NEWS index dc64954..09d1302 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -75,6 +75,8 @@ Core and Builtins 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__(). +- Removed support for __members__ and __methods__. + - Removed indexing/slicing on BaseException. - input() became raw_input(): the name input() now implements the @@ -219,7 +221,7 @@ C API __coerce__, __div__, __idiv__, __rdiv__ - Removed these C APIs: - PyNumber_Coerce(), PyNumber_CoerceEx() + PyNumber_Coerce(), PyNumber_CoerceEx(), PyMember_Get, PyMember_Set - Removed these C slots/fields: nb_divide, nb_inplace_divide @@ -229,7 +231,8 @@ C API - Removed these typedefs: intargfunc, intintargfunc, intobjargproc, intintobjargproc, - getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc + getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc, + memberlist Tests diff --git a/Misc/find_recursionlimit.py b/Misc/find_recursionlimit.py index e6454c9c3..32bdae4 100644 --- a/Misc/find_recursionlimit.py +++ b/Misc/find_recursionlimit.py @@ -17,8 +17,6 @@ Limit of NNNN is fine. 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 MemoryError. - -NB: A program that does not use __methods__ can set a higher limit. """ import sys diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 8638b2e..02c5d40 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -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) \ do { \ PyObject *o = PyString_FromString(str); \ @@ -1408,36 +1414,39 @@ xmlparse_getattr(xmlparseobject *self, char *name) Py_XDECREF(o); \ } while (0) - if (strcmp(name, "__members__") == 0) { - int i; - PyObject *rc = PyList_New(0); - if (!rc) - return NULL; - for (i = 0; handler_info[i].name != NULL; i++) { - PyObject *o = get_handler_name(&handler_info[i]); - if (o != NULL) - PyList_Append(rc, o); - Py_XDECREF(o); - } - APPEND(rc, "ErrorCode"); - APPEND(rc, "ErrorLineNumber"); - APPEND(rc, "ErrorColumnNumber"); - APPEND(rc, "ErrorByteIndex"); - APPEND(rc, "CurrentLineNumber"); - APPEND(rc, "CurrentColumnNumber"); - APPEND(rc, "CurrentByteIndex"); - APPEND(rc, "buffer_size"); - APPEND(rc, "buffer_text"); - APPEND(rc, "buffer_used"); - APPEND(rc, "namespace_prefixes"); - APPEND(rc, "ordered_attributes"); - APPEND(rc, "specified_attributes"); - APPEND(rc, "intern"); + int i; + PyObject *rc = PyList_New(0); + if (!rc) + return NULL; + for (i = 0; handler_info[i].name != NULL; i++) { + PyObject *o = get_handler_name(&handler_info[i]); + if (o != NULL) + PyList_Append(rc, o); + Py_XDECREF(o); + } + APPEND(rc, "ErrorCode"); + APPEND(rc, "ErrorLineNumber"); + APPEND(rc, "ErrorColumnNumber"); + APPEND(rc, "ErrorByteIndex"); + APPEND(rc, "CurrentLineNumber"); + APPEND(rc, "CurrentColumnNumber"); + APPEND(rc, "CurrentByteIndex"); + APPEND(rc, "buffer_size"); + APPEND(rc, "buffer_text"); + APPEND(rc, "buffer_used"); + APPEND(rc, "namespace_prefixes"); + APPEND(rc, "ordered_attributes"); + APPEND(rc, "specified_attributes"); + APPEND(rc, "intern"); #undef APPEND - return rc; + + if (PyErr_Occurred()) { + Py_DECREF(rc); + rc = NULL; } - return Py_FindMethod(xmlparse_methods, (PyObject *)self, name); + + return rc; } static int @@ -1560,6 +1569,10 @@ xmlparse_clear(xmlparseobject *op) PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); +static PyMethodDef xmlparse_tp_methods[] = { + {"__dir__", xmlparse_dir, METH_NOARGS} +}; + static PyTypeObject Xmlparsetype = { PyVarObject_HEAD_INIT(NULL, 0) "pyexpat.xmlparser", /*tp_name*/ @@ -1588,7 +1601,12 @@ static PyTypeObject Xmlparsetype = { #endif Xmlparsetype__doc__, /* tp_doc - Documentation string */ (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 */ diff --git a/Objects/methodobject.c b/Objects/methodobject.c index f47037b..5f5d595 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -275,47 +275,12 @@ PyTypeObject PyCFunction_Type = { 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 */ PyObject * Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name) { if (name[0] == '_' && name[1] == '_') { - if (strcmp(name, "__methods__") == 0) - return listmethodchain(chain); if (strcmp(name, "__doc__") == 0) { const char *doc = self->ob_type->tp_doc; if (doc != NULL) diff --git a/PC/_winreg.c b/PC/_winreg.c index c294653..135be32 100644 --- a/PC/_winreg.c +++ b/PC/_winreg.c @@ -473,8 +473,8 @@ PyTypeObject PyHKEY_Type = #define OFF(e) offsetof(PyHKEYObject, e) -static struct memberlist PyHKEY_memberlist[] = { - {"handle", T_INT, OFF(hkey)}, +static PyMemberDef PyHKEY_memberlist[] = { + {"handle", T_INT, OFF(hkey), READONLY}, {NULL} /* Sentinel */ }; @@ -523,7 +523,10 @@ PyHKEY_getattr(PyObject *self, const char *name) PyErr_Clear(); if (strcmp(name, "handle") == 0) 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; } /************************************************************************ diff --git a/PC/os2emx/python25.def b/PC/os2emx/python25.def index ef6bd13..6aa2e62 100644 --- a/PC/os2emx/python25.def +++ b/PC/os2emx/python25.def @@ -1091,10 +1091,8 @@ EXPORTS "_Py_QnewFlag" ; From python25_s.lib(structmember) - "PyMember_Get" "PyMember_GetOne" "PyMember_SetOne" - "PyMember_Set" ; From python25_s.lib(symtable) "PySymtable_Build" diff --git a/PC/os2vacpp/python.def b/PC/os2vacpp/python.def index b336445..55a17d7 100644 --- a/PC/os2vacpp/python.def +++ b/PC/os2vacpp/python.def @@ -244,8 +244,6 @@ EXPORTS PyMem_Free PyMem_Malloc PyMem_Realloc - PyMember_Get - PyMember_Set PyMethod_Class PyMethod_Fini PyMethod_Function diff --git a/Python/structmember.c b/Python/structmember.c index 041f29b..e0014c4 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -5,51 +5,6 @@ #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 * PyMember_GetOne(const char *addr, PyMemberDef *l) { @@ -135,27 +90,6 @@ PyMember_GetOne(const char *addr, PyMemberDef *l) 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) \ do { \ if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \ diff --git a/Python/traceback.c b/Python/traceback.c index 370f3fd..0e24196 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -11,18 +11,28 @@ #define OFF(x) offsetof(PyTracebackObject, x) -static struct memberlist tb_memberlist[] = { - {"tb_next", T_OBJECT, OFF(tb_next)}, - {"tb_frame", T_OBJECT, OFF(tb_frame)}, - {"tb_lasti", T_INT, OFF(tb_lasti)}, - {"tb_lineno", T_INT, OFF(tb_lineno)}, +static PyMemberDef tb_memberlist[] = { + {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, + {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, + {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, + {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, {NULL} /* Sentinel */ }; +/* XXX(nnorwitz): can we get rid of tb_getattr and use tp_members? */ static PyObject * 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 @@ -80,8 +90,8 @@ PyTypeObject PyTraceBack_Type = { 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ + 0, /* tp_members */ + 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ }; diff --git a/Tools/modulator/Templates/object_structure b/Tools/modulator/Templates/object_structure index 573ac8d..78daa62 100644 --- a/Tools/modulator/Templates/object_structure +++ b/Tools/modulator/Templates/object_structure @@ -5,8 +5,8 @@ #define OFF(x) offsetof(XXXXobject, x) -static struct memberlist $abbrev$_memberlist[] = { - /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ +static PyMemberDef $abbrev$_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), READONLY } */ {NULL} /* Sentinel */ }; @@ -17,7 +17,7 @@ $abbrev$_getattr($abbrev$object *self, char *name) PyObject *rv; /* 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) return rv; PyErr_Clear(); @@ -33,5 +33,5 @@ $abbrev$_setattr($abbrev$object *self, char *name, PyObject *v) PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); return -1; } - return PyMember_Set((char *)/*XXXX*/0, $abbrev$_memberlist, name, v); + return PyMember_SetOne((char *)/*XXXX*/0, &$abbrev$_memberlist[i], v); } -- cgit v0.12