Convert some OrderedDict methods to Argument Clinic

Issue #29289. Convert methods:

* fromkeys() class method
* setdefault()
* popitem()
* move_to_end()
This commit is contained in:
Victor Stinner 2017-01-17 03:46:13 +01:00
parent 0c4a828cad
commit b05cbac052
2 changed files with 219 additions and 87 deletions

View File

@ -0,0 +1,135 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(OrderedDict_fromkeys__doc__,
"fromkeys($type, /, iterable, value=None)\n"
"--\n"
"\n"
"New ordered dictionary with keys from S.\n"
"\n"
"If not specified, the value defaults to None.");
#define ORDEREDDICT_FROMKEYS_METHODDEF \
{"fromkeys", (PyCFunction)OrderedDict_fromkeys, METH_FASTCALL|METH_CLASS, OrderedDict_fromkeys__doc__},
static PyObject *
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value);
static PyObject *
OrderedDict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"iterable", "value", NULL};
static _PyArg_Parser _parser = {"O|O:fromkeys", _keywords, 0};
PyObject *seq;
PyObject *value = Py_None;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&seq, &value)) {
goto exit;
}
return_value = OrderedDict_fromkeys_impl(type, seq, value);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_setdefault__doc__,
"setdefault($self, /, key, default=None)\n"
"--\n"
"\n"
"od.get(k,d), also set od[k]=d if k not in od.");
#define ORDEREDDICT_SETDEFAULT_METHODDEF \
{"setdefault", (PyCFunction)OrderedDict_setdefault, METH_FASTCALL, OrderedDict_setdefault__doc__},
static PyObject *
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
PyObject *failobj);
static PyObject *
OrderedDict_setdefault(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"key", "default", NULL};
static _PyArg_Parser _parser = {"O|O:setdefault", _keywords, 0};
PyObject *key;
PyObject *failobj = Py_None;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&key, &failobj)) {
goto exit;
}
return_value = OrderedDict_setdefault_impl(self, key, failobj);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_popitem__doc__,
"popitem($self, /, last=True)\n"
"--\n"
"\n"
"Return (k, v) and remove a (key, value) pair.\n"
"\n"
"Pairs are returned in LIFO order if last is true or FIFO order if false.");
#define ORDEREDDICT_POPITEM_METHODDEF \
{"popitem", (PyCFunction)OrderedDict_popitem, METH_FASTCALL, OrderedDict_popitem__doc__},
static PyObject *
OrderedDict_popitem_impl(PyODictObject *self, int last);
static PyObject *
OrderedDict_popitem(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"last", NULL};
static _PyArg_Parser _parser = {"|p:popitem", _keywords, 0};
int last = 1;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&last)) {
goto exit;
}
return_value = OrderedDict_popitem_impl(self, last);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_move_to_end__doc__,
"move_to_end($self, /, key, last=True)\n"
"--\n"
"\n"
"\"Move an existing element to the end (or beginning if last==False).\n"
"\n"
" Raises KeyError if the element does not exist.\n"
" When last=True, acts like a fast version of self[key]=self.pop(key).");
#define ORDEREDDICT_MOVE_TO_END_METHODDEF \
{"move_to_end", (PyCFunction)OrderedDict_move_to_end, METH_FASTCALL, OrderedDict_move_to_end__doc__},
static PyObject *
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last);
static PyObject *
OrderedDict_move_to_end(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"key", "last", NULL};
static _PyArg_Parser _parser = {"O|p:move_to_end", _keywords, 0};
PyObject *key;
int last = 1;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&key, &last)) {
goto exit;
}
return_value = OrderedDict_move_to_end_impl(self, key, last);
exit:
return return_value;
}
/*[clinic end generated code: output=f2641e1277045b59 input=a9049054013a1b77]*/

View File

