diff --git a/Lib/bisect.py b/Lib/bisect.py index 7732c639e38699..46dcb509fe6ff4 100644 --- a/Lib/bisect.py +++ b/Lib/bisect.py @@ -11,7 +11,7 @@ def insort_right(a, x, lo=0, hi=None): if lo < 0: raise ValueError('lo must be non-negative') - if hi is None: + if hi is None or hi == -1: hi = len(a) while lo < hi: mid = (lo+hi)//2 @@ -32,7 +32,7 @@ def bisect_right(a, x, lo=0, hi=None): if lo < 0: raise ValueError('lo must be non-negative') - if hi is None: + if hi is None or hi == -1: hi = len(a) while lo < hi: mid = (lo+hi)//2 @@ -51,7 +51,7 @@ def insort_left(a, x, lo=0, hi=None): if lo < 0: raise ValueError('lo must be non-negative') - if hi is None: + if hi is None or hi == -1: hi = len(a) while lo < hi: mid = (lo+hi)//2 @@ -73,7 +73,7 @@ def bisect_left(a, x, lo=0, hi=None): if lo < 0: raise ValueError('lo must be non-negative') - if hi is None: + if hi is None or hi == -1: hi = len(a) while lo < hi: mid = (lo+hi)//2 diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py index 580a963f627a34..bf514335a0805e 100644 --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -186,6 +186,11 @@ def test_optionalSlicing(self): self.assertTrue(data[ip-1] <= elem) self.assertEqual(ip, max(lo, min(hi, expected))) + def test_hi_backcompatbility(self): + for func, data, elem, expected in self.precomputedCases: + self.assertEqual(func(data, elem, 0, -1), + func(data, elem, 0, None)) + def test_backcompatibility(self): self.assertEqual(self.module.bisect, self.module.bisect_right) diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c index 831e10aa6078bb..88610c5effccac 100644 --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -6,6 +6,39 @@ Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru). #define PY_SSIZE_T_CLEAN #include "Python.h" +static int +ssize_t_converter(PyObject *obj, void *ptr) +{ + Py_ssize_t val; + + val = PyLong_AsSsize_t(obj); + if (val == -1 && PyErr_Occurred()) { + return 0; + } + *(Py_ssize_t *)ptr = val; + return 1; +} + +static int +optional_ssize_t_converter(PyObject *obj, void *ptr) +{ + if (obj != Py_None) { + return ssize_t_converter(obj, ptr); + } + else { + *(Py_ssize_t *)ptr = -1; + return 1; + } +} + + +#include "clinic/_bisectmodule.c.h" + +/*[clinic input] +module bisect +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d0e256c42a9e4c13]*/ + _Py_IDENTIFIER(insert); static Py_ssize_t @@ -44,56 +77,79 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t return lo; } +/*[python input] +class hi_parameter_converter(CConverter): + type = 'Py_ssize_t' + converter = 'optional_ssize_t_converter' + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=53c711121eb30d3f]*/ + + +/*[clinic input] +bisect.bisect_right + + a: object + x: object + lo: Py_ssize_t(c_default='0') = 0 + hi: hi_parameter(c_default='-1') = 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 PyObject * -bisect_right(PyObject *self, PyObject *args, PyObject *kw) +bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, + Py_ssize_t lo, Py_ssize_t hi) +/*[clinic end generated code: output=a2fb3e3261e46954 input=94e1e505e7f1ced8]*/ { - 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 (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_right", - keywords, &list, &item, &lo, &hi)) - return NULL; - index = internal_bisect_right(list, item, lo, hi); + index = internal_bisect_right(a, x, lo, hi); if (index < 0) return NULL; return PyLong_FromSsize_t(index); } -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(c_default='0') = 0 + hi: hi_parameter(c_default='-1') = 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=6e0b99c731a11c1a input=6790b22da4643197]*/ { - PyObject *list, *item, *result; - Py_ssize_t lo = 0; - Py_ssize_t hi = -1; + PyObject *result; Py_ssize_t index; - static char *keywords[] = {"a", "x", "lo", "hi", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_right", - keywords, &list, &item, &lo, &hi)) - return NULL; - index = internal_bisect_right(list, item, lo, hi); + 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); @@ -102,16 +158,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 Py_ssize_t internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi) { @@ -148,56 +194,71 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h return lo; } +/*[clinic input] +bisect.bisect_left + + a: object + x: object + lo: Py_ssize_t(c_default='0') = 0 + hi: hi_parameter(c_default='-1') = 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 PyObject * -bisect_left(PyObject *self, PyObject *args, PyObject *kw) +bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, + Py_ssize_t lo, Py_ssize_t hi) +/*[clinic end generated code: output=27a0228c4a0a5fa2 input=fc1e8f6081ccfd7c]*/ { - 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 (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_left", - keywords, &list, &item, &lo, &hi)) - return NULL; - index = internal_bisect_left(list, item, lo, hi); + index = internal_bisect_left(a, x, lo, hi); if (index < 0) return NULL; return PyLong_FromSsize_t(index); } -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(c_default='0') = 0 + hi: hi_parameter(c_default='-1') = 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=aa0228af6970ec52 input=582456c4727c5716]*/ { - PyObject *list, *item, *result; - Py_ssize_t lo = 0; - Py_ssize_t hi = -1; + PyObject *result; Py_ssize_t index; - static char *keywords[] = {"a", "x", "lo", "hi", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_left", - keywords, &list, &item, &lo, &hi)) - return NULL; - index = internal_bisect_left(list, item, lo, hi); + 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); @@ -206,25 +267,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)bisect_right, - METH_VARARGS|METH_KEYWORDS, bisect_right_doc}, - {"insort_right", (PyCFunction)insort_right, - METH_VARARGS|METH_KEYWORDS, insort_right_doc}, - {"bisect_left", (PyCFunction)bisect_left, - METH_VARARGS|METH_KEYWORDS, bisect_left_doc}, - {"insort_left", (PyCFunction)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 */ }; diff --git a/Modules/clinic/_bisectmodule.c.h b/Modules/clinic/_bisectmodule.c.h new file mode 100644 index 00000000000000..d79f1d98e9c4bc --- /dev/null +++ b/Modules/clinic/_bisectmodule.c.h @@ -0,0 +1,164 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(bisect_bisect_right__doc__, +"bisect_right($module, /, a, x, lo=0, hi=None)\n" +"--\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."); + +#define BISECT_BISECT_RIGHT_METHODDEF \ + {"bisect_right", (PyCFunction)bisect_bisect_right, METH_FASTCALL, bisect_bisect_right__doc__}, + +static PyObject * +bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, + Py_ssize_t lo, Py_ssize_t hi); + +static PyObject * +bisect_bisect_right(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static _PyArg_Parser _parser = {"OO|nO&:bisect_right", _keywords, 0}; + PyObject *a; + PyObject *x; + Py_ssize_t lo = 0; + Py_ssize_t hi = -1; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &a, &x, &lo, optional_ssize_t_converter, &hi)) { + goto exit; + } + return_value = bisect_bisect_right_impl(module, a, x, lo, hi); + +exit: + return return_value; +} + +PyDoc_STRVAR(bisect_insort_right__doc__, +"insort_right($module, /, a, x, lo=0, hi=None)\n" +"--\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."); + +#define BISECT_INSORT_RIGHT_METHODDEF \ + {"insort_right", (PyCFunction)bisect_insort_right, METH_FASTCALL, bisect_insort_right__doc__}, + +static PyObject * +bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x, + Py_ssize_t lo, Py_ssize_t hi); + +static PyObject * +bisect_insort_right(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static _PyArg_Parser _parser = {"OO|nO&:insort_right", _keywords, 0}; + PyObject *a; + PyObject *x; + Py_ssize_t lo = 0; + Py_ssize_t hi = -1; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &a, &x, &lo, optional_ssize_t_converter, &hi)) { + goto exit; + } + return_value = bisect_insort_right_impl(module, a, x, lo, hi); + +exit: + return return_value; +} + +PyDoc_STRVAR(bisect_bisect_left__doc__, +"bisect_left($module, /, a, x, lo=0, hi=None)\n" +"--\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."); + +#define BISECT_BISECT_LEFT_METHODDEF \ + {"bisect_left", (PyCFunction)bisect_bisect_left, METH_FASTCALL, bisect_bisect_left__doc__}, + +static PyObject * +bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, + Py_ssize_t lo, Py_ssize_t hi); + +static PyObject * +bisect_bisect_left(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static _PyArg_Parser _parser = {"OO|nO&:bisect_left", _keywords, 0}; + PyObject *a; + PyObject *x; + Py_ssize_t lo = 0; + Py_ssize_t hi = -1; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &a, &x, &lo, optional_ssize_t_converter, &hi)) { + goto exit; + } + return_value = bisect_bisect_left_impl(module, a, x, lo, hi); + +exit: + return return_value; +} + +PyDoc_STRVAR(bisect_insort_left__doc__, +"insort_left($module, /, a, x, lo=0, hi=None)\n" +"--\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."); + +#define BISECT_INSORT_LEFT_METHODDEF \ + {"insort_left", (PyCFunction)bisect_insort_left, METH_FASTCALL, bisect_insort_left__doc__}, + +static PyObject * +bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x, + Py_ssize_t lo, Py_ssize_t hi); + +static PyObject * +bisect_insort_left(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static _PyArg_Parser _parser = {"OO|nO&:insort_left", _keywords, 0}; + PyObject *a; + PyObject *x; + Py_ssize_t lo = 0; + Py_ssize_t hi = -1; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &a, &x, &lo, optional_ssize_t_converter, &hi)) { + goto exit; + } + return_value = bisect_insort_left_impl(module, a, x, lo, hi); + +exit: + return return_value; +} +/*[clinic end generated code: output=f21a122da59705d0 input=a9049054013a1b77]*/ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy