Skip to content

Commit

Permalink
Added get. Also added cytoolz.cpython for additional C bindings.
Browse files Browse the repository at this point in the history
  • Loading branch information
eriknw committed Apr 5, 2014
1 parent 2f32359 commit 21e0de9
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 9 deletions.
2 changes: 1 addition & 1 deletion cytoolz/__init__.pxd
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .itertoolz cimport (groupby, frequencies, reduceby,
first, second, nth, take, drop, rest, last,
concat, concatv, isdistinct, interpose, unique,
get, concat, concatv, isdistinct, interpose, unique,
isiterable, remove, iterate, accumulate,
count, cons, take_nth)

Expand Down
2 changes: 1 addition & 1 deletion cytoolz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .itertoolz import (groupby, frequencies, reduceby,
first, second, nth, take, drop, rest, last,
concat, concatv, isdistinct, interpose, unique,
get, concat, concatv, isdistinct, interpose, unique,
isiterable, remove, iterate, accumulate,
count, cons, take_nth)

Expand Down
8 changes: 8 additions & 0 deletions cytoolz/cpython.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
""" Additional bindings to Python's C-API.
These differ from Cython's bindings in ``cpython``.
"""
from cpython.ref cimport PyObject

cdef extern from "Python.h":
PyObject* PyObject_GetItem(object o, object key)
2 changes: 1 addition & 1 deletion cytoolz/itertoolz/__init__.pxd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .core cimport (groupby, remove, concat, concatv, frequencies, interpose,
first, second, nth, take, drop, rest, last, unique,
first, second, nth, take, drop, rest, get, last, unique,
reduceby, isiterable, isdistinct, cons, iterate,
accumulate, count, take_nth)
2 changes: 1 addition & 1 deletion cytoolz/itertoolz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .core import (groupby, remove, concat, concatv, frequencies, interpose,
first, second, nth, take, drop, rest, last, unique,
first, second, nth, take, drop, rest, get, last, unique,
reduceby, isiterable, isdistinct, cons, iterate,
accumulate, count, take_nth)
3 changes: 3 additions & 0 deletions cytoolz/itertoolz/core.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ cpdef object last(object seq)
cpdef object rest(object seq)


cpdef object get(object ind, object seq, object default=*)


cpdef inline object cons(object el, object seq)


Expand Down
86 changes: 84 additions & 2 deletions cytoolz/itertoolz/core.pyx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from cpython.dict cimport PyDict_Contains, PyDict_GetItem, PyDict_New, PyDict_SetItem
from cpython.list cimport PyList_New, PyList_Append
from cpython.ref cimport PyObject
from cpython.exc cimport PyErr_Clear, PyErr_GivenExceptionMatches, PyErr_Occurred
from cpython.list cimport PyList_Append, PyList_Check, PyList_New
from cpython.ref cimport PyObject, Py_INCREF
from cpython.sequence cimport PySequence_Check
from cpython.set cimport PySet_Add, PySet_Contains
from cpython.tuple cimport PyTuple_New, PyTuple_SET_ITEM
from itertools import chain, islice

from cytoolz.cpython cimport PyObject_GetItem


concatv = chain
concat = chain.from_iterable
Expand Down Expand Up @@ -329,6 +333,84 @@ cpdef object rest(object seq):
return seq


no_default = '__no__default__'


cdef tuple _get_exceptions = (IndexError, KeyError, TypeError)


cpdef object get(object ind, object seq, object default=no_default):
""" Get element in a sequence or dict
Provides standard indexing
>>> get(1, 'ABC') # Same as 'ABC'[1]
'B'
Pass a list to get multiple values
>>> get([1, 2], 'ABC') # ('ABC'[1], 'ABC'[2])
('B', 'C')
Works on any value that supports indexing/getitem
For example here we see that it works with dictionaries
>>> phonebook = {'Alice': '555-1234',
... 'Bob': '555-5678',
... 'Charlie':'555-9999'}
>>> get('Alice', phonebook)
'555-1234'
>>> get(['Alice', 'Bob'], phonebook)
('555-1234', '555-5678')
Provide a default for missing values
>>> get(['Alice', 'Dennis'], phonebook, None)
('555-1234', None)
See Also:
pluck
"""
cdef int i
cdef object val
cdef tuple result
cdef PyObject *obj
if PyList_Check(ind):
result = PyTuple_New(len(ind))
# List of indices, no default
if default is no_default:
for i, val in enumerate(ind):
val = seq[val]
Py_INCREF(val)
PyTuple_SET_ITEM(result, i, val)
return result

# List of indices with default
for i, val in enumerate(ind):
obj = PyObject_GetItem(seq, val)
if obj is NULL:
PyErr_Clear()
Py_INCREF(default)
PyTuple_SET_ITEM(result, i, default)
else:
val = <object>obj
Py_INCREF(val)
PyTuple_SET_ITEM(result, i, val)
return result

obj = PyObject_GetItem(seq, ind)
if obj is NULL:
val = <object>PyErr_Occurred()
if default is no_default:
raise val
if PyErr_GivenExceptionMatches(val, _get_exceptions):
PyErr_Clear()
return default
raise val
return <object>obj


cpdef inline object cons(object el, object seq):
""" Add el to beginning of (possibly infinite) sequence seq.
Expand Down
4 changes: 1 addition & 3 deletions cytoolz/itertoolz/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
concat, concatv, unique,
identity, isiterable,
isdistinct, first, second,
nth, take, drop, interpose,
nth, take, drop, interpose, get,
rest, last, cons, frequencies,
reduceby, iterate, accumulate,
count,
Expand Down Expand Up @@ -134,7 +134,6 @@ def test_take_nth():
assert list(take_nth(2, 'ABCDE')) == list('ACE')


'''
def test_get():
assert get(1, 'ABCDE') == 'B'
assert list(get([1, 3], 'ABCDE')) == list('BD')
Expand All @@ -148,7 +147,6 @@ def test_get():
assert raises(IndexError, lambda: get(10, 'ABC'))
assert raises(KeyError, lambda: get(10, {'a': 1}))
assert raises(TypeError, lambda: get({}, [1, 2, 3]))
'''


'''
Expand Down

0 comments on commit 21e0de9

Please sign in to comment.