Skip to content

Commit 8dfc4a9

Browse files
committed
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.
1 parent 32ca442 commit 8dfc4a9

File tree

14 files changed

+83
-195
lines changed

14 files changed

+83
-195
lines changed

Doc/lib/libstdtypes.tex

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,16 +2051,6 @@ \section{Special Attributes \label{specialattrs}}
20512051
object's (writable) attributes.
20522052
\end{memberdesc}
20532053

2054-
\begin{memberdesc}[object]{__methods__}
2055-
\deprecated{2.2}{Use the built-in function \function{dir()} to get a
2056-
list of an object's attributes. This attribute is no longer available.}
2057-
\end{memberdesc}
2058-
2059-
\begin{memberdesc}[object]{__members__}
2060-
\deprecated{2.2}{Use the built-in function \function{dir()} to get a
2061-
list of an object's attributes. This attribute is no longer available.}
2062-
\end{memberdesc}
2063-
20642054
\begin{memberdesc}[instance]{__class__}
20652055
The class to which a class instance belongs.
20662056
\end{memberdesc}

Include/structmember.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,12 @@ extern "C" {
1919
#define offsetof(type, member) ( (int) & ((type*)0) -> member )
2020
#endif
2121

22-
/* An array of memberlist structures defines the name, type and offset
22+
/* An array of PyMemberDef structures defines the name, type and offset
2323
of selected members of a C structure. These can be read by
24-
PyMember_Get() and set by PyMember_Set() (except if their READONLY flag
25-
is set). The array must be terminated with an entry whose name
24+
PyMember_GetOne() and set by PyMember_SetOne() (except if their READONLY
25+
flag is set). The array must be terminated with an entry whose name
2626
pointer is NULL. */
2727

28-
struct memberlist {
29-
/* Obsolete version, for binary backwards compatibility */
30-
char *name;
31-
int type;
32-
int offset;
33-
int flags;
34-
};
35-
3628
typedef struct PyMemberDef {
3729
/* Current version, use this */
3830
char *name;
@@ -76,16 +68,11 @@ typedef struct PyMemberDef {
7668

7769
/* Flags */
7870
#define READONLY 1
79-
#define RO READONLY /* Shorthand */
8071
#define READ_RESTRICTED 2
8172
#define WRITE_RESTRICTED 4
8273
#define RESTRICTED (READ_RESTRICTED | WRITE_RESTRICTED)
8374

8475

85-
/* Obsolete API, for binary backwards compatibility */
86-
PyAPI_FUNC(PyObject *) PyMember_Get(const char *, struct memberlist *, const char *);
87-
PyAPI_FUNC(int) PyMember_Set(char *, struct memberlist *, const char *, PyObject *);
88-
8976
/* Current API, use this */
9077
PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *);
9178
PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *);

Lib/test/test_descrtut.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,7 @@ def merge(self, other):
162162
True
163163
>>>
164164
165-
Under the new proposal, the __methods__ attribute no longer exists:
166-
167-
>>> [].__methods__
168-
Traceback (most recent call last):
169-
File "<stdin>", line 1, in ?
170-
AttributeError: 'list' object has no attribute '__methods__'
171-
>>>
172-
173-
Instead, you can get the same information from the list type:
165+
You can get the information from the list type:
174166
175167
>>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted
176168
['__add__',

Lib/test/test_traceback.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,6 @@ def test_bad_indentation(self):
5252
self.assert_("^" in err[2])
5353
self.assertEqual(err[1].find(")"), err[2].find("^"))
5454

55-
def test_members(self):
56-
# Covers Python/structmember.c::listmembers()
57-
try:
58-
1/0
59-
except:
60-
import sys
61-
sys.exc_info()[2].__members__
62-
6355
def test_base_exception(self):
6456
# Test that exceptions derived from BaseException are formatted right
6557
e = KeyboardInterrupt()

Misc/NEWS

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ Core and Builtins
7575
its argument, if it exists. If not, it will work like before. This allows
7676
customizing the output of dir() in the presence of a __getattr__().
7777

78+
- Removed support for __members__ and __methods__.
79+
7880
- Removed indexing/slicing on BaseException.
7981

8082
- input() became raw_input(): the name input() now implements the
@@ -219,7 +221,7 @@ C API
219221
__coerce__, __div__, __idiv__, __rdiv__
220222

221223
- Removed these C APIs:
222-
PyNumber_Coerce(), PyNumber_CoerceEx()
224+
PyNumber_Coerce(), PyNumber_CoerceEx(), PyMember_Get, PyMember_Set
223225

224226
- Removed these C slots/fields:
225227
nb_divide, nb_inplace_divide
@@ -229,7 +231,8 @@ C API
229231

230232
- Removed these typedefs:
231233
intargfunc, intintargfunc, intobjargproc, intintobjargproc,
232-
getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc
234+
getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc,
235+
memberlist
233236

234237

235238
Tests

Misc/find_recursionlimit.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
It ends when Python causes a segmentation fault because the limit is
1818
too high. On platforms like Mac and Windows, it should exit with a
1919
MemoryError.
20-
21-
NB: A program that does not use __methods__ can set a higher limit.
2220
"""
2321

2422
import sys

Modules/pyexpat.c

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,12 @@ xmlparse_getattr(xmlparseobject *self, char *name)
14001400
}
14011401
}
14021402

1403+
return Py_FindMethod(xmlparse_methods, (PyObject *)self, name);
1404+
}
1405+
1406+
static PyObject *
1407+
xmlparse_dir(PyObject *self, PyObject* noargs)
1408+
{
14031409
#define APPEND(list, str) \
14041410
do { \
14051411
PyObject *o = PyString_FromString(str); \
@@ -1408,36 +1414,39 @@ xmlparse_getattr(xmlparseobject *self, char *name)
14081414
Py_XDECREF(o); \
14091415
} while (0)
14101416

1411-
if (strcmp(name, "__members__") == 0) {
1412-
int i;
1413-
PyObject *rc = PyList_New(0);
1414-
if (!rc)
1415-
return NULL;
1416-
for (i = 0; handler_info[i].name != NULL; i++) {
1417-
PyObject *o = get_handler_name(&handler_info[i]);
1418-
if (o != NULL)
1419-
PyList_Append(rc, o);
1420-
Py_XDECREF(o);
1421-
}
1422-
APPEND(rc, "ErrorCode");
1423-
APPEND(rc, "ErrorLineNumber");
1424-
APPEND(rc, "ErrorColumnNumber");
1425-
APPEND(rc, "ErrorByteIndex");
1426-
APPEND(rc, "CurrentLineNumber");
1427-
APPEND(rc, "CurrentColumnNumber");
1428-
APPEND(rc, "CurrentByteIndex");
1429-
APPEND(rc, "buffer_size");
1430-
APPEND(rc, "buffer_text");
1431-
APPEND(rc, "buffer_used");
1432-
APPEND(rc, "namespace_prefixes");
1433-
APPEND(rc, "ordered_attributes");
1434-
APPEND(rc, "specified_attributes");
1435-
APPEND(rc, "intern");
1417+
int i;
1418+
PyObject *rc = PyList_New(0);
1419+
if (!rc)
1420+
return NULL;
1421+
for (i = 0; handler_info[i].name != NULL; i++) {
1422+
PyObject *o = get_handler_name(&handler_info[i]);
1423+
if (o != NULL)
1424+
PyList_Append(rc, o);
1425+
Py_XDECREF(o);
1426+
}
1427+
APPEND(rc, "ErrorCode");
1428+
APPEND(rc, "ErrorLineNumber");
1429+
APPEND(rc, "ErrorColumnNumber");
1430+
APPEND(rc, "ErrorByteIndex");
1431+
APPEND(rc, "CurrentLineNumber");
1432+
APPEND(rc, "CurrentColumnNumber");
1433+
APPEND(rc, "CurrentByteIndex");
1434+
APPEND(rc, "buffer_size");
1435+
APPEND(rc, "buffer_text");
1436+
APPEND(rc, "buffer_used");
1437+
APPEND(rc, "namespace_prefixes");
1438+
APPEND(rc, "ordered_attributes");
1439+
APPEND(rc, "specified_attributes");
1440+
APPEND(rc, "intern");
14361441

14371442
#undef APPEND
1438-
return rc;
1443+
1444+
if (PyErr_Occurred()) {
1445+
Py_DECREF(rc);
1446+
rc = NULL;
14391447
}
1440-
return Py_FindMethod(xmlparse_methods, (PyObject *)self, name);
1448+
1449+
return rc;
14411450
}
14421451

14431452
static int
@@ -1560,6 +1569,10 @@ xmlparse_clear(xmlparseobject *op)
15601569

15611570
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
15621571

1572+
static PyMethodDef xmlparse_tp_methods[] = {
1573+
{"__dir__", xmlparse_dir, METH_NOARGS}
1574+
};
1575+
15631576
static PyTypeObject Xmlparsetype = {
15641577
PyVarObject_HEAD_INIT(NULL, 0)
15651578
"pyexpat.xmlparser", /*tp_name*/
@@ -1588,7 +1601,12 @@ static PyTypeObject Xmlparsetype = {
15881601
#endif
15891602
Xmlparsetype__doc__, /* tp_doc - Documentation string */
15901603
(traverseproc)xmlparse_traverse, /* tp_traverse */
1591-
(inquiry)xmlparse_clear /* tp_clear */
1604+
(inquiry)xmlparse_clear, /* tp_clear */
1605+
0, /* tp_richcompare */
1606+
0, /* tp_weaklistoffset */
1607+
0, /* tp_iter */
1608+
0, /* tp_iternext */
1609+
xmlparse_tp_methods /* tp_methods */
15921610
};
15931611

15941612
/* End of code for xmlparser objects */

Objects/methodobject.c

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -275,47 +275,12 @@ PyTypeObject PyCFunction_Type = {
275275
0, /* tp_dict */
276276
};
277277

278-
/* List all methods in a chain -- helper for findmethodinchain */
279-
280-
static PyObject *
281-
listmethodchain(PyMethodChain *chain)
282-
{
283-
PyMethodChain *c;
284-
PyMethodDef *ml;
285-
int i, n;
286-
PyObject *v;
287-
288-
n = 0;
289-
for (c = chain; c != NULL; c = c->link) {
290-
for (ml = c->methods; ml->ml_name != NULL; ml++)
291-
n++;
292-
}
293-
v = PyList_New(n);
294-
if (v == NULL)
295-
return NULL;
296-
i = 0;
297-
for (c = chain; c != NULL; c = c->link) {
298-
for (ml = c->methods; ml->ml_name != NULL; ml++) {
299-
PyList_SetItem(v, i, PyUnicode_FromString(ml->ml_name));
300-
i++;
301-
}
302-
}
303-
if (PyErr_Occurred()) {
304-
Py_DECREF(v);
305-
return NULL;
306-
}
307-
PyList_Sort(v);
308-
return v;
309-
}
310-
311278
/* Find a method in a method chain */
312279

313280
PyObject *
314281
Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
315282
{
316283
if (name[0] == '_' && name[1] == '_') {
317-
if (strcmp(name, "__methods__") == 0)
318-
return listmethodchain(chain);
319284
if (strcmp(name, "__doc__") == 0) {
320285
const char *doc = self->ob_type->tp_doc;
321286
if (doc != NULL)

PC/_winreg.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,8 @@ PyTypeObject PyHKEY_Type =
473473

474474
#define OFF(e) offsetof(PyHKEYObject, e)
475475

476-
static struct memberlist PyHKEY_memberlist[] = {
477-
{"handle", T_INT, OFF(hkey)},
476+
static PyMemberDef PyHKEY_memberlist[] = {
477+
{"handle", T_INT, OFF(hkey), READONLY},
478478
{NULL} /* Sentinel */
479479
};
480480

@@ -523,7 +523,10 @@ PyHKEY_getattr(PyObject *self, const char *name)
523523
PyErr_Clear();
524524
if (strcmp(name, "handle") == 0)
525525
return PyLong_FromVoidPtr(((PyHKEYObject *)self)->hkey);
526-
return PyMember_Get((char *)self, PyHKEY_memberlist, name);
526+
PyErr_Format(PyExc_AttributeError,
527+
"'%.50s' object has no attribute '%.400s'",
528+
Py_Type(self)->tp_name, name);
529+
return NULL;
527530
}
528531

529532
/************************************************************************

PC/os2emx/python25.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,10 +1091,8 @@ EXPORTS
10911091
"_Py_QnewFlag"
10921092

10931093
; From python25_s.lib(structmember)
1094-
"PyMember_Get"
10951094
"PyMember_GetOne"
10961095
"PyMember_SetOne"
1097-
"PyMember_Set"
10981096

10991097
; From python25_s.lib(symtable)
11001098
"PySymtable_Build"

0 commit comments

Comments
 (0)