Source code for py2store.utils.sliceable
"""
utils to add sliceable functionality to stores
"""
from itertools import islice
from collections.abc import Mapping
[docs]class iSliceStore(Mapping):
"""
Wraps a store to make a reader that acts as if the store was a list (with integer keys, and that can be sliced).
I say "list", but it should be noted that the behavior is more that of range, that outputs an element of the list
when keying with an integer, but returns an iterable object (a range) if sliced.
Here, a map object is returned when the sliceable store is sliced.
>>> s = {'foo': 'bar', 'hello': 'world', 'alice': 'bob'}
>>> sliceable_s = iSliceStore(s)
>>> sliceable_s[1]
'world'
>>> list(sliceable_s[0:2])
['bar', 'world']
>>> list(sliceable_s[-2:])
['world', 'bob']
>>> list(sliceable_s[:-1])
['bar', 'world']
"""
def __init__(self, store):
self.store = store
def _get_key(self, k):
return next(islice(self.store.keys(), k, k + 1))
def _get_keys(self, k):
start, stop, step = k.start, k.stop, k.step
assert (step is None) or (step > 0), "step of slice can't be negative"
negative_start = start is not None and start < 0
negative_stop = stop is not None and stop < 0
if negative_start or negative_stop:
n = self.__len__()
if negative_start:
start = n + start
if negative_stop:
stop = n + stop
return islice(self.store.keys(), start, stop, step)
def __getitem__(self, k):
if not isinstance(k, slice):
_id = next(islice(self.store.keys(), k, k + 1))
return self.store[self._get_key(k)]
else:
return map(self.store.__getitem__, self._get_keys(k))
def __iter__(self):
return self.store.__iter__()
def __len__(self):
return self.store.__len__()