diff -r 6e1dd1ce95b8 Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py Tue Jul 30 01:37:36 2013 -0400 +++ b/Lib/test/test_dictviews.py Tue Jul 30 19:13:00 2013 +0100 @@ -1,4 +1,5 @@ import unittest +import sys from test import test_support class DictSetTest(unittest.TestCase): @@ -147,6 +148,18 @@ def test_recursive_repr(self): d = {} d[42] = d.viewvalues() + r = repr(d) + self.assertIsInstance(r, str) + self.assertEqual(r, '{42: dict_values([...])}') + d[42] = d.viewitems() + r = repr(d) + self.assertIsInstance(r, str) + self.assertEqual(r, '{42: dict_items([(42, ...)])}') + + def test_deeply_nested_repr(self): + d = {} + for i in range(sys.getrecursionlimit() + 100): + d = {42: d.values()} self.assertRaises(RuntimeError, repr, d) diff -r 6e1dd1ce95b8 Objects/dictobject.c --- a/Objects/dictobject.c Tue Jul 30 01:37:36 2013 -0400 +++ b/Objects/dictobject.c Tue Jul 30 19:13:00 2013 +0100 @@ -2912,21 +2912,28 @@ { PyObject *seq; PyObject *seq_str; - PyObject *result; + PyObject *result = NULL; + Py_ssize_t rc; + + rc = Py_ReprEnter((PyObject *)dv); + if (rc != 0) + return rc > 0 ? PyString_FromString("...") : NULL; seq = PySequence_List((PyObject *)dv); if (seq == NULL) - return NULL; + goto Done; seq_str = PyObject_Repr(seq); - if (seq_str == NULL) { - Py_DECREF(seq); - return NULL; - } + if (seq_str == NULL) + goto Done_seq; + result = PyString_FromFormat("%s(%s)", Py_TYPE(dv)->tp_name, PyString_AS_STRING(seq_str)); Py_DECREF(seq_str); +Done_seq: Py_DECREF(seq); +Done: + Py_ReprLeave((PyObject *)dv); return result; }