mirror of
https://github.com/python/cpython.git
synced 2025-11-24 20:30:18 +00:00
Issue 3501: Make heapq support both __le__ and __lt__.
This commit is contained in:
parent
0d236eb05a
commit
ec2fe78d47
1 changed files with 28 additions and 11 deletions
|
|
@ -8,6 +8,25 @@ annotated by Fran
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
|
/* Older implementations of heapq used Py_LE for comparisons. Now, it uses
|
||||||
|
Py_LT so it will match min(), sorted(), and bisect(). Unfortunately, some
|
||||||
|
client code (Twisted for example) relied on Py_LE, so this little function
|
||||||
|
restores compatability by trying both.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cmp_lt(PyObject *x, PyObject *y)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
cmp = PyObject_RichCompareBool(x, y, Py_LT);
|
||||||
|
if (cmp == -1 && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||||
|
PyErr_Clear();
|
||||||
|
cmp = PyObject_RichCompareBool(y, x, Py_LE);
|
||||||
|
if (cmp != -1)
|
||||||
|
cmp = 1 - cmp;
|
||||||
|
}
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
|
_siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
|
||||||
{
|
{
|
||||||
|
|
@ -28,7 +47,7 @@ _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
|
||||||
while (pos > startpos){
|
while (pos > startpos){
|
||||||
parentpos = (pos - 1) >> 1;
|
parentpos = (pos - 1) >> 1;
|
||||||
parent = PyList_GET_ITEM(heap, parentpos);
|
parent = PyList_GET_ITEM(heap, parentpos);
|
||||||
cmp = PyObject_RichCompareBool(newitem, parent, Py_LT);
|
cmp = cmp_lt(newitem, parent);
|
||||||
if (cmp == -1) {
|
if (cmp == -1) {
|
||||||
Py_DECREF(newitem);
|
Py_DECREF(newitem);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -68,10 +87,9 @@ _siftup(PyListObject *heap, Py_ssize_t pos)
|
||||||
/* Set childpos to index of smaller child. */
|
/* Set childpos to index of smaller child. */
|
||||||
rightpos = childpos + 1;
|
rightpos = childpos + 1;
|
||||||
if (rightpos < endpos) {
|
if (rightpos < endpos) {
|
||||||
cmp = PyObject_RichCompareBool(
|
cmp = cmp_lt(
|
||||||
PyList_GET_ITEM(heap, childpos),
|
PyList_GET_ITEM(heap, childpos),
|
||||||
PyList_GET_ITEM(heap, rightpos),
|
PyList_GET_ITEM(heap, rightpos));
|
||||||
Py_LT);
|
|
||||||
if (cmp == -1) {
|
if (cmp == -1) {
|
||||||
Py_DECREF(newitem);
|
Py_DECREF(newitem);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -214,7 +232,7 @@ heappushpop(PyObject *self, PyObject *args)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp = PyObject_RichCompareBool(PyList_GET_ITEM(heap, 0), item, Py_LT);
|
cmp = cmp_lt(PyList_GET_ITEM(heap, 0), item);
|
||||||
if (cmp == -1)
|
if (cmp == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
|
|
@ -313,7 +331,7 @@ nlargest(PyObject *self, PyObject *args)
|
||||||
else
|
else
|
||||||
goto sortit;
|
goto sortit;
|
||||||
}
|
}
|
||||||
cmp = PyObject_RichCompareBool(sol, elem, Py_LT);
|
cmp = cmp_lt(sol, elem);
|
||||||
if (cmp == -1) {
|
if (cmp == -1) {
|
||||||
Py_DECREF(elem);
|
Py_DECREF(elem);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -368,7 +386,7 @@ _siftdownmax(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
|
||||||
while (pos > startpos){
|
while (pos > startpos){
|
||||||
parentpos = (pos - 1) >> 1;
|
parentpos = (pos - 1) >> 1;
|
||||||
parent = PyList_GET_ITEM(heap, parentpos);
|
parent = PyList_GET_ITEM(heap, parentpos);
|
||||||
cmp = PyObject_RichCompareBool(parent, newitem, Py_LT);
|
cmp = cmp_lt(parent, newitem);
|
||||||
if (cmp == -1) {
|
if (cmp == -1) {
|
||||||
Py_DECREF(newitem);
|
Py_DECREF(newitem);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -408,10 +426,9 @@ _siftupmax(PyListObject *heap, Py_ssize_t pos)
|
||||||
/* Set childpos to index of smaller child. */
|
/* Set childpos to index of smaller child. */
|
||||||
rightpos = childpos + 1;
|
rightpos = childpos + 1;
|
||||||
if (rightpos < endpos) {
|
if (rightpos < endpos) {
|
||||||
cmp = PyObject_RichCompareBool(
|
cmp = cmp_lt(
|
||||||
PyList_GET_ITEM(heap, rightpos),
|
PyList_GET_ITEM(heap, rightpos),
|
||||||
PyList_GET_ITEM(heap, childpos),
|
PyList_GET_ITEM(heap, childpos));
|
||||||
Py_LT);
|
|
||||||
if (cmp == -1) {
|
if (cmp == -1) {
|
||||||
Py_DECREF(newitem);
|
Py_DECREF(newitem);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -484,7 +501,7 @@ nsmallest(PyObject *self, PyObject *args)
|
||||||
else
|
else
|
||||||
goto sortit;
|
goto sortit;
|
||||||
}
|
}
|
||||||
cmp = PyObject_RichCompareBool(elem, los, Py_LT);
|
cmp = cmp_lt(elem, los);
|
||||||
if (cmp == -1) {
|
if (cmp == -1) {
|
||||||
Py_DECREF(elem);
|
Py_DECREF(elem);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue