Add implementations of Py_Repr{Enter,Leave}.
(Jeremy will hardly recognize his patch :-)
This commit is contained in:
parent
26d4ac30be
commit
8661036cb8
|
@ -790,3 +790,67 @@ PyMem_Free(p)
|
|||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
/* These methods are used to control infinite recursion in repr, str, print,
|
||||
etc. Container objects that may recursively contain themselves,
|
||||
e.g. builtin dictionaries and lists, should used Py_ReprEnter() and
|
||||
Py_ReprLeave() to avoid infinite recursion.
|
||||
|
||||
Py_ReprEnter() returns 0 the first time it is called for a particular
|
||||
object and 1 every time thereafter. It returns -1 if an exception
|
||||
occurred. Py_ReprLeave() has no return value.
|
||||
|
||||
See dictobject.c and listobject.c for examples of use.
|
||||
*/
|
||||
|
||||
#define KEY "Py_Repr"
|
||||
|
||||
int
|
||||
Py_ReprEnter(obj)
|
||||
PyObject *obj;
|
||||
{
|
||||
PyObject *dict;
|
||||
PyObject *list;
|
||||
int i;
|
||||
|
||||
dict = PyThreadState_GetDict();
|
||||
if (dict == NULL)
|
||||
return -1;
|
||||
list = PyDict_GetItemString(dict, KEY);
|
||||
if (list == NULL) {
|
||||
list = PyList_New(0);
|
||||
if (list == NULL)
|
||||
return -1;
|
||||
if (PyDict_SetItemString(dict, KEY, list) < 0)
|
||||
return -1;
|
||||
Py_DECREF(list);
|
||||
}
|
||||
i = PyList_GET_SIZE(list);
|
||||
while (--i >= 0) {
|
||||
if (PyList_GET_ITEM(list, i) == obj)
|
||||
return 1;
|
||||
}
|
||||
PyList_Append(list, obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Py_ReprLeave(obj)
|
||||
PyObject *obj;
|
||||
{
|
||||
PyObject *dict;
|
||||
PyObject *list;
|
||||
int i;
|
||||
|
||||
dict = PyThreadState_GetDict();
|
||||
list = PyDict_GetItemString(dict, KEY);
|
||||
i = PyList_GET_SIZE(list);
|
||||
/* Count backwards because we always expect obj to be list[-1] */
|
||||
while (--i >= 0) {
|
||||
if (PyList_GET_ITEM(list, i) == obj) {
|
||||
PyList_SetSlice(list, i, i + 1, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue