Skip to content

bpo-40665: Use Argument Clinic for bisect #20163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Convert :mod:`bisect` to use Argument Clinic.
236 changes: 105 additions & 131 deletions Modules/_bisectmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
#define PY_SSIZE_T_CLEAN
#include "Python.h"

/*[clinic input]
module _bisect
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4d56a2b2033b462b]*/

#include "clinic/_bisectmodule.c.h"

_Py_IDENTIFIER(insert);

static inline Py_ssize_t
Expand Down Expand Up @@ -44,69 +51,63 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t
return lo;
}

static PyObject *
bisect_right(PyObject *self, PyObject *args, PyObject *kw)
/*[clinic input]
_bisect.bisect_right -> Py_ssize_t

a: object
x: object
lo: Py_ssize_t = 0
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None

Return the index where to insert item x in list a, assuming a is sorted.

The return value i is such that all e in a[:i] have e <= x, and all e in
a[i:] have e > x. So if x already appears in the list, i points just
beyond the rightmost x already there

Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
[clinic start generated code]*/

static Py_ssize_t
_bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x,
Py_ssize_t lo, Py_ssize_t hi)
/*[clinic end generated code: output=419e150cf1d2a235 input=e72212b282c83375]*/
{
PyObject *list, *item;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};

if (kw == NULL && PyTuple_GET_SIZE(args) == 2) {
list = PyTuple_GET_ITEM(args, 0);
item = PyTuple_GET_ITEM(args, 1);
}
else {
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_right",
keywords, &list, &item, &lo, &hi))
return NULL;
}
index = internal_bisect_right(list, item, lo, hi);
if (index < 0)
return NULL;
return PyLong_FromSsize_t(index);
return internal_bisect_right(a, x, lo, hi);
}

PyDoc_STRVAR(bisect_right_doc,
"bisect_right(a, x[, lo[, hi]]) -> index\n\
\n\
Return the index where to insert item x in list a, assuming a is sorted.\n\
\n\
The return value i is such that all e in a[:i] have e <= x, and all e in\n\
a[i:] have e > x. So if x already appears in the list, i points just\n\
beyond the rightmost x already there\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");
/*[clinic input]
_bisect.insort_right

a: object
x: object
lo: Py_ssize_t = 0
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None

Insert item x in list a, and keep it sorted assuming a is sorted.

If x is already in a, insert it to the right of the rightmost x.

Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
[clinic start generated code]*/

static PyObject *
insort_right(PyObject *self, PyObject *args, PyObject *kw)
_bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
Py_ssize_t lo, Py_ssize_t hi)
/*[clinic end generated code: output=c2caa3d4cd02035a input=d1c45bfa68182669]*/
{
PyObject *list, *item, *result;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};

if (kw == NULL && PyTuple_GET_SIZE(args) == 2) {
list = PyTuple_GET_ITEM(args, 0);
item = PyTuple_GET_ITEM(args, 1);
}
else {
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_right",
keywords, &list, &item, &lo, &hi))
return NULL;
}
index = internal_bisect_right(list, item, lo, hi);
PyObject *result;
Py_ssize_t index = internal_bisect_right(a, x, lo, hi);
if (index < 0)
return NULL;
if (PyList_CheckExact(list)) {
if (PyList_Insert(list, index, item) < 0)
if (PyList_CheckExact(a)) {
if (PyList_Insert(a, index, x) < 0)
return NULL;
}
else {
result = _PyObject_CallMethodId(list, &PyId_insert, "nO", index, item);
result = _PyObject_CallMethodId(a, &PyId_insert, "nO", index, x);
if (result == NULL)
return NULL;
Py_DECREF(result);
Expand All @@ -115,16 +116,6 @@ insort_right(PyObject *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
}

PyDoc_STRVAR(insort_right_doc,
"insort_right(a, x[, lo[, hi]])\n\
\n\
Insert item x in list a, and keep it sorted assuming a is sorted.\n\
\n\
If x is already in a, insert it to the right of the rightmost x.\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");

static inline Py_ssize_t
internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi)
{
Expand Down Expand Up @@ -161,67 +152,64 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h
return lo;
}

static PyObject *
bisect_left(PyObject *self, PyObject *args, PyObject *kw)

/*[clinic input]
_bisect.bisect_left -> Py_ssize_t

a: object
x: object
lo: Py_ssize_t = 0
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None

Return the index where to insert item x in list a, assuming a is sorted.

The return value i is such that all e in a[:i] have e < x, and all e in
a[i:] have e >= x. So if x already appears in the list, i points just
before the leftmost x already there.

Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
[clinic start generated code]*/

static Py_ssize_t
_bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x,
Py_ssize_t lo, Py_ssize_t hi)
/*[clinic end generated code: output=af82168bc2856f24 input=2bd90f34afe5609f]*/
{
PyObject *list, *item;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};

