[pypy-svn] r74571 - in pypy/trunk/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Wed May 19 12:07:16 CEST 2010
Author: afa
Date: Wed May 19 12:07:12 2010
New Revision: 74571
Modified:
pypy/trunk/pypy/module/cpyext/dictobject.py
pypy/trunk/pypy/module/cpyext/test/test_dictobject.py
Log:
Implement (very inefficiently) PyDict_Next
Modified: pypy/trunk/pypy/module/cpyext/dictobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/dictobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/dictobject.py Wed May 19 12:07:12 2010
@@ -3,6 +3,7 @@
cpython_api, CANNOT_FAIL, build_type_checkers, Py_ssize_t,
Py_ssize_tP, CONST_STRING)
from pypy.module.cpyext.pyobject import PyObject, PyObjectP, borrow_from
+from pypy.module.cpyext.pyobject import RefcountState
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
@@ -104,7 +105,7 @@
return space.call_method(w_obj, "items")
@cpython_api([PyObject, Py_ssize_tP, PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
-def PyDict_Next(space, w_obj, ppos, pkey, pvalue):
+def PyDict_Next(space, w_dict, ppos, pkey, pvalue):
"""Iterate over all key-value pairs in the dictionary p. The
Py_ssize_t referred to by ppos must be initialized to 0
prior to the first call to this function to start the iteration; the
@@ -145,8 +146,30 @@
}
Py_DECREF(o);
}"""
- if w_obj is None:
+ if w_dict is None:
return 0
- raise NotImplementedError
+
+ # Note: this is not efficient. Storing an iterator would probably
+ # work, but we can't work out how to not leak it if iteration does
+ # not complete.
+
+ try:
+ w_iter = space.call_method(w_dict, "iteritems")
+ pos = ppos[0]
+ while pos:
+ space.call_method(w_iter, "next")
+ pos -= 1
+
+ w_item = space.call_method(w_iter, "next")
+ w_key, w_value = space.fixedview(w_item, 2)
+ state = space.fromcache(RefcountState)
+ pkey[0] = state.make_borrowed(w_dict, w_key)
+ pvalue[0] = state.make_borrowed(w_dict, w_value)
+ ppos[0] += 1
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ return 0
+ return 1
Modified: pypy/trunk/pypy/module/cpyext/test/test_dictobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_dictobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_dictobject.py Wed May 19 12:07:12 2010
@@ -1,5 +1,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.api import Py_ssize_tP, PyObjectP
+from pypy.module.cpyext.pyobject import make_ref, from_ref
class TestDictObject(BaseApiTest):
def test_dict(self, space, api):
@@ -71,3 +73,28 @@
api.PyDict_Update(w_d, w_d2)
assert space.unwrap(w_d) == dict(a='b', c='d', e='f')
+
+ def test_iter(self, space, api):
+ w_dict = space.sys.getdict()
+ py_dict = make_ref(space, w_dict)
+
+ ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
+ ppos[0] = 0
+ pkey = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+ pvalue = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+
+ try:
+ w_copy = space.newdict()
+ while api.PyDict_Next(w_dict, ppos, pkey, pvalue):
+ w_key = from_ref(space, pkey[0])
+ w_value = from_ref(space, pvalue[0])
+ space.setitem(w_copy, w_key, w_value)
+ finally:
+ lltype.free(ppos, flavor='raw')
+ lltype.free(pkey, flavor='raw')
+ lltype.free(pvalue, flavor='raw')
+
+ api.Py_DecRef(py_dict) # release borrowed references
+
+ assert space.eq_w(space.len(w_copy), space.len(w_dict))
+ assert space.eq_w(w_copy, w_dict)
More information about the Pypy-commit
mailing list