@ -474,6 +474,13 @@ later:
#include "dict-common.h"
#include <stddef.h>
#include "clinic/odictobject.c.h"
/*[clinic input]
class OrderedDict "PyODictObject *" "&PyODict_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
typedef struct _odictnode _ODictNode;
@ -912,25 +919,23 @@ PyDoc_STRVAR(odict_setitem__doc__, "od.__setitem__(i, y) <==> od[i]=y");
/* fromkeys() */
PyDoc_STRVAR(odict_fromkeys__doc__,
"OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.\n\
If not specified, the value defaults to None.\n\
\n\
");
/*[clinic input]
@classmethod
OrderedDict.fromkeys
iterable as seq: object
value: object = None
New ordered dictionary with keys from S.
If not specified, the value defaults to None.
[clinic start generated code]*/
static PyObject *
odict_fromkeys(PyObject *cls, PyObject *args, PyObject *kwargs)
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
/*[clinic end generated code: output=c10390d452d78d6d input=33eefc496d5eee7b]*/
{
static char *kwlist[] = {"iterable", "value", 0};
PyObject *seq;
PyObject *value = Py_None;
/* both borrowed */
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:fromkeys", kwlist,
&seq, &value)) {
return NULL;
}
return _PyDict_FromKeys(cls, seq, value);
return _PyDict_FromKeys((PyObject *)type, seq, value);
}
/* __sizeof__() */
@ -1000,32 +1005,32 @@ Done:
return result;
}
/* setdefault() */
/* setdefault(): Skips __missing__() calls. */
PyDoc_STRVAR(odict_setdefault__doc__,
"od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od");
/* Skips __missing__() calls. */
/*[clinic input]
OrderedDict.setdefault
key: object
default as failobj: object = None
od.get(k,d), also set od[k]=d if k not in od.
[clinic start generated code]*/
static PyObject *
odict_setdefault(register PyODictObject *od, PyObject *args, PyObject *kwargs)
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
PyObject *failobj)
/*[clinic end generated code: output=605d0f6f61ccb0a6 input=4ee5006f32f5691b]*/
{
static char *kwlist[] = {"key", "default", 0};
PyObject *key, *result = NULL;
PyObject *failobj = Py_None;
PyObject *result = NULL;
/* both borrowed */
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:setdefault", kwlist,
&key, &failobj)) {
return NULL;
}
if (PyODict_CheckExact(od)) {
result = PyODict_GetItemWithError(od, key); /* borrowed */
if (PyODict_CheckExact(self)) {
result = PyODict_GetItemWithError(self, key); /* borrowed */
if (result == NULL) {
if (PyErr_Occurred())
return NULL;
assert(_odict_find_node(od, key) == NULL);
if (PyODict_SetItem((PyObject *)od, key, failobj) >= 0) {
assert(_odict_find_node(self, key) == NULL);
if (PyODict_SetItem((PyObject *)self, key, failobj) >= 0) {
result = failobj;
Py_INCREF(failobj);
}
@ -1035,14 +1040,14 @@ odict_setdefault(register PyODictObject *od, PyObject *args, PyObject *kwargs)
}
}
else {
int exists = PySequence_Contains((PyObject *)od, key);
int exists = PySequence_Contains((PyObject *)self, key);
if (exists < 0) {
return NULL;
}
else if (exists) {
result = PyObject_GetItem((PyObject *)od, key);
result = PyObject_GetItem((PyObject *)self, key);
}
else if (PyObject_SetItem((PyObject *)od, key, failobj) >= 0) {
else if (PyObject_SetItem((PyObject *)self, key, failobj) >= 0) {
result = failobj;
Py_INCREF(failobj);
}
@ -1152,39 +1157,37 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
return _odict_popkey_hash(od, key, failobj, hash);
}
/* popitem() */
PyDoc_STRVAR(odict_popitem__doc__,
"od.popitem() -> (k, v), return and remove a (key, value) pair.\n\
Pairs are returned in LIFO order if last is true or FIFO order if false.\n\
\n\
");
/*[clinic input]
OrderedDict.popitem
last: bool = True
Return (k, v) and remove a (key, value) pair.
Pairs are returned in LIFO order if last is true or FIFO order if false.
[clinic start generated code]*/
static PyObject *
odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs)
OrderedDict_popitem_impl(PyODictObject *self, int last)
/*[clinic end generated code: output=98e7d986690d49eb input=4937da2015939126]*/
{
static char *kwlist[] = {"last", 0};
PyObject *key, *value, *item = NULL;
_ODictNode *node;
int last = 1;
/* pull the item */
/* borrowed */
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p:popitem", kwlist,
&last)) {
return NULL;
}
if (_odict_EMPTY(od)) {
if (_odict_EMPTY(self)) {
PyErr_SetString(PyExc_KeyError, "dictionary is empty");
return NULL;
}
node = last ? _odict_LAST(od) : _odict_FIRST(od);
node = last ? _odict_LAST(self) : _odict_FIRST(self);
key = _odictnode_KEY(node);
Py_INCREF(key);
value = _odict_popkey_hash(od, key, NULL, _odictnode_HASH(node));
value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
if (value == NULL)
return NULL;
item = PyTuple_Pack(2, key, value);
@ -1312,36 +1315,34 @@ odict_reversed(PyODictObject *od)
return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
}
/* move_to_end() */
PyDoc_STRVAR(odict_move_to_end__doc__,
"Move an existing element to the end (or beginning if last==False).\n\
\n\
Raises KeyError if the element does not exist.\n\
When last=True, acts like a fast version of self[key]=self.pop(key).\n\
\n\
");
/*[clinic input]
OrderedDict.move_to_end
key: object
last: bool = True
"Move an existing element to the end (or beginning if last==False).
Raises KeyError if the element does not exist.
When last=True, acts like a fast version of self[key]=self.pop(key).
[clinic start generated code]*/
static PyObject *
odict_move_to_end(PyODictObject *od, PyObject *args, PyObject *kwargs)
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=3b8283f7d0e15e43]*/
{
static char *kwlist[] = {"key", "last", 0};
PyObject *key;
int last = 1;
_ODictNode *node;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|p:move_to_end", kwlist,
&key, &last)) {
return NULL;
}
if (_odict_EMPTY(od)) {
if (_odict_EMPTY(self)) {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
node = last ? _odict_LAST(od) : _odict_FIRST(od);
node = last ? _odict_LAST(self) : _odict_FIRST(self);
if (key != _odictnode_KEY(node)) {
node = _odict_find_node(od, key);
node = _odict_find_node(self, key);
if (node == NULL) {
if (!PyErr_Occurred())
PyErr_SetObject(PyExc_KeyError, key);
@ -1349,16 +1350,16 @@ odict_move_to_end(PyODictObject *od, PyObject *args, PyObject *kwargs)
}
if (last) {
/* Only move if not already the last one. */
if (node != _odict_LAST(od)) {
_odict_remove_node(od, node);
_odict_add_tail(od, node);
if (node != _odict_LAST(self)) {
_odict_remove_node(self, node);
_odict_add_tail(self, node);
}
}
else {
/* Only move if not already the first one. */
if (node != _odict_FIRST(od)) {
_odict_remove_node(od, node);
_odict_add_head(od, node);
if (node != _odict_FIRST(self)) {
_odict_remove_node(self, node);
_odict_add_head(self, node);
}
}
}
@ -1386,20 +1387,17 @@ static PyMethodDef odict_methods[] = {
odict_repr__doc__},
{"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS,
odict_setitem__doc__},
{"fromkeys", (PyCFunction)odict_fromkeys,
METH_VARARGS | METH_KEYWORDS | METH_CLASS, odict_fromkeys__doc__},
ORDEREDDICT_FROMKEYS_METHODDEF
/* overridden dict methods */
{"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
odict_sizeof__doc__},
{"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
odict_reduce__doc__},
{"setdefault", (PyCFunction)odict_setdefault,
METH_VARARGS | METH_KEYWORDS, odict_setdefault__doc__},
ORDEREDDICT_SETDEFAULT_METHODDEF
{"pop", (PyCFunction)odict_pop,
METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
{"popitem", (PyCFunction)odict_popitem,
METH_VARARGS | METH_KEYWORDS, odict_popitem__doc__},
ORDEREDDICT_POPITEM_METHODDEF
{"keys", (PyCFunction)odictkeys_new, METH_NOARGS,
odict_keys__doc__},
{"values", (PyCFunction)odictvalues_new, METH_NOARGS,
@ -1416,8 +1414,7 @@ static PyMethodDef odict_methods[] = {
/* new methods */
{"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
odict_reversed__doc__},
{"move_to_end", (PyCFunction)odict_move_to_end,
METH_VARARGS | METH_KEYWORDS, odict_move_to_end__doc__},
ORDEREDDICT_MOVE_TO_END_METHODDEF
{NULL, NULL} /* sentinel */
};