def test_pipes(): assert c.list_comp(c.inline_expr("{0} ** 2").pass_args(c.this())).pipe( c.call_func(sum, c.this())).pipe( c.call_func( lambda x, a: x + a, c.this(), c.naive({ "abc": 10 }).item(c.input_arg("key_name")), )).pipe([c.this(), c.this()]).execute([1, 2, 3], key_name="abc", debug=False) == [ 24, 24, ] assert c.item(0).pipe( datetime.strptime, "%Y-%m-%d", ).pipe(c.call_func(lambda dt: dt.date(), c.this())).execute([ "2019-01-01", ], debug=False) == date(2019, 1, 1) assert c.item(0).pipe( datetime.strptime, "%Y-%m-%d", ).pipe(c.this().call_method("date")).execute([ "2019-01-01", ], debug=False) == date(2019, 1, 1) with pytest.raises(c.ConversionException): c.naive(True).pipe(c.item("key1", _predefined_input={"key1": 777}))
def test_naive_conversion_attr(): TestType = namedtuple("TestType", ["field_a", "field_b"]) obj = TestType(1, 2) assert c.naive(obj).attr("field_b").gen_converter()(100) == 2 assert c.naive(obj).attr("field_b", "real").gen_converter()(100) == 2 with pytest.raises(AttributeError): c.naive(obj).attr("field_c").gen_converter()(100) assert c.attr(c.naive(["field_a"]).item(0)).gen_converter()(obj) == 1
def test_naive_conversion_call(): assert c.naive("TEST").attr("lower").call().gen_converter()(100) == "test" assert c.call_func(str.lower, c.this()).gen_converter()("TEST") == "test" assert (c.naive("TE ST").attr("replace").call( " ", "").gen_converter()(100) == "TEST") f = MagicMock(return_value=1) c.naive(f).call(1, 2, test1=True, test2="test3").gen_converter()(100) f.assert_called_with(1, 2, test1=True, test2="test3") c.call(10, test="abc").gen_converter()(f) f.assert_called_with(10, test="abc")
def test_naive_conversion_apply(): f = MagicMock(return_value=1) c.naive(f).apply((1, 2), dict(test1=True, test2="test3")).gen_converter()(100) f.assert_called_with(1, 2, test1=True, test2="test3") c.apply((10, ), dict(test="abc")).gen_converter()(f) f.assert_called_with(10, test="abc") c.apply((), {}).execute(f) f.assert_called_with() c.apply((1, ), {}).execute(f) f.assert_called_with(1)
def test_naive_conversion_or_and(): assert c.naive(False).or_(c.naive(False)).gen_converter()(100) is False assert (c.naive(False) | c.naive(False)).gen_converter()(100) is False assert c.naive(0).or_(c.naive(10)).gen_converter()(100) == 10 assert c.naive(10).and_(c.naive(0)).gen_converter()(100) == 0 assert (c.naive(10) & c.naive(0)).gen_converter()(100) == 0 assert (c.this.and_(1).and_(2).execute(1) == c.and_(c.this, 1, 2).execute(1) == 2) assert (c.this.or_(1).or_(2).execute(1) == c.or_(c.this, 1, 2).execute(1) == 1) assert (c.this.and_(1).and_(2).or_(3).execute(1) == c.and_( c.this, 1, 2).or_(3).execute(1) == 2)
def _gen_code_and_update_ctx(self, code_input, ctx): suffix = self.gen_name("_", ctx, ("take_while", self, code_input)) converter_name = f"drop_while{suffix}" var_chain = f"chain{suffix}" var_it = f"it{suffix}" var_item = f"item{suffix}" ( code_args, positional_args_as_conversions, keyword_args_as_conversions, namespace_ctx, ) = self.get_args_def_info(ctx) with namespace_ctx: condition_code = self.condition.gen_code_and_update_ctx( var_item, ctx) code = Code() code.add_line( f"def {converter_name}({var_it},{var_chain}{code_args}):", 1) code.add_line(f"{var_it} = iter({var_it})", 0) code.add_line(f"for {var_item} in {var_it}:", 1) code.add_line(f"if not ({condition_code}):", 1) code.add_line("break", -2) code.add_line("else:", 1) code.add_line("return ()", -1) code.add_line(f"return {var_chain}(({var_item},), {var_it})", -1) self._code_to_converter(converter_name, code.to_string(0), ctx) return (c.escaped_string(converter_name).call( c.this, c.naive(chain), *positional_args_as_conversions, **keyword_args_as_conversions, ).gen_code_and_update_ctx(code_input, ctx))
def test_naive_conversion(): d = {1: 2} assert c.naive(d).gen_converter()(1) == d assert c.naive("abc").gen_converter()(1) == "abc" assert c.naive(1).gen_converter()(10) == 1 assert c.naive(True).gen_converter()(10) is True assert c.naive(False).gen_converter()(10) is False assert c.naive(None).gen_converter()(10) is None assert c.naive("1").as_type(int).gen_converter()(10) == 1 assert c.naive(1).gen_converter(method=True)(None, 10) == 1
def test_or_and_not(): assert c.or_(None, 0).gen_converter()(100) == 0 assert c.and_(None, 0).gen_converter()(100) is None assert c.not_(True).gen_converter()(100) is False assert (~c.this).gen_converter()(True) is False assert c.naive(None).not_().execute(100) is True with pytest.raises(ValueError): c.or_()
def test_base_reducer(): assert c.aggregate(( c.reduce(lambda a, b: a + b, c.this, initial=0), c.reduce(c.naive(lambda a, b: a + b), c.this, initial=int), c.reduce( c.inline_expr("{0} + {1}"), c.this, initial=c.inline_expr("int()"), default=0, ), c.reduce( c.inline_expr("{0} + {1}"), c.this, initial=c(int), default=0, ), c.reduce( c.inline_expr("{0} + {1}"), c.this, initial=int, default=0, ), )).filter(c.this > 5).gen_converter(debug=False)([1, 2, 3]) == [ 6, 6, 6, 6, 6, ] with pytest.raises(ValueError): c.aggregate(c.ReduceFuncs.Sum(c.reduce( c.ReduceFuncs.Count))).gen_converter() with pytest.raises(ValueError): c.aggregate(c.ReduceFuncs.Sum(c.ReduceFuncs.Count() + 1)).gen_converter() with pytest.raises(ValueError): c.aggregate((c.ReduceFuncs.Count() + 2).pipe(c.ReduceFuncs.Sum(c.this) + 1)).gen_converter() conv = c.aggregate(c.ReduceFuncs.DictArray( c.item(0), c.item(1))).gen_converter(debug=False) data = [ ("a", 1), ("a", 2), ("b", 3), ] result = {"a": [1, 2], "b": [3]} assert conv(data) == result assert conv([]) is None conv2 = c.aggregate({ "key": c.ReduceFuncs.DictArray(c.item(0), c.item(1)) }).gen_converter(debug=False) assert conv2([]) == {"key": None} assert conv2(data) == {"key": result}
def test_pipes(): assert c.list_comp(c.inline_expr("{0} ** 2").pass_args(c.this)).pipe( c.call_func(sum, c.this)).pipe( c.call_func( lambda x, a: x + a, c.this, c.naive({ "abc": 10 }).item(c.input_arg("key_name")), )).pipe([c.this, c.this]).execute([1, 2, 3], key_name="abc", debug=False) == [ 24, 24, ] assert c.item(0).pipe(datetime.strptime, "%Y-%m-%d").pipe( c.call_func(lambda dt: dt.date(), c.this)).execute(["2019-01-01"], debug=False) == date(2019, 1, 1) assert c.item(0).pipe(datetime.strptime, "%Y-%m-%d").pipe( c.this.call_method("date")).execute(["2019-01-01"], debug=False) == date(2019, 1, 1) conv = c.dict_comp( c.item("name"), c.item("transactions").pipe( c.list_comp({ "id": c.item(0).as_type(str), "amount": c.item(1).pipe(c.if_(c.this, c.this.as_type(Decimal), None)), })), ).gen_converter(debug=False) assert conv([{ "name": "test", "transactions": [(0, 0), (1, 10)] }]) == { "test": [ { "id": "0", "amount": None }, { "id": "1", "amount": Decimal("10") }, ] } assert c.this.pipe(lambda it: it).filter( c.this).sort().as_type(list).execute((2, 1, 0)) == [1, 2]
def test_naive_conversion(): d = {1: 2} prev_max_counter = c.BaseConversion.max_counter c.BaseConversion.max_counter = 3 try: assert c.naive(d).gen_converter()(1) == d assert c.naive("abc").gen_converter()(1) == "abc" assert c.naive(1).gen_converter()(10) == 1 assert c.naive(True).gen_converter()(10) is True assert c.naive(False).gen_converter()(10) is False assert c.naive(None).gen_converter()(10) is None assert c.naive("1").as_type(int).gen_converter()(10) == 1 assert c.naive(1).gen_converter(method=True)(None, 10) == 1 finally: c.BaseConversion.max_counter = prev_max_counter
def test_filter(): assert list(c.naive([1, 2, 3]).filter(c.this().gt(2)).execute(None)) == [3] assert c.filter(c.this().gt(1), cast=list).execute([1, 2, 3]) == [2, 3] assert c.filter(c.this().gt(1), cast=tuple).execute([1, 2, 3]) == (2, 3) assert c.filter(c.this().gt(1), cast=set).execute([1, 2, 3]) == {2, 3} assert c.filter(c.this().gt(1), cast=lambda x: list(x)).execute([1, 2, 3]) == [2, 3] assert c.list_comp(c.this()).filter(c.this().gt(1)).execute([1, 2, 3]) == [ 2, 3, ] assert c.this().filter(c.this().gt(1), cast=list).execute([1, 2, 3]) == [ 2, 3, ]
def test_filter(): assert list(c.naive([1, 2, 3]).filter(c.this.gt(2)).execute(None)) == [3] assert c.filter(c.this.gt(1), cast=list).execute([1, 2, 3]) == [2, 3] assert c.filter(c.this.gt(1), cast=tuple).execute([1, 2, 3]) == (2, 3) assert c.filter(c.this.gt(1), cast=set).execute([1, 2, 3]) == {2, 3} assert c.filter(c.this.gt(1), cast=lambda x: list(x)).execute([1, 2, 3]) == [2, 3] assert c.list_comp(c.this).filter(c.this.gt(1)).execute([1, 2, 3], debug=False) == [ 2, 3, ] assert c.this.filter(c.this.gt(1), cast=list).execute([1, 2, 3], debug=False) == [ 2, 3, ] assert c.list_comp(c.this).filter( c.this > 1, cast=lambda x: list(x)).execute(range(4)) == [2, 3]
def test_pipe_conversion(): from convtools import conversion as c from convtools.base import PipeConversion assert PipeConversion(c.naive([1, 2, 3]), c.item(1)).execute(None) == 2 assert (PipeConversion(c.item("key1"), c.item("key2")).execute({"key1": { "key2": 3 }}, debug=False) == 3) assert (c.this.pipe(c.list_comp(c.this + 1)).filter(c.this > 3).execute( [1, 2, 3, 4, 5, 6], debug=False)) == [4, 5, 6, 7] c.aggregate( c.ReduceFuncs.Array(c.item("key"), default=list).pipe( c.if_( c.call_func(any, c.generator_comp(c.this.is_(None))), c.call_func(list), c.this, ))).gen_converter(debug=False)
def test_naive_conversion_or_and(): assert c.naive(False).or_(c.naive(False)).gen_converter()(100) is False assert (c.naive(False) | c.naive(False)).gen_converter()(100) is False assert c.naive(0).or_(c.naive(10)).gen_converter()(100) == 10 assert c.naive(10).and_(c.naive(0)).gen_converter()(100) == 0 assert (c.naive(10) & c.naive(0)).gen_converter()(100) == 0
def test_naive_conversion_callmethod(): mock = Mock() c.naive(mock).call_method("test_method", 1, abc=2).gen_converter()(100) mock.test_method.assert_called_with(1, abc=2)
def test_naive_conversion(): d = {1: 2} assert c.naive(d).gen_converter()(1) == d assert c.naive("abc").gen_converter()(1) == "abc" assert c.naive(1).gen_converter()(10) == 1 assert c.naive(True).gen_converter()(10) is True assert c.naive(False).gen_converter()(10) is False assert c.naive(None).gen_converter()(10) is None assert c.naive("1").as_type(int).gen_converter()(10) == 1 assert c.naive(1).gen_converter(method=True)(None, 10) == 1 assert ("%" not in next( iter(c.naive("%abc").gen_converter()._name_to_converter.values())) ["code_str"]) assert ("{" not in next( iter(c.naive("{abc").gen_converter()._name_to_converter.values())) ["code_str"]) assert ("abc" in next( iter(c.naive("abc").gen_converter()._name_to_converter.values())) ["code_str"])
def test_pipes(): assert c.list_comp(c.inline_expr("{0} ** 2").pass_args(c.this())).pipe( c.call_func(sum, c.this())).pipe( c.call_func( lambda x, a: x + a, c.this(), c.naive({ "abc": 10 }).item(c.input_arg("key_name")), )).pipe([c.this(), c.this()]).execute([1, 2, 3], key_name="abc", debug=False) == [ 24, 24, ] assert c.item(0).pipe(datetime.strptime, "%Y-%m-%d").pipe( c.call_func(lambda dt: dt.date(), c.this())).execute(["2019-01-01"], debug=False) == date(2019, 1, 1) assert c.item(0).pipe(datetime.strptime, "%Y-%m-%d").pipe( c.this().call_method("date")).execute(["2019-01-01"], debug=False) == date(2019, 1, 1) with c.OptionsCtx() as options: max_pipe_length = options.max_pipe_length = 10 with pytest.raises(c.ConversionException): conv = c.this() for i in range(max_pipe_length + 1): conv = c.this().pipe(conv) with c.OptionsCtx() as options2, pytest.raises(c.ConversionException): options2.max_pipe_length = 5 conv.clone() conv = c.dict_comp( c.item("name"), c.item("transactions").pipe( c.list_comp({ "id": c.item(0).as_type(str), "amount": c.item(1).pipe(c.if_(c.this(), c.this().as_type(Decimal), None)), })), ).gen_converter(debug=True) assert conv([{ "name": "test", "transactions": [(0, 0), (1, 10)] }]) == { "test": [ { "id": "0", "amount": None }, { "id": "1", "amount": Decimal("10") }, ] } with c.OptionsCtx() as options: max_pipe_length = options.max_pipe_length = 10 conv1 = c.item(0).pipe(c.item(1).pipe(c.item(2))) def measure_pipe_length(conv): length = 0 for i in range(max_pipe_length): if conv._predefined_input is not None: length += 1 conv = conv._predefined_input else: break return length pipe_length_before = measure_pipe_length(conv1) for i in range(max_pipe_length + 20): c.generator_comp(c.this().pipe(conv1)) pipe_length_after = measure_pipe_length(conv1) assert pipe_length_after == pipe_length_before
def test_docs(): print(1 < c.naive(2))
def test_naive_conversion_item(): d = {1: 2, 10: {"test": 15, 2: 777}, 100: {"test2": 200}} assert c.naive(d).item(1).execute(100) == 2 assert c.item(1).gen_converter()(d) == 2 assert c.item(10, "test").gen_converter()(d) == 15 assert c.item(11, "test", default=77).gen_converter()(d) == 77 assert (c.item(10, c.input_arg("arg1"), default=c.input_arg("arg2")).gen_converter()(d, arg1="test", arg2=77) == 15) assert (c.item(10, c.input_arg("arg1"), default=c.input_arg("arg2")).gen_converter()(d, arg1="tst", arg2=77) == 77) assert (c.item(11, "test", default=77).gen_converter(method=True)(None, d) == 77) assert c.item(10, "testt", default=77).gen_converter()(d) == 77 assert c.item(10, "testt", default=c.this()).gen_converter()(d) == d assert c.item(10, c.item(1)).gen_converter()(d) == 777 assert c.item(10).item(2).gen_converter()(d) == 777 with pytest.raises(KeyError): c.naive(d).item(11).gen_converter()(100) with pytest.raises(IndexError): c.naive([]).item(11).gen_converter()(100) with pytest.raises(TypeError): c.naive(None).item(11).gen_converter()(100) assert (c.naive(d).item(100).item("test2").gen_converter( debug=False)(100) == 200) assert (c.naive(d).item(c.this(), "test2").gen_converter(debug=False)(100) == 200) assert (c.naive(d).item(100, default=30).item( "test2", default=30).gen_converter(debug=False)(100) == 200) # testing defaults assert (c.naive(d).item(100, default=30).item( "test", default=30).gen_converter()(100) == 30) assert (c.naive(d).item(10).item("test2", default=30).gen_converter()(100) == 30) assert c.naive(True).is_(True).execute(100) is True assert c.naive(True).is_not(True).execute(100) is False assert c.naive(1).in_({1, 2}).execute(100) is True assert c.naive(1).in_({3, 2}).execute(100) is False assert c.naive(1).not_in({3, 2}).execute(100) is True assert c.naive(1).eq(1).execute(100) is True assert (c.naive(1) == 1).execute(100) is True assert c.naive(1).not_eq(1).execute(100) is False assert (c.naive(1) != 1).execute(100) is False assert c.naive(1).gte(1).execute(100) is True assert (c.naive(1) >= 1).execute(100) is True assert c.naive(2).gte(1).execute(100) is True assert (c.naive(2) >= 1).execute(100) is True assert c.naive(10).gt(1).execute(100) is True assert (c.naive(10) > 1).execute(100) is True assert c.naive(1).lte(1).execute(100) is True assert (c.naive(1) <= 1).execute(100) is True assert c.naive(0).lte(1).execute(100) is True assert (c.naive(0) <= 1).execute(100) is True assert c.naive(0).lt(1).execute(100) is True assert (c.naive(0) < 1).execute(100) is True assert c.this().neg().execute(2) == -2 assert (-c.this()).execute(2) == -2 assert (c.this() + c.this()).execute(2) == 4 assert (c.this() * c.this()).execute(3) == 9 assert (c.this() - c.this()).execute(2) == 0 assert (c.naive(5) / c.this()).execute(2) == 2.5 assert (c.naive(5) // c.this()).execute(2) == 2 assert (c.naive(5) % c.this()).execute(2) == 1
def test_base_reducer(): from convtools.aggregations import _ReducerExpression, _ReducerStatements assert c.aggregate(( c.reduce( _ReducerExpression(lambda a, b: a + b, expr=c.this(), initial=0)), c.reduce( _ReducerExpression(c.naive(lambda a, b: a + b), expr=c.this(), initial=int)), c.reduce(_ReducerExpression("{0} + {1}", expr=c.this(), default=0)), c.reduce( _ReducerExpression( "{0} + {1}", expr=c.this(), initial_from_first=int, default=0, )), c.reduce( _ReducerStatements( reduce="%(result)s += ({1} or 0)", initial_from_first="%(result)s = ({0} or 0)", default=0, ), c.this(), ), c.reduce( _ReducerStatements( reduce="%(result)s += ({1} or 0)", default=c.naive(int), ), c.this(), ), c.reduce( _ReducerStatements( reduce="%(result)s = ({1} or 0)", initial=0, ), c.this(), ), )).filter(c.this() > 5, cast=tuple).gen_converter(debug=True)([1, 2, 3]) == ( 6, 6, 6, 6, 6, 6, ) with pytest.raises(AssertionError): c.aggregate((c.reduce( c.ReduceFuncs.Sum, c.reduce(c.ReduceFuncs.Count), ), )).gen_converter() conv = c.aggregate( c.reduce(c.ReduceFuncs.DictArray, (c.item(0), c.item(1)))).gen_converter(debug=True) data = [ ("a", 1), ("a", 2), ("b", 3), ] result = {"a": [1, 2], "b": [3]} assert conv(data) == result assert conv([]) is None conv2 = c.aggregate({ "key": c.reduce(c.ReduceFuncs.DictArray, (c.item(0), c.item(1))) }).gen_converter(debug=True) assert conv2([]) == {"key": None} assert conv2(data) == {"key": result}
def test_doc__index_deserialization(): class Employee: def __init__(self, **kwargs): self.kwargs = kwargs input_data = { "objects": [ { "id": 1, "first_name": "john", "last_name": "black", "dob": None, "salary": "1,000.00", "department": "D1 ", "date": "2000-01-01", }, { "id": 2, "first_name": "bob", "last_name": "wick", "dob": "1900-01-01", "salary": "1,001.00", "department": "D3 ", "date": "2000-01-01", }, ] } # prepare a few conversions to reuse c_strip = c.this.call_method("strip") c_capitalize = c.this.call_method("capitalize") c_decimal = c.this.call_method("replace", ",", "").as_type(Decimal) c_date = c.call_func(datetime.strptime, c.this, "%Y-%m-%d").call_method("date") # reusing c_date c_optional_date = c.if_(c.this, c_date, None) first_name = c.item("first_name").pipe(c_capitalize) last_name = c.item("last_name").pipe(c_capitalize) # call "format" method of a string and pass first & last names as # parameters full_name = c("{} {}").call_method("format", first_name, last_name) conv = ( c.item("objects").pipe( c.generator_comp({ "id": c.item("id"), "first_name": first_name, "last_name": last_name, "full_name": full_name, "date_of_birth": c.item("dob").pipe(c_optional_date), "salary": c.item("salary").pipe(c_decimal), # pass a hardcoded dict and to get value by "department" # key "department_id": c.naive({ "D1": 10, "D2": 11, "D3": 12, }).item(c.item("department").pipe(c_strip)), "date": c.item("date").pipe(c_date), })).pipe( c.dict_comp( c.item("id"), # key c.apply_func( # value Employee, args=(), kwargs=c.this, ), )).gen_converter(debug=True) # to see print generated code ) result = conv(input_data) assert result[1].kwargs == { "date": date(2000, 1, 1), "date_of_birth": None, "department_id": 10, "first_name": "John", "full_name": "John Black", "id": 1, "last_name": "Black", "salary": Decimal("1000.00"), } assert result[2].kwargs == { "date": date(2000, 1, 1), "date_of_birth": date(1900, 1, 1), "department_id": 12, "first_name": "Bob", "full_name": "Bob Wick", "id": 2, "last_name": "Wick", "salary": Decimal("1001.00"), }
def test_doc__index_deserialization(): class Employee: def __init__(self, **kwargs): self.kwargs = kwargs input_data = { "objects": [ { "id": 1, "first_name": "john", "last_name": "black", "dob": None, "salary": "1,000.00", "department": "D1 ", "date": "2000-01-01", }, { "id": 2, "first_name": "bob", "last_name": "wick", "dob": "1900-01-01", "salary": "1,001.00", "department": "D3 ", "date": "2000-01-01", }, ] } # get by "department" key and then call method "strip" department = c.item("department").call_method("strip") first_name = c.item("first_name").call_method("capitalize") last_name = c.item("last_name").call_method("capitalize") # call "format" method of a string and pass first & last names as # parameters full_name = c("{} {}").call_method("format", first_name, last_name) date_of_birth = c.item("dob") # partially initialized "strptime" parse_date = c.call_func(datetime.strptime, c.this(), "%Y-%m-%d").call_method("date") conv = ( c.item("objects").pipe( c.generator_comp({ "id": c.item("id"), "first_name": first_name, "last_name": last_name, "full_name": full_name, "date_of_birth": c.if_( date_of_birth, date_of_birth.pipe(parse_date), None, ), "salary": c.call_func( Decimal, c.item("salary").call_method("replace", ",", ""), ), # pass a hardcoded dict and to get value by "department" # key "department_id": c.naive({ "D1": 10, "D2": 11, "D3": 12, }).item(department), "date": c.item("date").pipe(parse_date), })). pipe( c.dict_comp( c.item( "id"), # key # write a python code expression, format with passed parameters c.inline_expr("{employee_cls}(**{kwargs})").pass_args( employee_cls=Employee, kwargs=c.this(), ), # value )).gen_converter(debug=True)) result = conv(input_data) assert result[1].kwargs == { "date": date(2000, 1, 1), "date_of_birth": None, "department_id": 10, "first_name": "John", "full_name": "John Black", "id": 1, "last_name": "Black", "salary": Decimal("1000.00"), } assert result[2].kwargs == { "date": date(2000, 1, 1), "date_of_birth": date(1900, 1, 1), "department_id": 12, "first_name": "Bob", "full_name": "Bob Wick", "id": 2, "last_name": "Wick", "salary": Decimal("1001.00"), }
def test_naive_conversion_applymethod(): mock = Mock() c.naive(mock).apply_method("test_method", (1, ), dict(abc=2)).gen_converter()(100) mock.test_method.assert_called_with(1, abc=2)
def test_or_and_not(): assert c.or_(None, 0).gen_converter()(100) == 0 assert c.and_(None, 0).gen_converter()(100) is None assert c.not_(True).gen_converter()(100) is False assert (~c.this()).gen_converter()(True) is False assert c.naive(None).not_().execute(100) is True
def test_gen_converter(): class A: x = 10 def __init__(self): self.x = 20 conv1 = (c.this() + c.input_arg("self").attr("x")).gen_converter(method=True) conv2 = (c.this() + c.input_arg("cls").attr("x")).gen_converter(method=True) conv3 = classmethod( (c.this() + c.input_arg("cls").attr("x")).gen_converter(class_method=True)) conv4 = classmethod( (c.this() + c.input_arg("self").attr("x")).gen_converter(class_method=True)) conv5 = (c.this() + c.input_arg("self").attr("x") + c.input_arg("n")).gen_converter( signature="self, n=1000, data_=15") conv6 = staticmethod( ((c.this() + c.call_func(sum, c.input_arg("args"))) * c.input_arg("kwargs").call_method("get", "multiplicator", 1) ).gen_converter(signature="data_, *args, **kwargs")) assert A().conv1(100) == 120 assert A.conv3(100) == 110 with pytest.raises(NameError): A().conv2(100) with pytest.raises(NameError): A.conv4(100) assert A().conv5() == 1035 assert A().conv5(data_=7) == 1027 assert A().conv5(n=100) == 135 assert A.conv6(20) == 20 assert A.conv6(20, 1, 2, 3) == 26 assert A.conv6(20, 1, 2, 3, multiplicator=10) == 260 assert (c.call_func(sum, c.this()).gen_converter(signature="*data_")(1, 2, 3) == 6) assert (c.call_func(lambda i: globals().__setitem__("A", 1) or sum(i), c.this()).gen_converter(signature="*data_")(1, 2, 3) == 6) assert c({ c.naive("-").call_method("join", c.this().call_method("keys")): c.call_func(sum, c.this().call_method("values")) }).gen_converter(signature="**data_")(a=1, b=2, c=3) == { "a-b-c": 6 } with pytest.raises(c.ConversionException): c.call_func(sum, c.input_arg("x")).gen_converter(signature="*data_")(1, 2, 3) with pytest.raises(c.ConversionException): c.this().gen_converter(method=True, class_method=True)
def test_doc__index_word_count(): # Let's say we need to count words across all files input_data = [ "war-and-peace-1.txt", "war-and-peace-2.txt", "war-and-peace-3.txt", "war-and-peace-4.txt", ] # # iterate an input and read file lines # # def read_file(filename): # with open(filename) as f: # for line in f: # yield line # extract_strings = c.generator_comp(c.call_func(read_file, c.this())) # to simplify testing extract_strings = c.generator_comp( c.call_func(lambda filename: [filename], c.this())) # 1. make ``re`` pattern available to the code to be generated # 2. call ``finditer`` method of the pattern and pass the string # as an argument # 3. pass the result to the next conversion # 4. iterate results, call ``.group()`` method of each re.Match # and call ``.lower()`` on each result split_words = (c.naive(re.compile(r"\w+")).call_method( "finditer", c.this()).pipe( c.generator_comp(c.this().call_method("group", 0).call_method("lower")))) # ``extract_strings`` is the generator of strings # so we iterate it and pass each item to ``split_words`` conversion vectorized_split_words = c.generator_comp(c.this().pipe(split_words)) # flattening the result of ``vectorized_split_words``, which is # a generator of generators of strings flatten = c.call_func( chain.from_iterable, c.this(), ) # aggregate the input, the result is a single dict # words are keys, values are count of words dict_word_to_count = c.aggregate( c.ReduceFuncs.DictCount(c.this(), c.this(), default=dict)) # take top N words by: # - call ``.items()`` method of the dict (the result of the aggregate) # - pass the result to ``sorted`` # - take the slice, using input argument named ``top_n`` # - cast to a dict take_top_n = (c.this().call_method("items").sort( key=lambda t: t[1], reverse=True).pipe(c.this()[:c.input_arg("top_n")]).as_type(dict)) # the resulting pipeline is pretty self-descriptive, except the ``c.if_`` # part, which checks the condition (first argument), # and returns the 2nd if True OR the 3rd (input data by default) otherwise pipeline = ( extract_strings.pipe(flatten).pipe(vectorized_split_words).pipe( flatten).pipe(dict_word_to_count).pipe( c.if_( c.input_arg("top_n").is_not(None), c.this().pipe(take_top_n), )) # Define the resulting converter function signature. In fact this # isn't necessary if you don't need to specify default values ).gen_converter(debug=True, signature="data_, top_n=None") assert pipeline(input_data, top_n=3) == {"war": 4, "and": 4, "peace": 4}