From: Raymond Hettinger Date: Fri, 28 Nov 2003 21:43:02 +0000 (+0000) Subject: Make sure the list.sort's decorate step unwinds itself before returning X-Git-Tag: v2.4a1~1190 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=37e136373e0d9ab3bdf25ecd9c42b86281ed21d3;p=thirdparty%2FPython%2Fcpython.git Make sure the list.sort's decorate step unwinds itself before returning an exception raised by the key function. (Suggested by Michael Hudson.) --- diff --git a/Lib/test/test_sort.py b/Lib/test/test_sort.py index 053b3381d57d..2659a9088d44 100644 --- a/Lib/test/test_sort.py +++ b/Lib/test/test_sort.py @@ -186,6 +186,13 @@ class TestDecorateSortUndecorate(unittest.TestCase): data = 'The quick Brown fox Jumped over The lazy Dog'.split() self.assertRaises(TypeError, data.sort, "bad", str.lower) + def test_key_with_exception(self): + # Verify that the wrapper has been removed + data = range(-2,2) + dup = data[:] + self.assertRaises(ZeroDivisionError, data.sort, None, lambda x: 1/x) + self.assertEqual(data, dup) + def test_reverse(self): data = range(100) random.shuffle(data) diff --git a/Objects/listobject.c b/Objects/listobject.c index 3782c3baacfd..95aa484f2be3 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1876,8 +1876,15 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds) value = PyList_GET_ITEM(self, i); key = PyObject_CallFunctionObjArgs(keyfunc, value, NULL); - if (key == NULL) + if (key == NULL) { + for (i=i-1 ; i>=0 ; i--) { + kvpair = PyList_GET_ITEM(self, i); + value = sortwrapper_getvalue(kvpair); + PyList_SET_ITEM(self, i, value); + Py_DECREF(kvpair); + } goto dsu_fail; + } kvpair = build_sortwrapper(key, value); if (kvpair == NULL) goto dsu_fail; @@ -1885,7 +1892,7 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds) } } - /* Reverse sort stability achieved by initialially reversing the list, + /* Reverse sort stability achieved by initially reversing the list, applying a stable forward sort, then reversing the final result. */ if (reverse && self->ob_size > 1) reverse_slice(self->ob_item, self->ob_item + self->ob_size);