[Python-checkins] r53197 - in python/branches/release25-maint: Lib/test/test_set.py Misc/NEWS Objects/setobject.c

raymond.hettinger python-checkins at python.org
Fri Dec 29 19:49:14 CET 2006


Author: raymond.hettinger
Date: Fri Dec 29 19:49:13 2006
New Revision: 53197
Modified:
 python/branches/release25-maint/Lib/test/test_set.py
 python/branches/release25-maint/Misc/NEWS
 python/branches/release25-maint/Objects/setobject.c
Log:
For sets with cyclical reprs, emit '...' instead of recursing.
Modified: python/branches/release25-maint/Lib/test/test_set.py
==============================================================================
--- python/branches/release25-maint/Lib/test/test_set.py	(original)
+++ python/branches/release25-maint/Lib/test/test_set.py	Fri Dec 29 19:49:13 2006
@@ -21,6 +21,11 @@
 def __cmp__(self, other):
 raise RuntimeError
 
+class ReprWrapper:
+ 'Used to test self-referential repr() calls'
+ def __repr__(self):
+ return repr(self.value)
+
 class TestJointOps(unittest.TestCase):
 # Tests common to both set and frozenset
 
@@ -244,6 +249,27 @@
 self.assertRaises(RuntimeError, s.discard, BadCmp())
 self.assertRaises(RuntimeError, s.remove, BadCmp())
 
+ def test_cyclical_repr(self):
+ w = ReprWrapper()
+ s = self.thetype([w])
+ w.value = s
+ name = repr(s).partition('(')[0] # strip class name from repr string
+ self.assertEqual(repr(s), '%s([%s(...)])' % (name, name))
+
+ def test_cyclical_print(self):
+ w = ReprWrapper()
+ s = self.thetype([w])
+ w.value = s
+ try:
+ fo = open(test_support.TESTFN, "wb")
+ print >> fo, s,
+ fo.close()
+ fo = open(test_support.TESTFN, "rb")
+ self.assertEqual(fo.read(), repr(s))
+ finally:
+ fo.close()
+ os.remove(test_support.TESTFN)
+
 class TestSet(TestJointOps):
 thetype = set
 
Modified: python/branches/release25-maint/Misc/NEWS
==============================================================================
--- python/branches/release25-maint/Misc/NEWS	(original)
+++ python/branches/release25-maint/Misc/NEWS	Fri Dec 29 19:49:13 2006
@@ -18,6 +18,9 @@
 custom ``__eq__()`` method to confuse set internals when class instances
 were used as a set's elements and the ``__eq__()`` method mutated the set.
 
+- The repr for self-referential sets and fronzensets now shows "..." instead
+ of falling into infinite recursion.
+
 - Eliminated unnecessary repeated calls to hash() by set.intersection() and
 set.symmetric_difference_update().
 
Modified: python/branches/release25-maint/Objects/setobject.c
==============================================================================
--- python/branches/release25-maint/Objects/setobject.c	(original)
+++ python/branches/release25-maint/Objects/setobject.c	Fri Dec 29 19:49:13 2006
@@ -572,34 +572,54 @@
 	Py_ssize_t pos=0;
 	char *emit = "";	/* No separator emitted on first pass */
 	char *separator = ", ";
+	int status = Py_ReprEnter((PyObject*)so);
+
+	if (status != 0) {
+		if (status < 0)
+			return status;
+		fprintf(fp, "%s(...)", so->ob_type->tp_name);
+		return 0;
+	} 
 
 	fprintf(fp, "%s([", so->ob_type->tp_name);
 	while (set_next(so, &pos, &entry)) {
 		fputs(emit, fp);
 		emit = separator;
-		if (PyObject_Print(entry->key, fp, 0) != 0)
+		if (PyObject_Print(entry->key, fp, 0) != 0) {
+			Py_ReprLeave((PyObject*)so);
 			return -1;
+		}
 	}
 	fputs("])", fp);
+	Py_ReprLeave((PyObject*)so); 
 	return 0;
 }
 
 static PyObject *
 set_repr(PySetObject *so)
 {
-	PyObject *keys, *result, *listrepr;
+	PyObject *keys, *result=NULL, *listrepr;
+	int status = Py_ReprEnter((PyObject*)so);
+
+	if (status != 0) {
+		if (status < 0)
+			return NULL;
+		return PyString_FromFormat("%s(...)", so->ob_type->tp_name);
+	}
 
 	keys = PySequence_List((PyObject *)so);
 	if (keys == NULL)
-		return NULL;
+		goto done;
 	listrepr = PyObject_Repr(keys);
 	Py_DECREF(keys);
 	if (listrepr == NULL)
-		return NULL;
+		goto done;
 
 	result = PyString_FromFormat("%s(%s)", so->ob_type->tp_name,
 		PyString_AS_STRING(listrepr));
 	Py_DECREF(listrepr);
+done:
+	Py_ReprLeave((PyObject*)so);
 	return result;
 }
 


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /