summaryrefslogtreecommitdiff
path: root/Modules/_functoolsmodule.c
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2017-02-09 16:08:17 +0100
committerNick Coghlan <ncoghlan@gmail.com>2017-02-09 16:08:17 +0100
commitc6180bb73c8c7c7f9d8ea9816487b710597b6fc1 (patch)
treefb4a5c18886537b4b7df46ed3b2aa579747ff507 /Modules/_functoolsmodule.c
parent5e0114a832a903518c4af6983161c0c2a8942a24 (diff)
parent819a21a3a4aac38f32e1ba4f68bcef45591fa3f0 (diff)
downloadcpython-c6180bb73c8c7c7f9d8ea9816487b710597b6fc1.tar.gz
Merge issue #26355 fix from Python 3.5
Diffstat (limited to 'Modules/_functoolsmodule.c')
-rw-r--r--Modules/_functoolsmodule.c111
1 files changed, 55 insertions, 56 deletions
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index be0f5f9e65..f785a7260e 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -128,44 +128,60 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kw)
{
PyObject *ret;
PyObject *argappl, *kwappl;
+ PyObject **stack;
+ Py_ssize_t nargs;
assert (PyCallable_Check(pto->fn));
assert (PyTuple_Check(pto->args));
assert (PyDict_Check(pto->kw));
if (PyTuple_GET_SIZE(pto->args) == 0) {
- argappl = args;
- Py_INCREF(args);
- } else if (PyTuple_GET_SIZE(args) == 0) {
- argappl = pto->args;
- Py_INCREF(pto->args);
- } else {
+ stack = &PyTuple_GET_ITEM(args, 0);
+ nargs = PyTuple_GET_SIZE(args);
+ argappl = NULL;
+ }
+ else if (PyTuple_GET_SIZE(args) == 0) {
+ stack = &PyTuple_GET_ITEM(pto->args, 0);
+ nargs = PyTuple_GET_SIZE(pto->args);
+ argappl = NULL;
+ }
+ else {
+ stack = NULL;
argappl = PySequence_Concat(pto->args, args);
- if (argappl == NULL)
+ if (argappl == NULL) {
return NULL;
+ }
+
assert(PyTuple_Check(argappl));
}
if (PyDict_Size(pto->kw) == 0) {
kwappl = kw;
Py_XINCREF(kwappl);
- } else {
+ }
+ else {
kwappl = PyDict_Copy(pto->kw);
if (kwappl == NULL) {
- Py_DECREF(argappl);
+ Py_XDECREF(argappl);
return NULL;
}
+
if (kw != NULL) {
if (PyDict_Merge(kwappl, kw, 1) != 0) {
- Py_DECREF(argappl);
+ Py_XDECREF(argappl);
Py_DECREF(kwappl);
return NULL;
}
}
}
- ret = PyObject_Call(pto->fn, argappl, kwappl);
- Py_DECREF(argappl);
+ if (stack) {
+ ret = _PyObject_FastCallDict(pto->fn, stack, nargs, kwappl);
+ }
+ else {
+ ret = PyObject_Call(pto->fn, argappl, kwappl);
+ Py_DECREF(argappl);
+ }
Py_XDECREF(kwappl);
return ret;
}
@@ -213,7 +229,7 @@ partial_repr(partialobject *pto)
if (status != 0) {
if (status < 0)
return NULL;
- return PyUnicode_FromFormat("%s(...)", Py_TYPE(pto)->tp_name);
+ return PyUnicode_FromString("...");
}
arglist = PyUnicode_FromString("");
@@ -461,12 +477,12 @@ static PyObject *
keyobject_richcompare(PyObject *ko, PyObject *other, int op)
{
PyObject *res;
- PyObject *args;
PyObject *x;
PyObject *y;
PyObject *compare;
PyObject *answer;
static PyObject *zero;
+ PyObject* stack[2];
if (zero == NULL) {
zero = PyLong_FromLong(0);
@@ -490,17 +506,13 @@ keyobject_richcompare(PyObject *ko, PyObject *other, int op)
/* Call the user's comparison function and translate the 3-way
* result into true or false (or error).
*/
- args = PyTuple_New(2);
- if (args == NULL)
- return NULL;
- Py_INCREF(x);
- Py_INCREF(y);
- PyTuple_SET_ITEM(args, 0, x);
- PyTuple_SET_ITEM(args, 1, y);
- res = PyObject_Call(compare, args, NULL);
- Py_DECREF(args);
- if (res == NULL)
+ stack[0] = x;
+ stack[1] = y;
+ res = _PyObject_FastCall(compare, stack, 2);
+ if (res == NULL) {
return NULL;
+ }
+
answer = PyObject_RichCompare(res, zero, op);
Py_DECREF(res);
return answer;
@@ -692,8 +704,8 @@ static PyTypeObject lru_cache_type;
static PyObject *
lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
{
- PyObject *key, *sorted_items;
- Py_ssize_t key_size, pos, key_pos;
+ PyObject *key, *keyword, *value;
+ Py_ssize_t key_size, pos, key_pos, kwds_size;
/* short path, key will match args anyway, which is a tuple */
if (!typed && !kwds) {
@@ -701,28 +713,18 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
return args;
}
- if (kwds && PyDict_Size(kwds) > 0) {
- sorted_items = PyDict_Items(kwds);
- if (!sorted_items)
- return NULL;
- if (PyList_Sort(sorted_items) < 0) {
- Py_DECREF(sorted_items);
- return NULL;
- }
- } else
- sorted_items = NULL;
+ kwds_size = kwds ? PyDict_Size(kwds) : 0;
+ assert(kwds_size >= 0);
key_size = PyTuple_GET_SIZE(args);
- if (sorted_items)
- key_size += PyList_GET_SIZE(sorted_items);
+ if (kwds_size)
+ key_size += kwds_size * 2 + 1;
if (typed)
- key_size *= 2;
- if (sorted_items)
- key_size++;
+ key_size += PyTuple_GET_SIZE(args) + kwds_size;
key = PyTuple_New(key_size);
if (key == NULL)
- goto done;
+ return NULL;
key_pos = 0;
for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
@@ -730,14 +732,16 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
Py_INCREF(item);
PyTuple_SET_ITEM(key, key_pos++, item);
}
- if (sorted_items) {
+ if (kwds_size) {
Py_INCREF(kwd_mark);
PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
- for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) {
- PyObject *item = PyList_GET_ITEM(sorted_items, pos);
- Py_INCREF(item);
- PyTuple_SET_ITEM(key, key_pos++, item);
+ for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
+ Py_INCREF(keyword);
+ PyTuple_SET_ITEM(key, key_pos++, keyword);
+ Py_INCREF(value);
+ PyTuple_SET_ITEM(key, key_pos++, value);
}
+ assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
}
if (typed) {
for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
@@ -745,20 +749,15 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
Py_INCREF(item);
PyTuple_SET_ITEM(key, key_pos++, item);
}
- if (sorted_items) {
- for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) {
- PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos);
- PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1));
+ if (kwds_size) {
+ for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
+ PyObject *item = (PyObject *)Py_TYPE(value);
Py_INCREF(item);
PyTuple_SET_ITEM(key, key_pos++, item);
}
}
}
assert(key_pos == key_size);
-
-done:
- if (sorted_items)
- Py_DECREF(sorted_items);
return key;
}
@@ -871,7 +870,7 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
/* Remove it from the cache.
The cache dict holds one reference to the link,
and the linked list holds yet one reference to it. */
- popresult = _PyDict_Pop_KnownHash((PyDictObject *)self->cache,
+ popresult = _PyDict_Pop_KnownHash(self->cache,
link->key, link->hash,
Py_None);
if (popresult == Py_None) {