issue 2045: Infinite recursion when printing a subclass of defaultdict,
if default_factory is set to a bound method. Backport of r60663.
This commit is contained in:
parent
ec4301e60f
commit
3e5f8a6975
|
@ -141,6 +141,29 @@ class TestDefaultDict(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.fail("expected KeyError")
|
self.fail("expected KeyError")
|
||||||
|
|
||||||
|
def test_recursive_repr(self):
|
||||||
|
# Issue2045: stack overflow when default_factory is a bound method
|
||||||
|
class sub(defaultdict):
|
||||||
|
def __init__(self):
|
||||||
|
self.default_factory = self._factory
|
||||||
|
def _factory(self):
|
||||||
|
return []
|
||||||
|
d = sub()
|
||||||
|
self.assert_(repr(d).startswith(
|
||||||
|
"defaultdict(<bound method sub._factory of defaultdict(..."))
|
||||||
|
|
||||||
|
# NOTE: printing a subclass of a builtin type does not call its
|
||||||
|
# tp_print slot. So this part is essentially the same test as above.
|
||||||
|
tfn = tempfile.mktemp()
|
||||||
|
try:
|
||||||
|
f = open(tfn, "w+")
|
||||||
|
try:
|
||||||
|
print >>f, d
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
finally:
|
||||||
|
os.remove(tfn)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test_support.run_unittest(TestDefaultDict)
|
test_support.run_unittest(TestDefaultDict)
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 2.5.2c1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #2045: Fix an infinite recursion triggered when printing a subclass of
|
||||||
|
collections.defaultdict, if its default_factory is set to a bound method.
|
||||||
|
|
||||||
- Issue #1920: "while 0" statements were completely removed by the compiler,
|
- Issue #1920: "while 0" statements were completely removed by the compiler,
|
||||||
even in the presence of an "else" clause, which is supposed to be run when
|
even in the presence of an "else" clause, which is supposed to be run when
|
||||||
the condition is false. Now the compiler correctly emits bytecode for the
|
the condition is false. Now the compiler correctly emits bytecode for the
|
||||||
|
|
|
@ -1216,8 +1216,18 @@ defdict_repr(defdictobject *dd)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (dd->default_factory == NULL)
|
if (dd->default_factory == NULL)
|
||||||
defrepr = PyString_FromString("None");
|
defrepr = PyString_FromString("None");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int status = Py_ReprEnter(dd->default_factory);
|
||||||
|
if (status != 0) {
|
||||||
|
if (status < 0)
|
||||||
|
return NULL;
|
||||||
|
defrepr = PyString_FromString("...");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
defrepr = PyObject_Repr(dd->default_factory);
|
defrepr = PyObject_Repr(dd->default_factory);
|
||||||
|
Py_ReprLeave(dd->default_factory);
|
||||||
|
}
|
||||||
if (defrepr == NULL) {
|
if (defrepr == NULL) {
|
||||||
Py_DECREF(baserepr);
|
Py_DECREF(baserepr);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue