예제 #1
0
def test_list_comprehension():
    assert c.list_comp(1).gen_converter()(range(5)) == [1] * 5
    data = [{"name": "John"}, {"name": "Bill"}, {"name": "Nick"}]
    assert c.list_comp(
        c.item("name")).sort(key=lambda n: n).gen_converter()(data) == [
            "Bill",
            "John",
            "Nick",
        ]
    assert c.list_comp(c.item("name")).sort().gen_converter()(data) == [
        "Bill",
        "John",
        "Nick",
    ]
    assert tuple(c.generator_comp(c.item("name")).gen_converter()(data)) == (
        "John",
        "Bill",
        "Nick",
    )
    assert c.list_comp(c.item("name")).sort(
        key=lambda n: n,
        reverse=True).gen_converter()(data) == ["Nick", "John", "Bill"]
    assert c.list_comp({(c.item("name"), )}, ).execute(data) == [
        {("John", )},
        {("Bill", )},
        {("Nick", )},
    ]
예제 #2
0
def test_list_comprehension():
    assert c.list_comp(1).gen_converter()(range(5)) == [1] * 5
    data = [{"name": "John"}, {"name": "Bill"}, {"name": "Nick"}]
    assert c.list_comp(c.item("name")).sort(
        key=lambda n: n).gen_converter()(data) == ["Bill", "John", "Nick"]
    assert c.list_comp(c.item("name")).sort().gen_converter()(data) == [
        "Bill",
        "John",
        "Nick",
    ]
    assert tuple(c.generator_comp(c.item("name")).gen_converter()(data)) == (
        "John",
        "Bill",
        "Nick",
    )
    assert c.list_comp(c.item("name")).sort(
        key=lambda n: n,
        reverse=True).gen_converter()(data) == ["Nick", "John", "Bill"]
    assert c.list_comp({(c.item("name"), )}, ).execute(data) == [
        {("John", )},
        {("Bill", )},
        {("Nick", )},
    ]

    class CustomException(Exception):
        pass

    def f():
        yield 1
        raise CustomException

    wrapped_generator = c.generator_comp(c.this()).execute(f())
    with pytest.raises(CustomException):
        list(wrapped_generator)
예제 #3
0
def test_if():
    conv1 = c.if_(True,
                  c.this() * 2,
                  c.this() - 1000).gen_converter(debug=False)
    assert conv1(0) == -1000
    assert conv1(10) == 20

    conv2 = c.list_comp(c.if_(c.this() % 2 == 0,
                              c.this() * 10,
                              c.this() * 100)).gen_converter(debug=False)
    conv3 = c.list_comp(
        c.if_(
            c.this() % 2 == 0,
            c.this() * 10,
            c.this() * 100,
            no_input_caching=True,
        )).gen_converter(debug=False)
    assert conv2([1, 2, 3, 4]) == [100, 20, 300, 40]
    assert conv3([1, 2, 3, 4]) == [100, 20, 300, 40]

    conv4 = c.list_comp((c.this() - 5).pipe(
        c.if_(c.this() % 2 == 0,
              c.this() * 10,
              c.this() * 100))).gen_converter(debug=False)
    assert conv4([1, 2, 3, 4]) == [-40, -300, -20, -100]

    conv5 = c.if_().gen_converter(debug=False)
    assert conv5(0) == 0 and conv5(1) == 1

    conv6 = c.list_comp(
        c.if_(c.this(), None, c.this(),
              no_input_caching=True)).gen_converter(debug=False)
    assert conv6([1, False, 2, None, 3, 0]) == [
        None,
        False,
        None,
        None,
        None,
        0,
    ]

    assert PipeConversion.input_is_simple("'abc'")
    assert PipeConversion.input_is_simple("0")
    assert PipeConversion.input_is_simple("None")
    assert PipeConversion.input_is_simple("True")
    assert PipeConversion.input_is_simple("False")
    assert PipeConversion.input_is_simple("a[1]")
    assert PipeConversion.input_is_simple("a['1']")
    assert PipeConversion.input_is_simple("a[1][2]")
    assert not PipeConversion.input_is_simple("a[1][2][3]")
    assert not PipeConversion.input_is_simple("1 + 1")
    assert not PipeConversion.input_is_simple("x.a")
    assert not PipeConversion.input_is_simple("x()")
예제 #4
0
def test_optional_dict():
    conv = c.list_comp({
        "key1":
        c.item("key1"),
        "key2":
        c.optional(c.item("key2", default=None)),
        "key3":
        c.optional(c.item("key1") * 200, skip_value=2000),
        "key4":
        c.optional(
            c.item("key1") * c.input_arg("x") * 300,
            skip_if=c.item("key1") < 5,
        ),
        "key5":
        c.optional(
            c.item("key1") * c.input_arg("x") * 300,
            keep_if=c.item("key1") >= 5,
        ),
        c.optional(c.item("key2", default=-1), skip_value=-1):
        0,
        c.optional(c.item("key1") * 400, skip_if=c.item("key1") < 5):
        c.optional(c.item("key22")),
        c.optional(c.item("key1") * 500, skip_if=c.item("key1") < 5):
        c.optional(c.item("key22"), skip_value=20),
    }).gen_converter(debug=False)
    assert conv([{
        "key1": 1,
        "key2": 2
    }, {
        "key1": 10,
        "key22": 20
    }], x=1) == [
        {
            "key1": 1,
            "key2": 2,
            "key3": 200,
            2: 0
        },
        {
            "key1": 10,
            "key4": 3000,
            "key5": 3000,
            4000: 20
        },
    ]

    with pytest.raises(Exception):
        c.list_comp(c.optional(c.item("key1"))).gen_converter()
    with pytest.raises(Exception):
        c.optional(c.item("key1"), skip_value=1, skip_if=c.this())
    with pytest.raises(Exception):
        c.this().pipe(c.optional(c.this()))
예제 #5
0
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]
예제 #6
0
def test_optional_list_tuple_set():
    conv = c.list_comp([
        c.item("key1"),
        c.optional(c.item("key2", default=None)),
        c.optional(c.item("key1") * 2, skip_value=20),
        c.optional(c.item("key1") * 3, skip_if=c.item("key1") < 5),
    ]).gen_converter(debug=False)
    assert conv([{
        "key1": 1,
        "key2": 2
    }, {
        "key1": 10,
        "key22": 20
    }]) == [
        [1, 2, 2],
        [10, 30],
    ]
    conv = c.list_comp((
        c.item("key1"),
        c.optional(c.item("key2", default=None)),
        c.optional(c.item("key1") * 2, skip_value=20),
        c.optional(c.item("key1") * 3, skip_if=c.item("key1") < 5),
    )).gen_converter(debug=False)
    assert conv([{
        "key1": 1,
        "key2": 2
    }, {
        "key1": 10,
        "key22": 20
    }]) == [
        (1, 2, 2),
        (10, 30),
    ]
    conv = c.list_comp({
        c.item("key1"),
        c.optional(c.item("key2", default=None)),
        c.optional(c.item("key1") * 2, skip_value=20),
        c.optional(c.item("key1") * 3, skip_if=c.item("key1") < 5),
    }).gen_converter(debug=False)
    assert conv([{
        "key1": 1,
        "key2": 2
    }, {
        "key1": 10,
        "key22": 20
    }]) == [
        {1, 2, 2},
        {10, 30},
    ]
예제 #7
0
def test_breakpoint():
    before = Breakpoint.debug_func
    l = []

    def add_to_list(obj):
        l.append(obj)
        return obj

    Breakpoint.debug_func = staticmethod(add_to_list)
    try:
        c.list_comp(c.this.breakpoint()).execute([1, 2, 3])
        c.list_comp(c.breakpoint()).execute([3, 4])
    finally:
        Breakpoint.debug_func = before
    assert l == [1, 2, 3, 3, 4]
예제 #8
0
def test_labels():
    conv1 = c.if_(
        1,
        c.input_arg("y").item("abc").add_label("abc").pipe(
            c.input_arg("x").pipe(
                c.inline_expr("{cde} + 10").pass_args(
                    cde=c.this().item("cde")))).pipe(
                        c.inline_expr("{this} + {abc}").pass_args(
                            this=c.this(), abc=c.label("abc"))),
        2,
    ).gen_converter(debug=False)
    assert conv1(data_=1, x={"cde": 2}, y={"abc": 3}) == 15

    list(c.generator_comp(c.this().add_label("a")).execute([1, 2]))
    c.list_comp(c.this().add_label("a")).execute([1, 2])
예제 #9
0
def test_mutation_item():
    now = datetime.now()
    assert c.list_comp(
        {
            "name": c.item("fullName"),
            "age": c.item("age").as_type(int),
            "to_del": 1,
        }
    ).pipe(
        c.list_comp(
            c.call_func(lambda d: d, c.this).tap(
                c.Mut.set_item(
                    "name_before", c.label("_input").item(0, "name")
                ),
                c.Mut.set_item("name", c.item("name").call_method("lower")),
                c.Mut.set_item(
                    "name_after", c.label("_input").item(0, "name")
                ),
                c.Mut.set_item("_updated", c.input_arg("now")),
                c.Mut.set_item(c.item("age"), c.item("age") >= 18),
                c.Mut.del_item("to_del"),
                c.Mut.custom(c.this.call_method("update", {"to_add": 2})),
                c.this.call_method("update", {"to_add2": 4}),
            )
        ),
        label_input="_input",
    ).execute(
        [{"fullName": "John", "age": "28"}], debug=False, now=now
    ) == [
        {
            "name": "john",
            "name_after": "john",
            "name_before": "John",
            "age": 28,
            "_updated": now,
            28: True,
            "to_add": 2,
            "to_add2": 4,
        }
    ]

    with pytest.raises(Exception):
        c.item(c.Mut.set_item("abc", "cde"))
    with pytest.raises(Exception):
        conversion = c.item(1)
        conversion.ensure_conversion(
            c.Mut.set_item("abc", "cde"), explicitly_allowed_cls=GetItem
        )
예제 #10
0
def test_simple_label():
    conv1 = (c.tuple(c.item(2).add_label("a"), c.this()).pipe(
        c.item(1).pipe(c.list_comp(
            (c.this(), c.label("a"))))).gen_converter(debug=False))
    assert conv1([1, 2, 3, 4]) == [(1, 3), (2, 3), (3, 3), (4, 3)]

    conv2 = (c.tuple(c.item(1).add_label("a"), c.this()).pipe(
        c.item(1),
        label_input={
            "aa": c.item(0),
            "bb": c.item(0)
        },
        label_output="collection1",
    ).pipe(
        c.label("collection1").pipe(
            c.aggregate(
                c.ReduceFuncs.Sum(
                    c.this() + c.label("a") + c.label("aa") +
                    c.input_arg("x") + c.label("collection1").item(0), ))),
        label_output="b",
    ).pipe(c.this() + c.label("b")).gen_converter(debug=False))
    assert conv2([1, 2, 3, 4], x=10) == 140

    conv3 = (c.tuple(c.item("default").add_label("default"), c.this()).pipe(
        c.item(1).pipe(c.item(
            "abc", default=c.label("default")))).gen_converter(debug=False))
    assert conv3({"default": 1}) == 1

    with pytest.raises(c.ConversionException):
        c.this().pipe(c.this(), label_input=1)
예제 #11
0
def test_complex_labeling():
    conv1 = (c.this().add_label("input").pipe(
        c.filter(c.this() % 3 == 0),
        label_input={
            "input_type": c.call_func(type, c.this())
        },
    ).pipe(
        c.list_comp(c.this().as_type(str)),
        label_output={
            "list_length": c.call_func(len, c.this()),
            "separator": c.if_(c.label("list_length") > 10, ",", ";"),
        },
    ).pipe({
        "result": c.label("separator").call_method("join", c.this()),
        "input_type": c.label("input_type"),
        "input_data": c.label("input"),
    }).gen_converter(debug=False))
    assert conv1(range(30)) == {
        "result": "0;3;6;9;12;15;18;21;24;27",
        "input_type": range,
        "input_data": range(0, 30),
    }
    assert conv1(range(40)) == {
        "result": "0,3,6,9,12,15,18,21,24,27,30,33,36,39",
        "input_type": range,
        "input_data": range(0, 40),
    }
예제 #12
0
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}))
예제 #13
0
def test_memory_freeing():
    converter = (
        c.this()
        .pipe(
            c.list_comp(c.this() + c.label("input_data").item(0)),
            label_input=dict(input_data=c.this()),
        )
        .gen_converter(debug=True)
    )

    sizes = []
    sizes.append(total_size(converter.__dict__))

    for i in range(100):
        l_input = [i + j for j in range(3)]
        l_out = [j + l_input[0] for j in l_input]
        assert converter(l_input) == l_out
        sizes.append(total_size(converter.__dict__))
    assert all(sizes[0] == size for size in sizes[1:]), sizes

    conv2 = (
        c.inline_expr("globals().__setitem__('a', {}) or 1")
        .pass_args(c.this())
        .gen_converter()
    )
    with pytest.raises(AssertionError):
        # should raise because of a memory leak
        conv2(123)
예제 #14
0
def test_chunks_by_size(data_for_chunking):
    assert c.chunk_by(size=5).iter(c.list_comp(c.item("z"))).as_type(
        list
    ).execute(data_for_chunking) == [
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18],
    ]

    assert c.chunk_by(c.item("x")).iter(c.list_comp(c.item("z"))).as_type(
        list
    ).execute(data_for_chunking) == [
        [10, 11, 12],
        [13, 14, 15],
        [16, 17, 18],
    ]
    assert c.chunk_by(c.item("x"), size=2).iter(
        c.list_comp(c.item("z"))
    ).as_type(list).execute(data_for_chunking) == [
        [10, 11],
        [12],
        [13, 14],
        [15],
        [16, 17],
        [18],
    ]

    assert c.chunk_by(c.item("x"), c.item("y")).iter(
        c.list_comp(c.item("z"))
    ).as_type(list).execute(data_for_chunking) == [
        [10, 11],
        [12],
        [13],
        [14, 15],
        [16, 17],
        [18],
    ]

    assert (
        c.chunk_by(c.item("x"), size=2)
        .aggregate(
            c.ReduceFuncs.Last(c.item("z")),
        )
        .as_type(list)
        .execute(data_for_chunking)
        == [11, 12, 14, 15, 17, 18]
    )
예제 #15
0
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]
예제 #16
0
def test_name_generation():
    c.list_comp({i: c.item(f"test{i}", default=1)
                 for i in range(100)}).gen_converter(debug=False)

    item = c.this()
    ctx = c.BaseConversion._init_ctx()
    for i in range(11):
        item.gen_name("abc", ctx, i)

    assert item.gen_name("_", ctx, (1, 2)) == item.gen_name("_", ctx, (1, 2))
    obj = object()
    assert item.gen_name("_", ctx,
                         (1, obj)) == item.gen_name("_", ctx, (1, obj))
    obj = (1, [])
    assert item.gen_name("_", ctx, obj) == item.gen_name(
        "_",
        ctx,
        obj,
    )
예제 #17
0
def test_comprehensions_sorting():
    assert c.generator_comp(c.this()).sort().execute(
        [2, 1, 3], debug=False
    ) == [1, 2, 3]
    assert c.list_comp(c.this()).sort().execute([2, 1, 3], debug=False) == [
        1,
        2,
        3,
    ]
    assert c.this().pipe(c.list_comp(c.this())).sort().execute(
        [2, 1, 3], debug=False
    ) == [
        1,
        2,
        3,
    ]
    assert c.list_comp(c.this()).sort().sort(reverse=True).execute(
        [2, 1, 3], debug=False
    ) == [3, 2, 1]

    assert c.set_comp(c.this()).sort().execute([2, 2, 1, 3], debug=False) == [
        1,
        2,
        3,
    ]
    assert c.tuple_comp(c.this()).sort().execute(
        [2, 2, 1, 3], debug=False
    ) == (
        1,
        2,
        2,
        3,
    )
    assert c.dict_comp(c.this() * -1, c.this()).sort().execute(
        [2, 2, 1, 3], debug=False
    ) == OrderedDict(
        [
            (-3, 3),
            (-2, 2),
            (-1, 1),
        ]
    )
예제 #18
0
def test_comprehension_filter_cast_assumptions():
    assert isinstance(
        c.generator_comp(c.this).filter(c.this).execute(range(10)),
        GeneratorType,
    )
    assert isinstance(
        c.generator_comp(c.this).filter(c.this, cast=None).execute(range(10)),
        GeneratorType,
    )
    assert (c.list_comp(c.this).filter(c.this).execute(range(3))) == [
        1,
        2,
    ]

    def f(x):
        f.number_of_calls += 1
        if f.number_of_calls > f.max_number_of_calls:
            raise ValueError
        return bool(x)

    f.max_number_of_calls = 2
    f.number_of_calls = 0

    assert (c.set_comp(c.this).filter(c.call_func(f,
                                                  c.this)).execute([0, 0,
                                                                    1])) == {
                                                                        1,
                                                                    }
    assert (c.set_comp(c.this).filter(c.this, cast=list).execute([0, 0,
                                                                  1])) == [
                                                                      1,
                                                                  ]
    assert (c.set_comp(c.this).filter(c.this).execute(range(3))) == {
        1,
        2,
    }
    assert (c.tuple_comp(c.this).filter(c.this).execute(range(3))) == (
        1,
        2,
    )
    assert (c.tuple_comp(c.this).filter(c.this, list).execute(range(3))) == [
        1,
        2,
    ]
    assert (c.dict_comp(c.this,
                        c.this).filter(c.item(0)).execute(range(3))) == {
                            1: 1,
                            2: 2,
                        }
    assert (c.dict_comp(c.this, c.this).filter(c.item(0),
                                               dict).execute(range(3))) == {
                                                   1: 1,
                                                   2: 2,
                                               }
