from functools import wraps from . import filters from .asyncsupport import auto_aiter from .asyncsupport import auto_await async def auto_to_seq(value): seq = [] if hasattr(value, "__aiter__"): async for item in value: seq.append(item) else: for item in value: seq.append(item) return seq async def async_select_or_reject(args, kwargs, modfunc, lookup_attr): seq, func = filters.prepare_select_or_reject(args, kwargs, modfunc, lookup_attr) if seq: async for item in auto_aiter(seq): if func(item): yield item def dualfilter(normal_filter, async_filter): wrap_evalctx = False if getattr(normal_filter, "environmentfilter", False) is True: def is_async(args): return args[0].is_async wrap_evalctx = False else: has_evalctxfilter = getattr(normal_filter, "evalcontextfilter", False) is True has_ctxfilter = getattr(normal_filter, "contextfilter", False) is True wrap_evalctx = not has_evalctxfilter and not has_ctxfilter def is_async(args): return args[0].environment.is_async @wraps(normal_filter) def wrapper(*args, **kwargs): b = is_async(args) if wrap_evalctx: args = args[1:] if b: return async_filter(*args, **kwargs) return normal_filter(*args, **kwargs) if wrap_evalctx: wrapper.evalcontextfilter = True wrapper.asyncfiltervariant = True return wrapper def asyncfiltervariant(original): def decorator(f): return dualfilter(original, f) return decorator @asyncfiltervariant(filters.do_first) async def do_first(environment, seq): try: return await auto_aiter(seq).__anext__() except StopAsyncIteration: return environment.undefined("No first item, sequence was empty.") @asyncfiltervariant(filters.do_groupby) async def do_groupby(environment, value, attribute): expr = filters.make_attrgetter(environment, attribute) return [ filters._GroupTuple(key, await auto_to_seq(values)) for key, values in filters.groupby( sorted(await auto_to_seq(value), key=expr), expr ) ] @asyncfiltervariant(filters.do_join) async def do_join(eval_ctx, value, d=u"", attribute=None): return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute) @asyncfiltervariant(filters.do_list) async def do_list(value): return await auto_to_seq(value) @asyncfiltervariant(filters.do_reject) async def do_reject(*args, **kwargs): return async_select_or_reject(args, kwargs, lambda x: not x, False) @asyncfiltervariant(filters.do_rejectattr) async def do_rejectattr(*args, **kwargs): return async_select_or_reject(args, kwargs, lambda x: not x, True) @asyncfiltervariant(filters.do_select) async def do_select(*args, **kwargs): return async_select_or_reject(args, kwargs, lambda x: x, False) @asyncfiltervariant(filters.do_selectattr) async def do_selectattr(*args, **kwargs): return async_select_or_reject(args, kwargs, lambda x: x, True) @asyncfiltervariant(filters.do_map) async def do_map(*args, **kwargs): seq, func = filters.prepare_map(args, kwargs) if seq: async for item in auto_aiter(seq): yield await auto_await(func(item)) @asyncfiltervariant(filters.do_sum) async def do_sum(environment, iterable, attribute=None, start=0): rv = start if attribute is not None: func = filters.make_attrgetter(environment, attribute) else: def func(x): return x async for item in auto_aiter(iterable): rv += func(item) return rv @asyncfiltervariant(filters.do_slice) async def do_slice(value, slices, fill_with=None): return filters.do_slice(await auto_to_seq(value), slices, fill_with) ASYNC_FILTERS = { "first": do_first, "groupby": do_groupby, "join": do_join, "list": do_list, # we intentionally do not support do_last because that would be # ridiculous "reject": do_reject, "rejectattr": do_rejectattr, "map": do_map, "select": do_select, "selectattr": do_selectattr, "sum": do_sum, "slice": do_slice, }
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
__init__.py | File | 1.51 KB | 0644 |
|
_compat.py | File | 3.12 KB | 0644 |
|
_identifier.py | File | 1.73 KB | 0644 |
|
asyncfilters.py | File | 4.15 KB | 0644 |
|
asyncsupport.py | File | 7.04 KB | 0644 |
|
bccache.py | File | 11.85 KB | 0644 |
|
compiler.py | File | 64.73 KB | 0644 |
|
constants.py | File | 1.42 KB | 0644 |
|
debug.py | File | 8.33 KB | 0644 |
|
defaults.py | File | 1.1 KB | 0644 |
|
environment.py | File | 49.44 KB | 0644 |
|
exceptions.py | File | 5.3 KB | 0644 |
|
ext.py | File | 25.82 KB | 0644 |
|
filters.py | File | 40.44 KB | 0644 |
|
idtracking.py | File | 9 KB | 0644 |
|
lexer.py | File | 29.62 KB | 0644 |
|
loaders.py | File | 17.25 KB | 0644 |
|
meta.py | File | 4.03 KB | 0644 |
|
nativetypes.py | File | 2.69 KB | 0644 |
|
nodes.py | File | 30.37 KB | 0644 |
|
optimizer.py | File | 1.42 KB | 0644 |
|
parser.py | File | 34.82 KB | 0644 |
|
runtime.py | File | 29.9 KB | 0644 |
|
sandbox.py | File | 16.73 KB | 0644 |
|
tests.py | File | 4.69 KB | 0644 |
|
utils.py | File | 21.99 KB | 0644 |
|
visitor.py | File | 3.16 KB | 0644 |
|