[Python-checkins] r58304 - in python/trunk: Misc/NEWS Objects/enumobject.c
raymond.hettinger
python-checkins at python.org
Wed Oct 3 23:18:11 CEST 2007
Author: raymond.hettinger
Date: Wed Oct 3 23:18:11 2007
New Revision: 58304
Modified:
python/trunk/Misc/NEWS
python/trunk/Objects/enumobject.c
Log:
enumerate() is no longer bounded to using sequences shorter than LONG_MAX. The possibility of overflow was sending some newsgroup posters into a tizzy.
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Wed Oct 3 23:18:11 2007
@@ -12,6 +12,10 @@
Core and builtins
-----------------
+- The enumerate() builtin function is no longer bounded to sequences smaller
+ than LONG_MAX. Formerly, it raised an OverflowError. Now, automatically
+ shifts from ints to longs.
+
- Issue #1686386: Tuple's tp_repr did not take into account the possibility of
having a self-referential tuple, which is possible from C code. Nor did
object's tp_str consider that a type's tp_str could do something that could
Modified: python/trunk/Objects/enumobject.c
==============================================================================
--- python/trunk/Objects/enumobject.c (original)
+++ python/trunk/Objects/enumobject.c Wed Oct 3 23:18:11 2007
@@ -7,6 +7,7 @@
long en_index; /* current index of enumeration */
PyObject* en_sit; /* secondary iterator of enumeration */
PyObject* en_result; /* result tuple */
+ PyObject* en_longindex; /* index for sequences >= LONG_MAX */
} enumobject;
static PyObject *
@@ -25,6 +26,7 @@
return NULL;
en->en_index = 0;
en->en_sit = PyObject_GetIter(seq);
+ en->en_longindex = NULL;
if (en->en_sit == NULL) {
Py_DECREF(en);
return NULL;
@@ -43,6 +45,7 @@
PyObject_GC_UnTrack(en);
Py_XDECREF(en->en_sit);
Py_XDECREF(en->en_result);
+ Py_XDECREF(en->en_longindex);
Py_Type(en)->tp_free(en);
}
@@ -51,10 +54,53 @@
{
Py_VISIT(en->en_sit);
Py_VISIT(en->en_result);
+ Py_VISIT(en->en_longindex);
return 0;
}
static PyObject *
+enum_next_long(enumobject *en, PyObject* next_item)
+{
+ static PyObject *one = NULL;
+ PyObject *result = en->en_result;
+ PyObject *next_index;
+ PyObject *stepped_up;
+
+ if (en->en_longindex == NULL) {
+ en->en_longindex = PyInt_FromLong(LONG_MAX);
+ if (en->en_longindex == NULL)
+ return NULL;
+ }
+ if (one == NULL) {
+ one = PyInt_FromLong(1);
+ if (one == NULL)
+ return NULL;
+ }
+ next_index = en->en_longindex;
+ assert(next_index != NULL);
+ stepped_up = PyNumber_Add(next_index, one);
+ if (stepped_up == NULL)
+ return NULL;
+ en->en_longindex = stepped_up;
+
+ if (result->ob_refcnt == 1) {
+ Py_INCREF(result);
+ Py_DECREF(PyTuple_GET_ITEM(result, 0));
+ Py_DECREF(PyTuple_GET_ITEM(result, 1));
+ } else {
+ result = PyTuple_New(2);
+ if (result == NULL) {
+ Py_DECREF(next_index);
+ Py_DECREF(next_item);
+ return NULL;
+ }
+ }
+ PyTuple_SET_ITEM(result, 0, next_index);
+ PyTuple_SET_ITEM(result, 1, next_item);
+ return result;
+}
+
+static PyObject *
enum_next(enumobject *en)
{
PyObject *next_index;
@@ -62,16 +108,13 @@
PyObject *result = en->en_result;
PyObject *it = en->en_sit;
- if (en->en_index == LONG_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "enumerate() is limited to LONG_MAX items");
- return NULL;
- }
-
next_item = (*Py_Type(it)->tp_iternext)(it);
if (next_item == NULL)
return NULL;
+ if (en->en_index == LONG_MAX)
+ return enum_next_long(en, next_item);
+
next_index = PyInt_FromLong(en->en_index);
if (next_index == NULL) {
Py_DECREF(next_item);
More information about the Python-checkins
mailing list