diff options
author | Raymond Hettinger <python@rcn.com> | 2003-11-28 21:43:02 +0000 |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2003-11-28 21:43:02 +0000 |
commit | 37e136373e0d9ab3bdf25ecd9c42b86281ed21d3 (patch) | |
tree | fc0caf815fcf3da64a1a031065f1ee3f9c3f27c4 | |
parent | b3105911697d57098e9770078d89475f83274344 (diff) | |
download | cpython-git-37e136373e0d9ab3bdf25ecd9c42b86281ed21d3.tar.gz |
Make sure the list.sort's decorate step unwinds itself before returning
an exception raised by the key function.
(Suggested by Michael Hudson.)
-rw-r--r-- | Lib/test/test_sort.py | 7 | ||||
-rw-r--r-- | Objects/listobject.c | 11 |
2 files changed, 16 insertions, 2 deletions
diff --git a/Lib/test/test_sort.py b/Lib/test/test_sort.py index 053b3381d5..2659a9088d 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 3782c3baac..95aa484f2b 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); |