gh-112050: Adapt collections.deque to Argument Clinic (#113963)

This commit is contained in:
mpage 2024-01-29 07:08:23 -08:00 committed by GitHub
parent e8b8f5e9c2
commit c87233fd3f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 690 additions and 157 deletions

View file

@ -1049,6 +1049,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(max_length)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(max_length));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxdigits)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxdigits));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxevents)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxevents));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxlen));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxmem)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxmem));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxsplit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxsplit));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxvalue)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxvalue));

View file

@ -538,6 +538,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(max_length) STRUCT_FOR_ID(max_length)
STRUCT_FOR_ID(maxdigits) STRUCT_FOR_ID(maxdigits)
STRUCT_FOR_ID(maxevents) STRUCT_FOR_ID(maxevents)
STRUCT_FOR_ID(maxlen)
STRUCT_FOR_ID(maxmem) STRUCT_FOR_ID(maxmem)
STRUCT_FOR_ID(maxsplit) STRUCT_FOR_ID(maxsplit)
STRUCT_FOR_ID(maxvalue) STRUCT_FOR_ID(maxvalue)

View file

@ -1047,6 +1047,7 @@ extern "C" {
INIT_ID(max_length), \ INIT_ID(max_length), \
INIT_ID(maxdigits), \ INIT_ID(maxdigits), \
INIT_ID(maxevents), \ INIT_ID(maxevents), \
INIT_ID(maxlen), \
INIT_ID(maxmem), \ INIT_ID(maxmem), \
INIT_ID(maxsplit), \ INIT_ID(maxsplit), \
INIT_ID(maxvalue), \ INIT_ID(maxvalue), \

View file

@ -1455,6 +1455,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(maxevents); string = &_Py_ID(maxevents);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(maxlen);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(maxmem); string = &_Py_ID(maxmem);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);

View file

@ -0,0 +1 @@
Convert :class:`collections.deque` to use Argument Clinic.

View file

