1e31aef6aSopenharmony_cifrom functools import wraps 2e31aef6aSopenharmony_ci 3e31aef6aSopenharmony_cifrom . import filters 4e31aef6aSopenharmony_cifrom .asyncsupport import auto_aiter 5e31aef6aSopenharmony_cifrom .asyncsupport import auto_await 6e31aef6aSopenharmony_ci 7e31aef6aSopenharmony_ci 8e31aef6aSopenharmony_ciasync def auto_to_seq(value): 9e31aef6aSopenharmony_ci seq = [] 10e31aef6aSopenharmony_ci if hasattr(value, "__aiter__"): 11e31aef6aSopenharmony_ci async for item in value: 12e31aef6aSopenharmony_ci seq.append(item) 13e31aef6aSopenharmony_ci else: 14e31aef6aSopenharmony_ci for item in value: 15e31aef6aSopenharmony_ci seq.append(item) 16e31aef6aSopenharmony_ci return seq 17e31aef6aSopenharmony_ci 18e31aef6aSopenharmony_ci 19e31aef6aSopenharmony_ciasync def async_select_or_reject(args, kwargs, modfunc, lookup_attr): 20e31aef6aSopenharmony_ci seq, func = filters.prepare_select_or_reject(args, kwargs, modfunc, lookup_attr) 21e31aef6aSopenharmony_ci if seq: 22e31aef6aSopenharmony_ci async for item in auto_aiter(seq): 23e31aef6aSopenharmony_ci if func(item): 24e31aef6aSopenharmony_ci yield item 25e31aef6aSopenharmony_ci 26e31aef6aSopenharmony_ci 27e31aef6aSopenharmony_cidef dualfilter(normal_filter, async_filter): 28e31aef6aSopenharmony_ci wrap_evalctx = False 29e31aef6aSopenharmony_ci if getattr(normal_filter, "environmentfilter", False) is True: 30e31aef6aSopenharmony_ci 31e31aef6aSopenharmony_ci def is_async(args): 32e31aef6aSopenharmony_ci return args[0].is_async 33e31aef6aSopenharmony_ci 34e31aef6aSopenharmony_ci wrap_evalctx = False 35e31aef6aSopenharmony_ci else: 36e31aef6aSopenharmony_ci has_evalctxfilter = getattr(normal_filter, "evalcontextfilter", False) is True 37e31aef6aSopenharmony_ci has_ctxfilter = getattr(normal_filter, "contextfilter", False) is True 38e31aef6aSopenharmony_ci wrap_evalctx = not has_evalctxfilter and not has_ctxfilter 39e31aef6aSopenharmony_ci 40e31aef6aSopenharmony_ci def is_async(args): 41e31aef6aSopenharmony_ci return args[0].environment.is_async 42e31aef6aSopenharmony_ci 43e31aef6aSopenharmony_ci @wraps(normal_filter) 44e31aef6aSopenharmony_ci def wrapper(*args, **kwargs): 45e31aef6aSopenharmony_ci b = is_async(args) 46e31aef6aSopenharmony_ci if wrap_evalctx: 47e31aef6aSopenharmony_ci args = args[1:] 48e31aef6aSopenharmony_ci if b: 49e31aef6aSopenharmony_ci return async_filter(*args, **kwargs) 50e31aef6aSopenharmony_ci return normal_filter(*args, **kwargs) 51e31aef6aSopenharmony_ci 52e31aef6aSopenharmony_ci if wrap_evalctx: 53e31aef6aSopenharmony_ci wrapper.evalcontextfilter = True 54e31aef6aSopenharmony_ci 55e31aef6aSopenharmony_ci wrapper.asyncfiltervariant = True 56e31aef6aSopenharmony_ci 57e31aef6aSopenharmony_ci return wrapper 58e31aef6aSopenharmony_ci 59e31aef6aSopenharmony_ci 60e31aef6aSopenharmony_cidef asyncfiltervariant(original): 61e31aef6aSopenharmony_ci def decorator(f): 62e31aef6aSopenharmony_ci return dualfilter(original, f) 63e31aef6aSopenharmony_ci 64e31aef6aSopenharmony_ci return decorator 65e31aef6aSopenharmony_ci 66e31aef6aSopenharmony_ci 67e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_first) 68e31aef6aSopenharmony_ciasync def do_first(environment, seq): 69e31aef6aSopenharmony_ci try: 70e31aef6aSopenharmony_ci return await auto_aiter(seq).__anext__() 71e31aef6aSopenharmony_ci except StopAsyncIteration: 72e31aef6aSopenharmony_ci return environment.undefined("No first item, sequence was empty.") 73e31aef6aSopenharmony_ci 74e31aef6aSopenharmony_ci 75e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_groupby) 76e31aef6aSopenharmony_ciasync def do_groupby(environment, value, attribute): 77e31aef6aSopenharmony_ci expr = filters.make_attrgetter(environment, attribute) 78e31aef6aSopenharmony_ci return [ 79e31aef6aSopenharmony_ci filters._GroupTuple(key, await auto_to_seq(values)) 80e31aef6aSopenharmony_ci for key, values in filters.groupby( 81e31aef6aSopenharmony_ci sorted(await auto_to_seq(value), key=expr), expr 82e31aef6aSopenharmony_ci ) 83e31aef6aSopenharmony_ci ] 84e31aef6aSopenharmony_ci 85e31aef6aSopenharmony_ci 86e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_join) 87e31aef6aSopenharmony_ciasync def do_join(eval_ctx, value, d=u"", attribute=None): 88e31aef6aSopenharmony_ci return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute) 89e31aef6aSopenharmony_ci 90e31aef6aSopenharmony_ci 91e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_list) 92e31aef6aSopenharmony_ciasync def do_list(value): 93e31aef6aSopenharmony_ci return await auto_to_seq(value) 94e31aef6aSopenharmony_ci 95e31aef6aSopenharmony_ci 96e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_reject) 97e31aef6aSopenharmony_ciasync def do_reject(*args, **kwargs): 98e31aef6aSopenharmony_ci return async_select_or_reject(args, kwargs, lambda x: not x, False) 99e31aef6aSopenharmony_ci 100e31aef6aSopenharmony_ci 101e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_rejectattr) 102e31aef6aSopenharmony_ciasync def do_rejectattr(*args, **kwargs): 103e31aef6aSopenharmony_ci return async_select_or_reject(args, kwargs, lambda x: not x, True) 104e31aef6aSopenharmony_ci 105e31aef6aSopenharmony_ci 106e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_select) 107e31aef6aSopenharmony_ciasync def do_select(*args, **kwargs): 108e31aef6aSopenharmony_ci return async_select_or_reject(args, kwargs, lambda x: x, False) 109e31aef6aSopenharmony_ci 110e31aef6aSopenharmony_ci 111e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_selectattr) 112e31aef6aSopenharmony_ciasync def do_selectattr(*args, **kwargs): 113e31aef6aSopenharmony_ci return async_select_or_reject(args, kwargs, lambda x: x, True) 114e31aef6aSopenharmony_ci 115e31aef6aSopenharmony_ci 116e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_map) 117e31aef6aSopenharmony_ciasync def do_map(*args, **kwargs): 118e31aef6aSopenharmony_ci seq, func = filters.prepare_map(args, kwargs) 119e31aef6aSopenharmony_ci if seq: 120e31aef6aSopenharmony_ci async for item in auto_aiter(seq): 121e31aef6aSopenharmony_ci yield await auto_await(func(item)) 122e31aef6aSopenharmony_ci 123e31aef6aSopenharmony_ci 124e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_sum) 125e31aef6aSopenharmony_ciasync def do_sum(environment, iterable, attribute=None, start=0): 126e31aef6aSopenharmony_ci rv = start 127e31aef6aSopenharmony_ci if attribute is not None: 128e31aef6aSopenharmony_ci func = filters.make_attrgetter(environment, attribute) 129e31aef6aSopenharmony_ci else: 130e31aef6aSopenharmony_ci 131e31aef6aSopenharmony_ci def func(x): 132e31aef6aSopenharmony_ci return x 133e31aef6aSopenharmony_ci 134e31aef6aSopenharmony_ci async for item in auto_aiter(iterable): 135e31aef6aSopenharmony_ci rv += func(item) 136e31aef6aSopenharmony_ci return rv 137e31aef6aSopenharmony_ci 138e31aef6aSopenharmony_ci 139e31aef6aSopenharmony_ci@asyncfiltervariant(filters.do_slice) 140e31aef6aSopenharmony_ciasync def do_slice(value, slices, fill_with=None): 141e31aef6aSopenharmony_ci return filters.do_slice(await auto_to_seq(value), slices, fill_with) 142e31aef6aSopenharmony_ci 143e31aef6aSopenharmony_ci 144e31aef6aSopenharmony_ciASYNC_FILTERS = { 145e31aef6aSopenharmony_ci "first": do_first, 146e31aef6aSopenharmony_ci "groupby": do_groupby, 147e31aef6aSopenharmony_ci "join": do_join, 148e31aef6aSopenharmony_ci "list": do_list, 149e31aef6aSopenharmony_ci # we intentionally do not support do_last because that would be 150e31aef6aSopenharmony_ci # ridiculous 151e31aef6aSopenharmony_ci "reject": do_reject, 152e31aef6aSopenharmony_ci "rejectattr": do_rejectattr, 153e31aef6aSopenharmony_ci "map": do_map, 154e31aef6aSopenharmony_ci "select": do_select, 155e31aef6aSopenharmony_ci "selectattr": do_selectattr, 156e31aef6aSopenharmony_ci "sum": do_sum, 157e31aef6aSopenharmony_ci "slice": do_slice, 158e31aef6aSopenharmony_ci} 159