diff --git a/.gitignore b/.gitignore index 9a220c6..1f543a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.c +*.html *.pyc *.swp *.so diff --git a/AUTHORS.md b/AUTHORS.md index 7a5c308..04bd230 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -2,4 +2,6 @@ Erik Welch [@eriknw](https://github.com/eri [Matthew Rocklin](http://matthewrocklin.com) [@mrocklin](http://github.com/mrocklin/) +Lars Buitinck [@larsmans](http://github.com/larsmans) + [Thouis (Ray) Jones](http://people.seas.harvard.edu/~thouis) [@thouis](https://github.com/thouis/) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..69a668e --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +PYTHON ?= python + +inplace: + $(PYTHON) setup.py build_ext --inplace + +test: inplace + nosetests -s --with-doctest cytoolz/ diff --git a/cytoolz/dicttoolz.pyx b/cytoolz/dicttoolz.pyx index a807fe7..7c69e93 100644 --- a/cytoolz/dicttoolz.pyx +++ b/cytoolz/dicttoolz.pyx @@ -1,6 +1,7 @@ #cython: embedsignature=True from cpython.dict cimport (PyDict_Check, PyDict_GetItem, PyDict_Merge, - PyDict_New, PyDict_SetItem, PyDict_Update) + PyDict_New, PyDict_Next, PyDict_SetItem, + PyDict_Update) from cpython.exc cimport PyErr_Clear, PyErr_GivenExceptionMatches, PyErr_Occurred from cpython.list cimport PyList_Append, PyList_New from cpython.ref cimport PyObject @@ -94,10 +95,19 @@ cpdef dict valmap(object func, dict d): See Also: keymap """ - cdef dict rv + cdef: + dict rv + Py_ssize_t pos + PyObject *k + PyObject *v + + if d is None: + raise TypeError("expected dict, got None") + rv = PyDict_New() - for k, v in d.iteritems(): - PyDict_SetItem(rv, k, func(v)) + pos = 0 + while PyDict_Next(d, &pos, &k, &v): + PyDict_SetItem(rv, k, func(v)) return rv @@ -112,10 +122,19 @@ cpdef dict keymap(object func, dict d): See Also: valmap """ - cdef dict rv + cdef: + dict rv + Py_ssize_t pos + PyObject *k + PyObject *v + + if d is None: + raise TypeError("expected dict, got None") + rv = PyDict_New() - for k, v in d.iteritems(): - PyDict_SetItem(rv, func(k), v) + pos = 0 + while PyDict_Next(d, &pos, &k, &v): + PyDict_SetItem(rv, func(k), v) return rv @@ -132,11 +151,20 @@ cpdef dict valfilter(object predicate, dict d): keyfilter valmap """ - cdef dict rv + cdef: + dict rv + Py_ssize_t pos + PyObject *k + PyObject *v + + if d is None: + raise TypeError("expected dict, got None") + rv = PyDict_New() - for k, v in d.iteritems(): - if predicate(v): - PyDict_SetItem(rv, k, v) + pos = 0 + while PyDict_Next(d, &pos, &k, &v): + if predicate(v): + PyDict_SetItem(rv, k, v) return rv @@ -153,11 +181,20 @@ cpdef dict keyfilter(object predicate, dict d): valfilter keymap """ - cdef dict rv + cdef: + dict rv + Py_ssize_t pos + PyObject *k + PyObject *v + + if d is None: + raise TypeError("expected dict, got None") + rv = PyDict_New() - for k, v in d.iteritems(): - if predicate(k): - PyDict_SetItem(rv, k, v) + pos = 0 + while PyDict_Next(d, &pos, &k, &v): + if predicate(k): + PyDict_SetItem(rv, k, v) return rv diff --git a/cytoolz/tests/test_none_safe.py b/cytoolz/tests/test_none_safe.py index 4edfeb1..b65175d 100644 --- a/cytoolz/tests/test_none_safe.py +++ b/cytoolz/tests/test_none_safe.py @@ -53,15 +53,13 @@ def test_dicttoolz(): tested.append('get_in') assert raises(TypeError, lambda: keyfilter(None, {1: 2})) - assert raises((TypeError, AttributeError), - lambda: keyfilter(identity, None)) + assert raises(TypeError, lambda: keyfilter(identity, None)) tested.append('keyfilter') # XXX assert (raises(TypeError, lambda: keymap(None, {1: 2})) or keymap(None, {1: 2}) == {(1,): 2}) - assert raises((TypeError, AttributeError), - lambda: keymap(identity, None)) + assert raises(TypeError, lambda: keymap(identity, None)) tested.append('keymap') assert raises(TypeError, lambda: merge(None)) @@ -81,15 +79,13 @@ def test_dicttoolz(): tested.append('update_in') assert raises(TypeError, lambda: valfilter(None, {1: 2})) - assert raises((TypeError, AttributeError), - lambda: valfilter(identity, None)) + assert raises(TypeError, lambda: valfilter(identity, None)) tested.append('valfilter') # XXX assert (raises(TypeError, lambda: valmap(None, {1: 2})) or valmap(None, {1: 2}) == {1: (2,)}) - assert raises((TypeError, AttributeError), - lambda: valmap(identity, None)) + assert raises(TypeError, lambda: valmap(identity, None)) tested.append('valmap') s1 = set(tested)