Commit 5c45b258 authored by Stefan Behnel's avatar Stefan Behnel

implement builtin next() to make it available in Py2

parent 2e67e464
......@@ -39,6 +39,8 @@ builtin_function_table = [
#('map', "", "", ""),
#('max', "", "", ""),
#('min', "", "", ""),
('next', "O", "O", "__Pyx_PyIter_Next"), # not available in Py2 => implemented here
('next', "OO", "O", "__Pyx_PyIter_Next2"), # not available in Py2 => implemented here
#('oct', "", "", ""),
# Not worth doing open, when second argument would become mandatory
#('open', "ss", "O", "PyFile_FromString"),
......@@ -158,6 +160,40 @@ proto = """
#define __Pyx_PyNumber_Power2(a, b) PyNumber_Power(a, b, Py_None)
""")
iter_next_utility_code = UtilityCode(
proto = """
#define __Pyx_PyIter_Next(obj) __Pyx_PyIter_Next2(obj, NULL);
static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject *, PyObject *); /*proto*/
""",
# copied from Py3's builtin_next()
impl = '''
static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject* defval) {
PyObject* next;
if (unlikely(!PyIter_Check(iterator))) {
PyErr_Format(PyExc_TypeError,
"%.200s object is not an iterator", iterator->ob_type->tp_name);
return NULL;
}
next = (*iterator->ob_type->tp_iternext)(iterator);
if (likely(next)) {
return next;
} else if (defval) {
if (PyErr_Occurred()) {
if(!PyErr_ExceptionMatches(PyExc_StopIteration))
return NULL;
PyErr_Clear();
}
Py_INCREF(defval);
return defval;
} else if (PyErr_Occurred()) {
return NULL;
} else {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
}
''')
getattr3_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
......@@ -390,6 +426,7 @@ builtin_utility_code = {
'exec' : pyexec_utility_code,
'getattr3' : getattr3_utility_code,
'pow' : pow2_utility_code,
'next' : iter_next_utility_code,
'intern' : intern_utility_code,
'set' : py23_set_utility_code,
'frozenset' : py23_set_utility_code,
......
import sys
IS_PY3 = sys.version_info[0] >= 3
__doc__ = """
>>> it = iter([1,2,3])
>>> if not IS_PY3:
... next = type(it).next
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
Traceback (most recent call last):
StopIteration
>>> next(it)
Traceback (most recent call last):
StopIteration
>>> if IS_PY3: next(it, 123)
... else: print(123)
123
"""
def test_single_next(it):
"""
>>> it = iter([1,2,3])
>>> test_single_next(it)
1
>>> test_single_next(it)
2
>>> test_single_next(it)
3
>>> test_single_next(it)
Traceback (most recent call last):
StopIteration
>>> test_single_next(it)
Traceback (most recent call last):
StopIteration
"""
return next(it)
def test_default_next(it, default):
"""
>>> it = iter([1,2,3])
>>> test_default_next(it, 99)
1
>>> test_default_next(it, 99)
2
>>> test_default_next(it, 99)
3
>>> test_default_next(it, 99)
99
>>> test_default_next(it, 99)
99
"""
return next(it, default)
def test_next_not_iterable(it):
"""
>>> test_next_not_iterable(123)
Traceback (most recent call last):
TypeError: int object is not an iterator
"""
return next(it)
def test_next_override(it):
"""
>>> it = iter([1,2,3])
>>> test_next_override(it)
1
>>> test_next_override(it)
1
>>> test_next_override(it)
1
>>> test_next_override(it)
1
"""
def next(it):
return 1
return next(it)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment