|
| 1 | +from functools import partial |
| 2 | +from itertools import product |
| 3 | +from operator import eq |
| 4 | + |
| 5 | + |
| 6 | +class StreamMapper(object): |
| 7 | + """The stream mapper can be used to simplify the process of creating |
| 8 | + stream objects from data. |
| 9 | +
|
| 10 | + :param cmp: This callable is used to compare each mapping's key |
| 11 | + with a value. |
| 12 | + """ |
| 13 | + def __init__(self, cmp=eq): |
| 14 | + self._map = [] |
| 15 | + self._cmp = cmp |
| 16 | + |
| 17 | + def map(self, key, func, *args, **kwargs): |
| 18 | + """Creates a key-function mapping. |
| 19 | +
|
| 20 | + The return value from the function should be either |
| 21 | + - A tuple containing a name and stream |
| 22 | + - A iterator of tuples containing a name and stream |
| 23 | +
|
| 24 | + Any extra arguments will be passed to the function. |
| 25 | + """ |
| 26 | + self._map.append((key, partial(func, *args, **kwargs))) |
| 27 | + |
| 28 | + def _cmp_filter(self, args): |
| 29 | + value, (key, func) = args |
| 30 | + return self._cmp(key, value) |
| 31 | + |
| 32 | + def _mapped_func(self, args): |
| 33 | + value, (key, func) = args |
| 34 | + return func(value) |
| 35 | + |
| 36 | + def __call__(self, values): |
| 37 | + """Runs through each value and transform it with a mapped function.""" |
| 38 | + values = product(values, self._map) |
| 39 | + for value in map(self._mapped_func, filter(self._cmp_filter, values)): |
| 40 | + if isinstance(value, tuple) and len(value) == 2: |
| 41 | + yield value |
| 42 | + else: |
| 43 | + try: |
| 44 | + # TODO: Replace with "yield from" when dropping Python 2. |
| 45 | + for __ in value: |
| 46 | + yield __ |
| 47 | + except TypeError: |
| 48 | + # Non-iterable returned |
| 49 | + continue |
0 commit comments