예제 #19
0
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,
    ]
예제 #20
0
def test_pipe_single_call_functions():
    class CustomException(Exception):
        pass

    def one_off_func():
        if one_off_func.first:
            one_off_func.first = False
            return 1
        raise CustomException

    one_off_func.first = True

    assert (c.list_comp(
        c.call_func(one_off_func).pipe((
            c.this + 1,
            c.this + 2,
        ))).gen_converter(debug=False)([1]) == [(2, 3)])
예제 #21
0
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)
예제 #22
0
def test_chunks_by_condition(data_for_chunking):
    assert c.chunk_by_condition(c.call_func(len, c.CHUNK) < 5).iter(
        c.list_comp(c.item("z"))
    ).as_type(list).execute(data_for_chunking) == [
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18],
    ]
    assert c.chunk_by_condition(
        c.and_(c.call_func(len, c.CHUNK) < 5, c.item("z") < 18)
    ).aggregate(c.ReduceFuncs.Median(c.item("z"))).as_type(list).execute(
        data_for_chunking,
    ) == [
        12,
        16,
        18,
    ]
    assert c.chunk_by_condition(False).as_type(list).execute(range(3)) == [
        [0],
        [1],
        [2],
    ]
예제 #23
0
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
예제 #24
0
def test_doc__index_intro():

    # ======== #
    # GROUP BY #
    # ======== #
    input_data = [
        {
            "a": 5,
            "b": "foo"
        },
        {
            "a": 10,
            "b": "foo"
        },
        {
            "a": 10,
            "b": "bar"
        },
        {
            "a": 10,
            "b": "bar"
        },
        {
            "a": 20,
            "b": "bar"
        },
    ]

    conv = (c.group_by(c.item("b")).aggregate({
        "b":
        c.item("b"),
        "a_first":
        c.ReduceFuncs.First(c.item("a")),
        "a_max":
        c.ReduceFuncs.Max(c.item("a")),
    }).gen_converter(debug=True))

    assert conv(input_data) == [
        {
            "b": "foo",
            "a_first": 5,
            "a_max": 10
        },
        {
            "b": "bar",
            "a_first": 10,
            "a_max": 20
        },
    ]

    # ========= #
    # AGGREGATE #
    # ========= #
    conv = c.aggregate({
        # list of "a" values where "b" equals to "bar"
        "a":
        c.ReduceFuncs.Array(c.item("a"), where=c.item("b") == "bar"),
        # "b" value of a row where "a" has Max value
        "b":
        c.ReduceFuncs.MaxRow(c.item("a"), ).item("b", default=None),
    }).gen_converter(debug=True)

    assert conv(input_data) == {"a": [10, 10, 20], "b": "bar"}

    # ==== #
    # JOIN #
    # ==== #
    collection_1 = [
        {
            "id": 1,
            "name": "Nick"
        },
        {
            "id": 2,
            "name": "Joash"
        },
        {
            "id": 3,
            "name": "Bob"
        },
    ]
    collection_2 = [
        {
            "ID": "3",
            "age": 17,
            "country": "GB"
        },
        {
            "ID": "2",
            "age": 21,
            "country": "US"
        },
        {
            "ID": "1",
            "age": 18,
            "country": "CA"
        },
    ]
    input_data = (collection_1, collection_2)

    conv = (c.join(
        c.item(0),
        c.item(1),
        c.and_(
            c.LEFT.item("id") == c.RIGHT.item("ID").as_type(int),
            c.RIGHT.item("age") >= 18,
        ),
        how="left",
    ).pipe(
        c.list_comp({
            "id": c.item(0, "id"),
            "name": c.item(0, "name"),
            "age": c.item(1, "age", default=None),
            "country": c.item(1, "country", default=None),
        })).gen_converter(debug=True))

    assert conv(input_data) == [
        {
            "id": 1,
            "name": "Nick",
            "age": 18,
            "country": "CA"
        },
        {
            "id": 2,
            "name": "Joash",
            "age": 21,
            "country": "US"
        },
        {
            "id": 3,
            "name": "Bob",
            "age": None,
            "country": None
        },
    ]