diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 8cc1b00..2ede0e8 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1633,6 +1633,17 @@ class TestSorted(unittest.TestCase): data = 'The quick Brown fox Jumped over The lazy Dog'.split() self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0) + def test_flexible_signature(self): + data = list(range(100)) + copy = data[:] + random.shuffle(copy) + self.assertEqual(data, sorted(iterable=copy)) + self.assertEqual(data, sorted(iterable=copy, key=lambda x: -x, + reverse=True)) + self.assertEqual(data, sorted(copy, lambda x: x)) + self.assertEqual(data, sorted(copy, lambda x: -x), True) + self.assertRaises(TypeError, sorted) + class ShutdownTest(unittest.TestCase): diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 31d9e0e..aee05da 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2089,10 +2089,10 @@ PyDoc_STRVAR(builtin_sorted__doc__, static PyObject * builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *newlist, *v, *seq, *keyfunc=NULL, *newargs; + PyObject *newlist, *v, *seq, *keyfunc=NULL, *newargs, *newkwds=NULL; PyObject *callable; static char *kwlist[] = {"iterable", "key", "reverse", 0}; - int reverse; + int reverse = -1; /* args 1-3 should match listsort in Objects/listobject.c */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:sorted", @@ -2109,15 +2109,32 @@ builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - newargs = PyTuple_GetSlice(args, 1, 4); + newargs = PyTuple_New(0); if (newargs == NULL) { Py_DECREF(newlist); Py_DECREF(callable); return NULL; } - v = PyObject_Call(callable, newargs, kwds); + if (keyfunc != NULL || reverse != -1) { + if (keyfunc == NULL) { + newkwds = Py_BuildValue("{s:i}", "reverse", reverse); + } else if (reverse != -1) { + newkwds = Py_BuildValue("{s:O,s:i}", "key", keyfunc, "reverse", reverse); + } else { + newkwds = Py_BuildValue("{s:O}", "key", keyfunc); + } + if (newkwds == NULL) { + Py_DECREF(newlist); + Py_DECREF(callable); + Py_DECREF(newargs); + return NULL; + } + } + + v = PyObject_Call(callable, newargs, newkwds); Py_DECREF(newargs); + Py_XDECREF(newkwds); Py_DECREF(callable); if (v == NULL) { Py_DECREF(newlist);