if (kw == NULL && PyTuple_GET_SIZE(args) == 2) {
list = PyTuple_GET_ITEM(args, 0);
item = PyTuple_GET_ITEM(args, 1);
}
else {
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_left",
keywords, &list, &item, &lo, &hi))
return NULL;
}
index = internal_bisect_left(list, item, lo, hi);
if (index < 0)
return NULL;
return PyLong_FromSsize_t(index);
return internal_bisect_left(a, x, lo, hi);
}

PyDoc_STRVAR(bisect_left_doc,
"bisect_left(a, x[, lo[, hi]]) -> index\n\
\n\
Return the index where to insert item x in list a, assuming a is sorted.\n\
\n\
The return value i is such that all e in a[:i] have e < x, and all e in\n\
a[i:] have e >= x. So if x already appears in the list, i points just\n\
before the leftmost x already there.\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");

/*[clinic input]
_bisect.insort_left

a: object
x: object
lo: Py_ssize_t = 0
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None

Insert item x in list a, and keep it sorted assuming a is sorted.

If x is already in a, insert it to the left of the leftmost x.

Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
[clinic start generated code]*/

static PyObject *
insort_left(PyObject *self, PyObject *args, PyObject *kw)
_bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x,
Py_ssize_t lo, Py_ssize_t hi)
/*[clinic end generated code: output=9e8356c0844a182b input=bc4583308bce00cc]*/
{
PyObject *list, *item, *result;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};

if (kw == NULL && PyTuple_GET_SIZE(args) == 2) {
list = PyTuple_GET_ITEM(args, 0);
item = PyTuple_GET_ITEM(args, 1);
} else {
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_left",
keywords, &list, &item, &lo, &hi))
return NULL;
}
index = internal_bisect_left(list, item, lo, hi);
PyObject *result;
Py_ssize_t index = internal_bisect_left(a, x, lo, hi);
if (index < 0)
return NULL;
if (PyList_CheckExact(list)) {
if (PyList_Insert(list, index, item) < 0)
if (PyList_CheckExact(a)) {
if (PyList_Insert(a, index, x) < 0)
return NULL;
} else {
result = _PyObject_CallMethodId(list, &PyId_insert, "nO", index, item);
result = _PyObject_CallMethodId(a, &PyId_insert, "nO", index, x);
if (result == NULL)
return NULL;
Py_DECREF(result);
Expand All @@ -230,25 +218,11 @@ insort_left(PyObject *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
}

PyDoc_STRVAR(insort_left_doc,
"insort_left(a, x[, lo[, hi]])\n\
\n\
Insert item x in list a, and keep it sorted assuming a is sorted.\n\
\n\
If x is already in a, insert it to the left of the leftmost x.\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");

static PyMethodDef bisect_methods[] = {
{"bisect_right", (PyCFunction)(void(*)(void))bisect_right,
METH_VARARGS|METH_KEYWORDS, bisect_right_doc},
{"insort_right", (PyCFunction)(void(*)(void))insort_right,
METH_VARARGS|METH_KEYWORDS, insort_right_doc},
{"bisect_left", (PyCFunction)(void(*)(void))bisect_left,
METH_VARARGS|METH_KEYWORDS, bisect_left_doc},
{"insort_left", (PyCFunction)(void(*)(void))insort_left,
METH_VARARGS|METH_KEYWORDS, insort_left_doc},
_BISECT_BISECT_RIGHT_METHODDEF
_BISECT_INSORT_RIGHT_METHODDEF
_BISECT_BISECT_LEFT_METHODDEF
_BISECT_INSORT_LEFT_METHODDEF
{NULL, NULL} /* sentinel */
};

Expand Down
Loading