@ -44,8 +44,11 @@ find_module_state_by_def(PyTypeObject *type)
/*[clinic input] /*[clinic input]
module _collections module _collections
class _tuplegetter "_tuplegetterobject *" "clinic_state()->tuplegetter_type" class _tuplegetter "_tuplegetterobject *" "clinic_state()->tuplegetter_type"
class _collections.deque "dequeobject *" "clinic_state()->deque_type"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7356042a89862e0e]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a033cc2a8476b3f1]*/
typedef struct dequeobject dequeobject;
/* We can safely assume type to be the defining class, /* We can safely assume type to be the defining class,
* since tuplegetter is not a base type */ * since tuplegetter is not a base type */
@ -53,6 +56,12 @@ class _tuplegetter "_tuplegetterobject *" "clinic_state()->tuplegetter_type"
#include "clinic/_collectionsmodule.c.h" #include "clinic/_collectionsmodule.c.h"
#undef clinic_state #undef clinic_state
/*[python input]
class dequeobject_converter(self_converter):
type = "dequeobject *"
[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=b6ae4a3ff852be2f]*/
/* collections module implementation of a deque() datatype /* collections module implementation of a deque() datatype
Written and maintained by Raymond D. Hettinger <python@rcn.com> Written and maintained by Raymond D. Hettinger <python@rcn.com>
*/ */
@ -121,7 +130,7 @@ typedef struct BLOCK {
struct BLOCK *rightlink; struct BLOCK *rightlink;
} block; } block;
typedef struct { struct dequeobject {
PyObject_VAR_HEAD PyObject_VAR_HEAD
block *leftblock; block *leftblock;
block *rightblock; block *rightblock;
@ -132,7 +141,7 @@ typedef struct {
Py_ssize_t numfreeblocks; Py_ssize_t numfreeblocks;
block *freeblocks[MAXFREEBLOCKS]; block *freeblocks[MAXFREEBLOCKS];
PyObject *weakreflist; PyObject *weakreflist;
} dequeobject; };
/* For debug builds, add error checking to track the endpoints /* For debug builds, add error checking to track the endpoints
* in the chain of links. The goal is to make sure that link * in the chain of links. The goal is to make sure that link
@ -219,8 +228,17 @@ deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)deque; return (PyObject *)deque;
} }
/*[clinic input]
_collections.deque.pop as deque_pop
deque: dequeobject
Remove and return the rightmost element.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_pop(dequeobject *deque, PyObject *unused) deque_pop_impl(dequeobject *deque)
/*[clinic end generated code: output=2e5f7890c4251f07 input=eb6e6d020f877dec]*/
{ {
PyObject *item; PyObject *item;
block *prevblock; block *prevblock;
@ -254,10 +272,17 @@ deque_pop(dequeobject *deque, PyObject *unused)
return item; return item;
} }
PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); /*[clinic input]
_collections.deque.popleft as deque_popleft
deque: dequeobject
Remove and return the leftmost element.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_popleft(dequeobject *deque, PyObject *unused) deque_popleft_impl(dequeobject *deque)
/*[clinic end generated code: output=62b154897097ff68 input=acb41b9af50a9d9b]*/
{ {
PyObject *item; PyObject *item;
block *prevblock; block *prevblock;
@ -292,8 +317,6 @@ deque_popleft(dequeobject *deque, PyObject *unused)
return item; return item;
} }
PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element.");
/* The deque's size limit is d.maxlen. The limit can be zero or positive. /* The deque's size limit is d.maxlen. The limit can be zero or positive.
* If there is no limit, then d.maxlen == -1. * If there is no limit, then d.maxlen == -1.
* *
@ -326,7 +349,7 @@ deque_append_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
deque->rightindex++; deque->rightindex++;
deque->rightblock->data[deque->rightindex] = item; deque->rightblock->data[deque->rightindex] = item;
if (NEEDS_TRIM(deque, maxlen)) { if (NEEDS_TRIM(deque, maxlen)) {
PyObject *olditem = deque_popleft(deque, NULL); PyObject *olditem = deque_popleft_impl(deque);
Py_DECREF(olditem); Py_DECREF(olditem);
} else { } else {
deque->state++; deque->state++;
@ -334,16 +357,25 @@ deque_append_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
return 0; return 0;
} }
/*[clinic input]
_collections.deque.append as deque_append
deque: dequeobject
item: object
/
Add an element to the right side of the deque.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_append(dequeobject *deque, PyObject *item) deque_append(dequeobject *deque, PyObject *item)
/*[clinic end generated code: output=507b13efc4853ecc input=f112b83c380528e3]*/
{ {
if (deque_append_internal(deque, Py_NewRef(item), deque->maxlen) < 0) if (deque_append_internal(deque, Py_NewRef(item), deque->maxlen) < 0)
return NULL; return NULL;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque.");
static inline int static inline int
deque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen) deque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
{ {
@ -362,7 +394,7 @@ deque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
deque->leftindex--; deque->leftindex--;
deque->leftblock->data[deque->leftindex] = item; deque->leftblock->data[deque->leftindex] = item;
if (NEEDS_TRIM(deque, deque->maxlen)) { if (NEEDS_TRIM(deque, deque->maxlen)) {
PyObject *olditem = deque_pop(deque, NULL); PyObject *olditem = deque_pop_impl(deque);
Py_DECREF(olditem); Py_DECREF(olditem);
} else { } else {
deque->state++; deque->state++;
@ -370,16 +402,25 @@ deque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
return 0; return 0;
} }
/*[clinic input]
_collections.deque.appendleft as deque_appendleft
deque: dequeobject
item: object
/
Add an element to the left side of the deque.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_appendleft(dequeobject *deque, PyObject *item) deque_appendleft(dequeobject *deque, PyObject *item)
/*[clinic end generated code: output=de0335a64800ffd8 input=bbdaa60a3e956062]*/
{ {
if (deque_appendleft_internal(deque, Py_NewRef(item), deque->maxlen) < 0) if (deque_appendleft_internal(deque, Py_NewRef(item), deque->maxlen) < 0)
return NULL; return NULL;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque.");
static PyObject* static PyObject*
finalize_iterator(PyObject *it) finalize_iterator(PyObject *it)
{ {
@ -410,8 +451,19 @@ consume_iterator(PyObject *it)
return finalize_iterator(it); return finalize_iterator(it);
} }
/*[clinic input]
_collections.deque.extend as deque_extend
deque: dequeobject
iterable: object
/
Extend the right side of the deque with elements from the iterable.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_extend(dequeobject *deque, PyObject *iterable) deque_extend(dequeobject *deque, PyObject *iterable)
/*[clinic end generated code: output=a3a6e74d17063f8d input=cfebfd34d5383339]*/
{ {
PyObject *it, *item; PyObject *it, *item;
PyObject *(*iternext)(PyObject *); PyObject *(*iternext)(PyObject *);
@ -454,11 +506,19 @@ deque_extend(dequeobject *deque, PyObject *iterable)
return finalize_iterator(it); return finalize_iterator(it);
} }
PyDoc_STRVAR(extend_doc, /*[clinic input]
"Extend the right side of the deque with elements from the iterable"); _collections.deque.extendleft as deque_extendleft
deque: dequeobject
iterable: object
/
Extend the left side of the deque with elements from the iterable.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_extendleft(dequeobject *deque, PyObject *iterable) deque_extendleft(dequeobject *deque, PyObject *iterable)
/*[clinic end generated code: output=2dba946c50498c67 input=f4820e695a6f9416]*/
{ {
PyObject *it, *item; PyObject *it, *item;
PyObject *(*iternext)(PyObject *); PyObject *(*iternext)(PyObject *);
@ -501,9 +561,6 @@ deque_extendleft(dequeobject *deque, PyObject *iterable)
return finalize_iterator(it); return finalize_iterator(it);
} }
PyDoc_STRVAR(extendleft_doc,
"Extend the left side of the deque with elements from the iterable");
static PyObject * static PyObject *
deque_inplace_concat(dequeobject *deque, PyObject *other) deque_inplace_concat(dequeobject *deque, PyObject *other)
{ {
@ -517,8 +574,17 @@ deque_inplace_concat(dequeobject *deque, PyObject *other)
return (PyObject *)deque; return (PyObject *)deque;
} }
/*[clinic input]
_collections.deque.copy as deque_copy
deque: dequeobject
Return a shallow copy of a deque.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored)) deque_copy_impl(dequeobject *deque)
/*[clinic end generated code: output=6409b3d1ad2898b5 input=0e22f138bc1fcbee]*/
{ {
PyObject *result; PyObject *result;
dequeobject *old_deque = (dequeobject *)deque; dequeobject *old_deque = (dequeobject *)deque;
@ -537,7 +603,7 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored))
PyObject *item = old_deque->leftblock->data[old_deque->leftindex]; PyObject *item = old_deque->leftblock->data[old_deque->leftindex];
rv = deque_append(new_deque, item); rv = deque_append(new_deque, item);
} else { } else {
rv = deque_extend(new_deque, deque); rv = deque_extend(new_deque, (PyObject *)deque);
} }
if (rv != NULL) { if (rv != NULL) {
Py_DECREF(rv); Py_DECREF(rv);
@ -547,7 +613,8 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored))
return NULL; return NULL;
} }
if (old_deque->maxlen < 0) if (old_deque->maxlen < 0)
result = PyObject_CallOneArg((PyObject *)(Py_TYPE(deque)), deque); result = PyObject_CallOneArg((PyObject *)(Py_TYPE(deque)),
(PyObject *)deque);
else else
result = PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi", result = PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi",
deque, old_deque->maxlen, NULL); deque, old_deque->maxlen, NULL);
@ -561,7 +628,18 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored))
return result; return result;
} }
PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque."); /*[clinic input]
_collections.deque.__copy__ as deque___copy__ = _collections.deque.copy
Return a shallow copy of a deque.
[clinic start generated code]*/
static PyObject *
deque___copy___impl(dequeobject *deque)
/*[clinic end generated code: output=7c5821504342bf23 input=fce05df783e7912b]*/
{
return deque_copy_impl(deque);
}
static PyObject * static PyObject *
deque_concat(dequeobject *deque, PyObject *other) deque_concat(dequeobject *deque, PyObject *other)
@ -580,7 +658,7 @@ deque_concat(dequeobject *deque, PyObject *other)
return NULL; return NULL;
} }
new_deque = deque_copy((PyObject *)deque, NULL); new_deque = deque_copy_impl(deque);
if (new_deque == NULL) if (new_deque == NULL)
return NULL; return NULL;
result = deque_extend((dequeobject *)new_deque, other); result = deque_extend((dequeobject *)new_deque, other);
@ -669,22 +747,29 @@ deque_clear(dequeobject *deque)
alternate_method: alternate_method:
while (Py_SIZE(deque)) { while (Py_SIZE(deque)) {
item = deque_pop(deque, NULL); item = deque_pop_impl(deque);
assert (item != NULL); assert (item != NULL);
Py_DECREF(item); Py_DECREF(item);
} }
return 0; return 0;
} }
/*[clinic input]
_collections.deque.clear as deque_clearmethod
deque: dequeobject
Remove all elements from the deque.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_clearmethod(dequeobject *deque, PyObject *Py_UNUSED(ignored)) deque_clearmethod_impl(dequeobject *deque)
/*[clinic end generated code: output=79b2513e097615c1 input=20488eb932f89f9e]*/
{ {
deque_clear(deque); deque_clear(deque);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
static PyObject * static PyObject *
deque_inplace_repeat(dequeobject *deque, Py_ssize_t n) deque_inplace_repeat(dequeobject *deque, Py_ssize_t n)
{ {
@ -768,7 +853,7 @@ deque_repeat(dequeobject *deque, Py_ssize_t n)
dequeobject *new_deque; dequeobject *new_deque;
PyObject *rv; PyObject *rv;
new_deque = (dequeobject *)deque_copy((PyObject *) deque, NULL); new_deque = (dequeobject *)deque_copy_impl(deque);
if (new_deque == NULL) if (new_deque == NULL)
return NULL; return NULL;
rv = deque_inplace_repeat(new_deque, n); rv = deque_inplace_repeat(new_deque, n);
@ -925,36 +1010,36 @@ done:
return rv; return rv;
} }
/*[clinic input]
_collections.deque.rotate as deque_rotate
deque: dequeobject
n: Py_ssize_t = 1
/
Rotate the deque n steps to the right. If n is negative, rotates left.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_rotate(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) deque_rotate_impl(dequeobject *deque, Py_ssize_t n)
/*[clinic end generated code: output=96c2402a371eb15d input=d22070f49cc06c76]*/
{ {
Py_ssize_t n=1;
if (!_PyArg_CheckPositional("deque.rotate", nargs, 0, 1)) {
return NULL;
}
if (nargs) {
PyObject *index = _PyNumber_Index(args[0]);
if (index == NULL) {
return NULL;
}
n = PyLong_AsSsize_t(index);
Py_DECREF(index);
if (n == -1 && PyErr_Occurred()) {
return NULL;
}
}
if (!_deque_rotate(deque, n)) if (!_deque_rotate(deque, n))
Py_RETURN_NONE; Py_RETURN_NONE;
return NULL; return NULL;
} }
PyDoc_STRVAR(rotate_doc, /*[clinic input]
"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left."); _collections.deque.reverse as deque_reverse
deque: dequeobject
Reverse *IN PLACE*.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_reverse(dequeobject *deque, PyObject *unused) deque_reverse_impl(dequeobject *deque)
/*[clinic end generated code: output=bdeebc2cf8c1f064 input=f139787f406101c9]*/
{ {
block *leftblock = deque->leftblock; block *leftblock = deque->leftblock;
block *rightblock = deque->rightblock; block *rightblock = deque->rightblock;
@ -991,11 +1076,19 @@ deque_reverse(dequeobject *deque, PyObject *unused)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(reverse_doc, /*[clinic input]
"D.reverse() -- reverse *IN PLACE*"); _collections.deque.count as deque_count
deque: dequeobject
value as v: object
/
Return number of occurrences of value.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_count(dequeobject *deque, PyObject *v) deque_count(dequeobject *deque, PyObject *v)
/*[clinic end generated code: output=7405d289d94d7b9b input=1892925260ff5d78]*/
{ {
block *b = deque->leftblock; block *b = deque->leftblock;
Py_ssize_t index = deque->leftindex; Py_ssize_t index = deque->leftindex;
@ -1030,9 +1123,6 @@ deque_count(dequeobject *deque, PyObject *v)
return PyLong_FromSsize_t(count); return PyLong_FromSsize_t(count);
} }
PyDoc_STRVAR(count_doc,
"D.count(value) -- return number of occurrences of value");
static int static int
deque_contains(dequeobject *deque, PyObject *v) deque_contains(dequeobject *deque, PyObject *v)
{ {
@ -1071,22 +1161,33 @@ deque_len(dequeobject *deque)
return Py_SIZE(deque); return Py_SIZE(deque);
} }
/*[clinic input]
@text_signature "($self, value, [start, [stop]])"
_collections.deque.index as deque_index
deque: dequeobject
value as v: object
start: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='0') = NULL
stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='Py_SIZE(deque)') = NULL
/
Return first index of value.
Raises ValueError if the value is not present.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_index(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start,
Py_ssize_t stop)
/*[clinic end generated code: output=df45132753175ef9 input=140210c099830f64]*/
{ {
Py_ssize_t i, n, start=0, stop=Py_SIZE(deque); Py_ssize_t i, n;
PyObject *v, *item; PyObject *item;
block *b = deque->leftblock; block *b = deque->leftblock;
Py_ssize_t index = deque->leftindex; Py_ssize_t index = deque->leftindex;
size_t start_state = deque->state; size_t start_state = deque->state;
int cmp; int cmp;
if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index", &v,
_PyEval_SliceIndexNotNone, &start,
_PyEval_SliceIndexNotNone, &stop)) {
return NULL;
}
if (start < 0) { if (start < 0) {
start += Py_SIZE(deque); start += Py_SIZE(deque);
if (start < 0) if (start < 0)
@ -1138,10 +1239,6 @@ deque_index(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
return NULL; return NULL;
} }
PyDoc_STRVAR(index_doc,
"D.index(value, [start, [stop]]) -- return first index of value.\n"
"Raises ValueError if the value is not present.");
/* insert(), remove(), and delitem() are implemented in terms of /* insert(), remove(), and delitem() are implemented in terms of
rotate() for simplicity and reasonable performance near the end rotate() for simplicity and reasonable performance near the end
points. If for some reason these methods become popular, it is not points. If for some reason these methods become popular, it is not
@ -1150,17 +1247,23 @@ PyDoc_STRVAR(index_doc,
boost (by moving each pointer only once instead of twice). boost (by moving each pointer only once instead of twice).
*/ */
static PyObject * /*[clinic input]
deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) _collections.deque.insert as deque_insert
{
Py_ssize_t index;
Py_ssize_t n = Py_SIZE(deque);
PyObject *value;
PyObject *rv;
if (!_PyArg_ParseStack(args, nargs, "nO:insert", &index, &value)) { deque: dequeobject
return NULL; index: Py_ssize_t
} value: object
/
Insert value before index.
[clinic start generated code]*/
static PyObject *
deque_insert_impl(dequeobject *deque, Py_ssize_t index, PyObject *value)
/*[clinic end generated code: output=ef4d2c15d5532b80 input=3e5c1c120d70c0e6]*/
{
Py_ssize_t n = Py_SIZE(deque);
PyObject *rv;
if (deque->maxlen == Py_SIZE(deque)) { if (deque->maxlen == Py_SIZE(deque)) {
PyErr_SetString(PyExc_IndexError, "deque already at its maximum size"); PyErr_SetString(PyExc_IndexError, "deque already at its maximum size");
@ -1184,12 +1287,6 @@ deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(insert_doc,
"D.insert(index, object) -- insert object before index");
PyDoc_STRVAR(remove_doc,
"D.remove(value) -- remove first occurrence of value.");
static int static int
valid_index(Py_ssize_t i, Py_ssize_t limit) valid_index(Py_ssize_t i, Py_ssize_t limit)
{ {
@ -1246,15 +1343,26 @@ deque_del_item(dequeobject *deque, Py_ssize_t i)
assert (i >= 0 && i < Py_SIZE(deque)); assert (i >= 0 && i < Py_SIZE(deque));
if (_deque_rotate(deque, -i)) if (_deque_rotate(deque, -i))
return -1; return -1;
item = deque_popleft(deque, NULL); item = deque_popleft_impl(deque);
rv = _deque_rotate(deque, i); rv = _deque_rotate(deque, i);
assert (item != NULL); assert (item != NULL);
Py_DECREF(item); Py_DECREF(item);
return rv; return rv;
} }
/*[clinic input]
_collections.deque.remove as deque_remove
deque: dequeobject
value: object
/
Remove first occurrence of value.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_remove(dequeobject *deque, PyObject *value) deque_remove(dequeobject *deque, PyObject *value)
/*[clinic end generated code: output=49e1666d612fe911 input=d972f32d15990880]*/
{ {
PyObject *item; PyObject *item;
block *b = deque->leftblock; block *b = deque->leftblock;
@ -1375,8 +1483,17 @@ deque_traverse(dequeobject *deque, visitproc visit, void *arg)
return 0; return 0;
} }
/*[clinic input]
_collections.deque.__reduce__ as deque___reduce__
deque: dequeobject
Return state information for pickling.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_reduce(dequeobject *deque, PyObject *Py_UNUSED(ignored)) deque___reduce___impl(dequeobject *deque)
/*[clinic end generated code: output=cb85d9e0b7d2c5ad input=991a933a5bc7a526]*/
{ {
PyObject *state, *it; PyObject *state, *it;
@ -1510,26 +1627,23 @@ done:
return NULL; return NULL;
} }
static int /*[clinic input]
deque_init(dequeobject *deque, PyObject *args, PyObject *kwdargs) @text_signature "([iterable[, maxlen]])"
{ _collections.deque.__init__ as deque_init
PyObject *iterable = NULL;
PyObject *maxlenobj = NULL;
Py_ssize_t maxlen = -1;
char *kwlist[] = {"iterable", "maxlen", 0};
if (kwdargs == NULL && PyTuple_GET_SIZE(args) <= 2) { deque: dequeobject
if (PyTuple_GET_SIZE(args) > 0) { iterable: object = NULL
iterable = PyTuple_GET_ITEM(args, 0); maxlen as maxlenobj: object = NULL
}
if (PyTuple_GET_SIZE(args) > 1) { A list-like sequence optimized for data accesses near its endpoints.
maxlenobj = PyTuple_GET_ITEM(args, 1); [clinic start generated code]*/
}
} else { static int
if (!PyArg_ParseTupleAndKeywords(args, kwdargs, "|OO:deque", kwlist, deque_init_impl(dequeobject *deque, PyObject *iterable, PyObject *maxlenobj)
&iterable, &maxlenobj)) /*[clinic end generated code: output=7084a39d71218dcd input=5ebdffc48a2d27ae]*/
return -1;
} {
Py_ssize_t maxlen = -1;
if (maxlenobj != NULL && maxlenobj != Py_None) { if (maxlenobj != NULL && maxlenobj != Py_None) {
maxlen = PyLong_AsSsize_t(maxlenobj); maxlen = PyLong_AsSsize_t(maxlenobj);
if (maxlen == -1 && PyErr_Occurred()) if (maxlen == -1 && PyErr_Occurred())
@ -1551,8 +1665,17 @@ deque_init(dequeobject *deque, PyObject *args, PyObject *kwdargs)
return 0; return 0;
} }
/*[clinic input]
_collections.deque.__sizeof__ as deque___sizeof__
deque: dequeobject
Return the size of the deque in memory, in bytes.
[clinic start generated code]*/
static PyObject * static PyObject *
deque_sizeof(dequeobject *deque, void *unused) deque___sizeof___impl(dequeobject *deque)
/*[clinic end generated code: output=4d36e9fb4f30bbaf input=4e7c9a00c03c3290]*/
{ {
size_t res = _PyObject_SIZE(Py_TYPE(deque)); size_t res = _PyObject_SIZE(Py_TYPE(deque));
size_t blocks; size_t blocks;
@ -1563,9 +1686,6 @@ deque_sizeof(dequeobject *deque, void *unused)
return PyLong_FromSize_t(res); return PyLong_FromSize_t(res);
} }
PyDoc_STRVAR(sizeof_doc,
"D.__sizeof__() -- size of D in memory, in bytes");
static PyObject * static PyObject *
deque_get_maxlen(dequeobject *deque, void *Py_UNUSED(ignored)) deque_get_maxlen(dequeobject *deque, void *Py_UNUSED(ignored))
{ {
@ -1574,6 +1694,22 @@ deque_get_maxlen(dequeobject *deque, void *Py_UNUSED(ignored))
return PyLong_FromSsize_t(deque->maxlen); return PyLong_FromSsize_t(deque->maxlen);
} }
static PyObject *deque_reviter(dequeobject *deque);
/*[clinic input]
_collections.deque.__reversed__ as deque___reversed__
deque: dequeobject
Return a reverse iterator over the deque.
[clinic start generated code]*/
static PyObject *
deque___reversed___impl(dequeobject *deque)
/*[clinic end generated code: output=3e7e7e715883cf2e input=3d494c25a6fe5c7e]*/
{
return deque_reviter(deque);
}
/* deque object ********************************************************/ /* deque object ********************************************************/
@ -1584,47 +1720,26 @@ static PyGetSetDef deque_getset[] = {
}; };
static PyObject *deque_iter(dequeobject *deque); static PyObject *deque_iter(dequeobject *deque);
static PyObject *deque_reviter(dequeobject *deque, PyObject *Py_UNUSED(ignored));
PyDoc_STRVAR(reversed_doc,
"D.__reversed__() -- return a reverse iterator over the deque");
static PyMethodDef deque_methods[] = { static PyMethodDef deque_methods[] = {
{"append", (PyCFunction)deque_append, DEQUE_APPEND_METHODDEF
METH_O, append_doc}, DEQUE_APPENDLEFT_METHODDEF
{"appendleft", (PyCFunction)deque_appendleft, DEQUE_CLEARMETHOD_METHODDEF
METH_O, appendleft_doc}, DEQUE___COPY___METHODDEF
{"clear", (PyCFunction)deque_clearmethod, DEQUE_COPY_METHODDEF
METH_NOARGS, clear_doc}, DEQUE_COUNT_METHODDEF
{"__copy__", deque_copy, DEQUE_EXTEND_METHODDEF
METH_NOARGS, copy_doc}, DEQUE_EXTENDLEFT_METHODDEF
{"copy", deque_copy, DEQUE_INDEX_METHODDEF
METH_NOARGS, copy_doc}, DEQUE_INSERT_METHODDEF
{"count", (PyCFunction)deque_count, DEQUE_POP_METHODDEF
METH_O, count_doc}, DEQUE_POPLEFT_METHODDEF
{"extend", (PyCFunction)deque_extend, DEQUE___REDUCE___METHODDEF
METH_O, extend_doc}, DEQUE_REMOVE_METHODDEF
{"extendleft", (PyCFunction)deque_extendleft, DEQUE___REVERSED___METHODDEF
METH_O, extendleft_doc}, DEQUE_REVERSE_METHODDEF
{"index", _PyCFunction_CAST(deque_index), DEQUE_ROTATE_METHODDEF
METH_FASTCALL, index_doc}, DEQUE___SIZEOF___METHODDEF
{"insert", _PyCFunction_CAST(deque_insert),
METH_FASTCALL, insert_doc},
{"pop", (PyCFunction)deque_pop,
METH_NOARGS, pop_doc},
{"popleft", (PyCFunction)deque_popleft,
METH_NOARGS, popleft_doc},
{"__reduce__", (PyCFunction)deque_reduce,
METH_NOARGS, reduce_doc},
{"remove", (PyCFunction)deque_remove,
METH_O, remove_doc},
{"__reversed__", (PyCFunction)deque_reviter,
METH_NOARGS, reversed_doc},
{"reverse", (PyCFunction)deque_reverse,
METH_NOARGS, reverse_doc},
{"rotate", _PyCFunction_CAST(deque_rotate),
METH_FASTCALL, rotate_doc},
{"__sizeof__", (PyCFunction)deque_sizeof,
METH_NOARGS, sizeof_doc},
{"__class_getitem__", Py_GenericAlias, {"__class_getitem__", Py_GenericAlias,
METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
@ -1635,17 +1750,12 @@ static PyMemberDef deque_members[] = {
{NULL}, {NULL},
}; };
PyDoc_STRVAR(deque_doc,
"deque([iterable[, maxlen]]) --> deque object\n\
\n\
A list-like sequence optimized for data accesses near its endpoints.");
static PyType_Slot deque_slots[] = { static PyType_Slot deque_slots[] = {
{Py_tp_dealloc, deque_dealloc}, {Py_tp_dealloc, deque_dealloc},
{Py_tp_repr, deque_repr}, {Py_tp_repr, deque_repr},
{Py_tp_hash, PyObject_HashNotImplemented}, {Py_tp_hash, PyObject_HashNotImplemented},
{Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_doc, (void *)deque_doc}, {Py_tp_doc, (void *)deque_init__doc__},
{Py_tp_traverse, deque_traverse}, {Py_tp_traverse, deque_traverse},
{Py_tp_clear, deque_clear}, {Py_tp_clear, deque_clear},
{Py_tp_richcompare, deque_richcompare}, {Py_tp_richcompare, deque_richcompare},
@ -1834,7 +1944,7 @@ static PyType_Spec dequeiter_spec = {
/*********************** Deque Reverse Iterator **************************/ /*********************** Deque Reverse Iterator **************************/
static PyObject * static PyObject *
deque_reviter(dequeobject *deque, PyObject *Py_UNUSED(ignored)) deque_reviter(dequeobject *deque)
{ {
dequeiterobject *it; dequeiterobject *it;
collections_state *state = find_module_state_by_def(Py_TYPE(deque)); collections_state *state = find_module_state_by_def(Py_TYPE(deque));
@ -1889,7 +1999,7 @@ dequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
assert(type == state->dequereviter_type); assert(type == state->dequereviter_type);
it = (dequeiterobject*)deque_reviter((dequeobject *)deque, NULL); it = (dequeiterobject *)deque_reviter((dequeobject *)deque);
if (!it) if (!it)
return NULL; return NULL;
/* consume items from the queue */ /* consume items from the queue */

View file

@ -2,9 +2,425 @@
preserve preserve
[clinic start generated code]*/ [clinic start generated code]*/
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_modsupport.h" // _PyArg_CheckPositional() #include "pycore_modsupport.h" // _PyArg_CheckPositional()
PyDoc_STRVAR(deque_pop__doc__,
"pop($self, /)\n"
"--\n"
"\n"
"Remove and return the rightmost element.");
#define DEQUE_POP_METHODDEF \
{"pop", (PyCFunction)deque_pop, METH_NOARGS, deque_pop__doc__},
static PyObject *
deque_pop_impl(dequeobject *deque);
static PyObject *
deque_pop(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque_pop_impl(deque);
}
PyDoc_STRVAR(deque_popleft__doc__,
"popleft($self, /)\n"
"--\n"
"\n"
"Remove and return the leftmost element.");
#define DEQUE_POPLEFT_METHODDEF \
{"popleft", (PyCFunction)deque_popleft, METH_NOARGS, deque_popleft__doc__},
static PyObject *
deque_popleft_impl(dequeobject *deque);
static PyObject *
deque_popleft(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque_popleft_impl(deque);
}
PyDoc_STRVAR(deque_append__doc__,
"append($self, item, /)\n"
"--\n"
"\n"
"Add an element to the right side of the deque.");
#define DEQUE_APPEND_METHODDEF \
{"append", (PyCFunction)deque_append, METH_O, deque_append__doc__},
PyDoc_STRVAR(deque_appendleft__doc__,
"appendleft($self, item, /)\n"
"--\n"
"\n"
"Add an element to the left side of the deque.");
#define DEQUE_APPENDLEFT_METHODDEF \
{"appendleft", (PyCFunction)deque_appendleft, METH_O, deque_appendleft__doc__},
PyDoc_STRVAR(deque_extend__doc__,
"extend($self, iterable, /)\n"
"--\n"
"\n"
"Extend the right side of the deque with elements from the iterable.");
#define DEQUE_EXTEND_METHODDEF \
{"extend", (PyCFunction)deque_extend, METH_O, deque_extend__doc__},
PyDoc_STRVAR(deque_extendleft__doc__,
"extendleft($self, iterable, /)\n"
"--\n"
"\n"
"Extend the left side of the deque with elements from the iterable.");
#define DEQUE_EXTENDLEFT_METHODDEF \
{"extendleft", (PyCFunction)deque_extendleft, METH_O, deque_extendleft__doc__},
PyDoc_STRVAR(deque_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a shallow copy of a deque.");
#define DEQUE_COPY_METHODDEF \
{"copy", (PyCFunction)deque_copy, METH_NOARGS, deque_copy__doc__},
static PyObject *
deque_copy_impl(dequeobject *deque);
static PyObject *
deque_copy(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque_copy_impl(deque);
}
PyDoc_STRVAR(deque___copy____doc__,
"__copy__($self, /)\n"
"--\n"
"\n"
"Return a shallow copy of a deque.");
#define DEQUE___COPY___METHODDEF \
{"__copy__", (PyCFunction)deque___copy__, METH_NOARGS, deque___copy____doc__},
static PyObject *
deque___copy___impl(dequeobject *deque);
static PyObject *
deque___copy__(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque___copy___impl(deque);
}
PyDoc_STRVAR(deque_clearmethod__doc__,
"clear($self, /)\n"
"--\n"
"\n"
"Remove all elements from the deque.");
#define DEQUE_CLEARMETHOD_METHODDEF \
{"clear", (PyCFunction)deque_clearmethod, METH_NOARGS, deque_clearmethod__doc__},
static PyObject *
deque_clearmethod_impl(dequeobject *deque);
static PyObject *
deque_clearmethod(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque_clearmethod_impl(deque);
}
PyDoc_STRVAR(deque_rotate__doc__,
"rotate($self, n=1, /)\n"
"--\n"
"\n"
"Rotate the deque n steps to the right. If n is negative, rotates left.");
#define DEQUE_ROTATE_METHODDEF \
{"rotate", _PyCFunction_CAST(deque_rotate), METH_FASTCALL, deque_rotate__doc__},
static PyObject *
deque_rotate_impl(dequeobject *deque, Py_ssize_t n);
static PyObject *
deque_rotate(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_ssize_t n = 1;
if (!_PyArg_CheckPositional("rotate", nargs, 0, 1)) {
goto exit;
}
if (nargs < 1) {
goto skip_optional;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[0]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
n = ival;
}
skip_optional:
return_value = deque_rotate_impl(deque, n);
exit:
return return_value;
}
PyDoc_STRVAR(deque_reverse__doc__,
"reverse($self, /)\n"
"--\n"
"\n"
"Reverse *IN PLACE*.");
#define DEQUE_REVERSE_METHODDEF \
{"reverse", (PyCFunction)deque_reverse, METH_NOARGS, deque_reverse__doc__},
static PyObject *
deque_reverse_impl(dequeobject *deque);
static PyObject *
deque_reverse(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque_reverse_impl(deque);
}
PyDoc_STRVAR(deque_count__doc__,
"count($self, value, /)\n"
"--\n"
"\n"
"Return number of occurrences of value.");
#define DEQUE_COUNT_METHODDEF \
{"count", (PyCFunction)deque_count, METH_O, deque_count__doc__},
PyDoc_STRVAR(deque_index__doc__,
"index($self, value, [start, [stop]])\n"
"--\n"
"\n"
"Return first index of value.\n"
"\n"
"Raises ValueError if the value is not present.");
#define DEQUE_INDEX_METHODDEF \
{"index", _PyCFunction_CAST(deque_index), METH_FASTCALL, deque_index__doc__},
static PyObject *
deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start,
Py_ssize_t stop);
static PyObject *
deque_index(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *v;
Py_ssize_t start = 0;
Py_ssize_t stop = Py_SIZE(deque);
if (!_PyArg_CheckPositional("index", nargs, 1, 3)) {
goto exit;
}
v = args[0];
if (nargs < 2) {
goto skip_optional;
}
if (!_PyEval_SliceIndexNotNone(args[1], &start)) {
goto exit;
}
if (nargs < 3) {
goto skip_optional;
}
if (!_PyEval_SliceIndexNotNone(args[2], &stop)) {
goto exit;
}
skip_optional:
return_value = deque_index_impl(deque, v, start, stop);
exit:
return return_value;
}
PyDoc_STRVAR(deque_insert__doc__,
"insert($self, index, value, /)\n"
"--\n"
"\n"
"Insert value before index.");
#define DEQUE_INSERT_METHODDEF \
{"insert", _PyCFunction_CAST(deque_insert), METH_FASTCALL, deque_insert__doc__},
static PyObject *
deque_insert_impl(dequeobject *deque, Py_ssize_t index, PyObject *value);
static PyObject *
deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_ssize_t index;
PyObject *value;
if (!_PyArg_CheckPositional("insert", nargs, 2, 2)) {
goto exit;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[0]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
index = ival;
}
value = args[1];
return_value = deque_insert_impl(deque, index, value);
exit:
return return_value;
}
PyDoc_STRVAR(deque_remove__doc__,
"remove($self, value, /)\n"
"--\n"
"\n"
"Remove first occurrence of value.");
#define DEQUE_REMOVE_METHODDEF \
{"remove", (PyCFunction)deque_remove, METH_O, deque_remove__doc__},
PyDoc_STRVAR(deque___reduce____doc__,
"__reduce__($self, /)\n"
"--\n"
"\n"
"Return state information for pickling.");
#define DEQUE___REDUCE___METHODDEF \
{"__reduce__", (PyCFunction)deque___reduce__, METH_NOARGS, deque___reduce____doc__},
static PyObject *
deque___reduce___impl(dequeobject *deque);
static PyObject *
deque___reduce__(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque___reduce___impl(deque);
}
PyDoc_STRVAR(deque_init__doc__,
"deque([iterable[, maxlen]])\n"
"--\n"
"\n"
"A list-like sequence optimized for data accesses near its endpoints.");
static int
deque_init_impl(dequeobject *deque, PyObject *iterable, PyObject *maxlenobj);
static int
deque_init(PyObject *deque, PyObject *args, PyObject *kwargs)
{
int return_value = -1;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(iterable), &_Py_ID(maxlen), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"iterable", "maxlen", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "deque",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
PyObject *iterable = NULL;
PyObject *maxlenobj = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 2, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!noptargs) {
goto skip_optional_pos;
}
if (fastargs[0]) {
iterable = fastargs[0];
if (!--noptargs) {
goto skip_optional_pos;
}
}
maxlenobj = fastargs[1];
skip_optional_pos:
return_value = deque_init_impl((dequeobject *)deque, iterable, maxlenobj);
exit:
return return_value;
}
PyDoc_STRVAR(deque___sizeof____doc__,
"__sizeof__($self, /)\n"
"--\n"
"\n"
"Return the size of the deque in memory, in bytes.");
#define DEQUE___SIZEOF___METHODDEF \
{"__sizeof__", (PyCFunction)deque___sizeof__, METH_NOARGS, deque___sizeof____doc__},
static PyObject *
deque___sizeof___impl(dequeobject *deque);
static PyObject *
deque___sizeof__(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque___sizeof___impl(deque);
}
PyDoc_STRVAR(deque___reversed____doc__,
"__reversed__($self, /)\n"
"--\n"
"\n"
"Return a reverse iterator over the deque.");
#define DEQUE___REVERSED___METHODDEF \
{"__reversed__", (PyCFunction)deque___reversed__, METH_NOARGS, deque___reversed____doc__},
static PyObject *
deque___reversed___impl(dequeobject *deque);
static PyObject *
deque___reversed__(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
return deque___reversed___impl(deque);
}
PyDoc_STRVAR(_collections__count_elements__doc__, PyDoc_STRVAR(_collections__count_elements__doc__,
"_count_elements($module, mapping, iterable, /)\n" "_count_elements($module, mapping, iterable, /)\n"
"--\n" "--\n"
@ -72,4 +488,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=c896a72f8c45930d input=a9049054013a1b77]*/ /*[clinic end generated code: output=3633a5cbc23e8440 input=a9049054013a1b77]*/