예제 #1
0
def test_operator_parse_brackets() -> None:
    assert [
        BinOp(
            start=Pos(line=0, col=4, filename=FNAME),
            end=Pos(line=0, col=24, filename=FNAME),
            op=logical_or,
            left=Lookup(
                start=Pos(line=0, col=4, filename=FNAME),
                end=Pos(line=0, col=7, filename=FNAME),
                root="foo",
                trailer=[],
            ),
            right=BinOp(
                start=Pos(line=0, col=12, filename=FNAME),
                end=Pos(line=0, col=24, filename=FNAME),
                op=operator.eq,
                left=Lookup(
                    start=Pos(line=0, col=12, filename=FNAME),
                    end=Pos(line=0, col=15, filename=FNAME),
                    root="bar",
                    trailer=[],
                ),
                right=Literal(
                    start=Pos(line=0, col=19, filename=FNAME),
                    end=Pos(line=0, col=24, filename=FNAME),
                    val="baz",
                ),
            ),
        )
    ] == PARSER.parse(list(tokenize("""${{ foo or (bar == "baz") }}""", START)))
예제 #2
0
def test_func_call_single_arg() -> None:
    assert [
        Call(
            Pos(0, 4, FNAME),
            Pos(0, 13, FNAME),
            FUNCTIONS["len"],
            [Literal(Pos(0, 8, FNAME), Pos(0, 13, FNAME), "abc")],
            [],
        )
    ] == PARSER.parse(list(tokenize("${{ len('abc') }}", START)))
예제 #3
0
def test_parser1() -> None:
    assert [
        Text(Pos(0, 0, FNAME), Pos(0, 5, FNAME), "some "),
        Lookup(
            Pos(0, 9, FNAME),
            Pos(0, 16, FNAME),
            "var",
            [AttrGetter(Pos(0, 13, FNAME), Pos(0, 16, FNAME), "arg")],
        ),
        Text(Pos(0, 19, FNAME), Pos(0, 24, FNAME), " text"),
    ] == PARSER.parse(list(tokenize("some ${{ var.arg }} text", START)))
예제 #4
0
def test_func_call_with_trailer_attr() -> None:
    assert [
        Call(
            Pos(0, 4, FNAME),
            Pos(0, 39, FNAME),
            FUNCTIONS["from_json"],
            [Literal(Pos(0, 14, FNAME), Pos(0, 36, FNAME), '{"a": 1, "b": "val"}')],
            [AttrGetter(Pos(0, 38, FNAME), Pos(0, 39, FNAME), "a")],
        )
    ] == PARSER.parse(
        list(tokenize("""${{ from_json('{"a": 1, "b": "val"}').a }}""", START))
    )
예제 #5
0
def test_tmpl_ok5() -> None:
    assert [
        Lookup(
            Pos(0, 4, FNAME),
            Pos(0, 18, FNAME),
            "name",
            [
                AttrGetter(Pos(0, 9, FNAME), Pos(0, 12, FNAME), "sub"),
                AttrGetter(Pos(0, 13, FNAME), Pos(0, 18, FNAME), "param"),
            ],
        )
    ] == PARSER.parse(list(tokenize("$[[ name.sub.param ]]", START)))
예제 #6
0
async def test_failure_func(expr: str, statuses: List[TaskStatus],
                            result: bool, client: Client) -> None:
    context = {
        "needs": {
            f"task_{num}": DepCtx(status, {})
            for num, status in enumerate(statuses, 1)
        }
    }
    parsed = PARSER.parse(list(tokenize("${{" + expr + "}}", START)))
    assert len(parsed) == 1
    assert result == await parsed[0].eval(DictContext(context,
                                                      client))  # type: ignore
예제 #7
0
def test_unary_operator_parse(op_str: str, op_func: Any) -> None:
    assert [
        UnaryOp(
            Pos(0, 4, FNAME),
            Pos(0, 10 + len(op_str), FNAME),
            op_func,
            Literal(
                Pos(0, 5 + len(op_str), FNAME),
                Pos(0, 10 + len(op_str), FNAME),
                "bar",
            ),
        )
    ] == PARSER.parse(list(tokenize(f"""${{{{ {op_str} "bar" }}}}""", START)))
예제 #8
0
def test_func_call_multiple_args() -> None:
    assert [
        Call(
            Pos(0, 4, FNAME),
            Pos(0, 27, FNAME),
            FUNCTIONS["fmt"],
            [
                Literal(Pos(0, 8, FNAME), Pos(0, 15, FNAME), "{} {}"),
                Literal(Pos(0, 17, FNAME), Pos(0, 22, FNAME), "abc"),
                Literal(Pos(0, 24, FNAME), Pos(0, 27, FNAME), 123),
            ],
            [],
        )
    ] == PARSER.parse(list(tokenize('${{ fmt("{} {}", "abc", 123) }}', START)))
예제 #9
0
def test_operator_parse(op_str: str, op_func: Any) -> None:
    assert [
        BinOp(
            Pos(0, 4, FNAME),
            Pos(0, 14 + len(op_str), FNAME),
            op_func,
            Lookup(Pos(0, 4, FNAME), Pos(0, 7, FNAME), "foo", []),
            Literal(
                Pos(0, 9 + len(op_str), FNAME),
                Pos(0, 14 + len(op_str), FNAME),
                "bar",
            ),
        )
    ] == PARSER.parse(list(tokenize(f"""${{{{ foo {op_str} "bar" }}}}""", START)))
예제 #10
0
def test_func_nested_calls() -> None:
    assert [
        Call(
            Pos(0, 4, FNAME),
            Pos(0, 16, FNAME),
            FUNCTIONS["len"],
            [
                Call(
                    Pos(0, 8, FNAME),
                    Pos(0, 16, FNAME),
                    FUNCTIONS["keys"],
                    [Lookup(Pos(0, 13, FNAME), Pos(0, 16, FNAME), "abc", [])],
                    [],
                )
            ],
            [],
        )
    ] == PARSER.parse(list(tokenize("${{ len(keys(abc)) }}", START)))
예제 #11
0
def test_dict() -> None:
    assert [
        DictMaker(
            start=Pos(0, 5, FNAME),
            end=Pos(0, 26, FNAME),
            items=[
                (
                    Literal(
                        start=Pos(0, 5, FNAME),
                        end=Pos(0, 6, FNAME),
                        val=1,
                    ),
                    Literal(
                        start=Pos(0, 8, FNAME),
                        end=Pos(0, 11, FNAME),
                        val="2",
                    ),
                ),
                (
                    Literal(
                        start=Pos(0, 13, FNAME),
                        end=Pos(0, 17, FNAME),
                        val=True,
                    ),
                    Call(
                        start=Pos(0, 19, FNAME),
                        end=Pos(0, 26, FNAME),
                        func=FUNCTIONS["len"],
                        args=[
                            Lookup(
                                start=Pos(0, 23, FNAME),
                                end=Pos(0, 26, FNAME),
                                root="ctx",
                                trailer=[],
                            )
                        ],
                        trailer=[],
                    ),
                ),
            ],
        )
    ] == PARSER.parse(list(tokenize("${{ {1: '2', True: len(ctx)} }}", START)))
예제 #12
0
def test_func_call_arg_lookup() -> None:
    assert [
        Call(
            Pos(0, 4, FNAME),
            Pos(0, 30, FNAME),
            FUNCTIONS["len"],
            [
                Lookup(
                    Pos(0, 8, FNAME),
                    Pos(0, 30, FNAME),
                    "images",
                    [
                        AttrGetter(Pos(0, 15, FNAME), Pos(0, 19, FNAME), "name"),
                        AttrGetter(Pos(0, 20, FNAME), Pos(0, 30, FNAME), "build_args"),
                    ],
                )
            ],
            [],
        )
    ] == PARSER.parse(list(tokenize("${{ len(images.name.build_args) }}", START)))
예제 #13
0
def test_corner_case2() -> None:
    s = dedent(
        """\
            bash -c 'cd ${{ volumes.project.mount }} &&
              python -u ${{ volumes.code.mount }}/train.py
                --data ${{ volumes.data.mount }}'
        """
    )
    assert [
        Text(Pos(0, 0, FNAME), Pos(0, 12, FNAME), "bash -c 'cd "),
        Lookup(
            Pos(0, 16, FNAME),
            Pos(0, 37, FNAME),
            "volumes",
            [
                AttrGetter(Pos(0, 24, FNAME), Pos(0, 31, FNAME), "project"),
                AttrGetter(Pos(0, 32, FNAME), Pos(0, 37, FNAME), "mount"),
            ],
        ),
        Text(Pos(0, 40, FNAME), Pos(1, 12, FNAME), " &&\n  python -u "),
        Lookup(
            Pos(1, 16, FNAME),
            Pos(1, 34, FNAME),
            "volumes",
            [
                AttrGetter(Pos(1, 24, FNAME), Pos(1, 28, FNAME), "code"),
                AttrGetter(Pos(1, 29, FNAME), Pos(1, 34, FNAME), "mount"),
            ],
        ),
        Text(Pos(1, 37, FNAME), Pos(2, 11, FNAME), "/train.py\n    --data "),
        Lookup(
            Pos(2, 15, FNAME),
            Pos(2, 33, FNAME),
            "volumes",
            [
                AttrGetter(Pos(2, 23, FNAME), Pos(2, 27, FNAME), "data"),
                AttrGetter(Pos(2, 28, FNAME), Pos(2, 33, FNAME), "mount"),
            ],
        ),
        Text(Pos(2, 36, FNAME), Pos(3, 0, FNAME), "'\n"),
    ] == PARSER.parse(list(tokenize(s, START)))
예제 #14
0
def test_dict_short() -> None:
    assert [
        DictMaker(
            start=Pos(0, 5, FNAME),
            end=Pos(0, 11, FNAME),
            items=[
                (
                    Literal(
                        start=Pos(0, 5, FNAME),
                        end=Pos(0, 6, FNAME),
                        val=1,
                    ),
                    Literal(
                        start=Pos(0, 8, FNAME),
                        end=Pos(0, 11, FNAME),
                        val="2",
                    ),
                ),
            ],
        )
    ] == PARSER.parse(list(tokenize("${{ {1: '2'} }}", START)))
예제 #15
0
def test_corner_case1() -> None:
    s = dedent(
        """\
            jupyter notebook
              --no-browser
              --ip=0.0.0.0
              --allow-root
              --NotebookApp.token=
              --notebook-dir=${{ volumes.notebooks.mount }}
        """
    )
    assert (
        [
            Text(
                Pos(0, 0, FNAME),
                Pos(5, 17, FNAME),
                dedent(
                    """\
                            jupyter notebook
                              --no-browser
                              --ip=0.0.0.0
                              --allow-root
                              --NotebookApp.token=
                              --notebook-dir="""
                ),
            ),
            Lookup(
                Pos(5, 21, FNAME),
                Pos(5, 44, FNAME),
                "volumes",
                [
                    AttrGetter(Pos(5, 29, FNAME), Pos(5, 38, FNAME), "notebooks"),
                    AttrGetter(Pos(5, 39, FNAME), Pos(5, 44, FNAME), "mount"),
                ],
            ),
            Text(Pos(5, 47, FNAME), Pos(6, 0, FNAME), "\n"),
        ]
        == PARSER.parse(list(tokenize(s, START)))
    )
예제 #16
0
def test_list() -> None:
    assert [
        ListMaker(
            start=Pos(0, 4, FNAME),
            end=Pos(0, 25, FNAME),
            items=[
                Literal(
                    start=Pos(0, 4, FNAME),
                    end=Pos(0, 5, FNAME),
                    val=1,
                ),
                Literal(
                    start=Pos(0, 7, FNAME),
                    end=Pos(0, 10, FNAME),
                    val="2",
                ),
                Literal(
                    start=Pos(0, 12, FNAME),
                    end=Pos(0, 16, FNAME),
                    val=True,
                ),
                Call(
                    start=Pos(0, 18, FNAME),
                    end=Pos(0, 25, FNAME),
                    func=FUNCTIONS["len"],
                    args=[
                        Lookup(
                            start=Pos(0, 22, FNAME),
                            end=Pos(0, 25, FNAME),
                            root="ctx",
                            trailer=[],
                        )
                    ],
                    trailer=[],
                ),
            ],
        )
    ] == PARSER.parse(list(tokenize("${{[1, '2', True, len(ctx)]}}", START)))
예제 #17
0
def test_tmpl_ok6() -> None:
    assert [Lookup(Pos(0, 3, FNAME), Pos(0, 7, FNAME), "name", [])] == PARSER.parse(
        list(tokenize("$[[name]]", START))
    )
예제 #18
0
def test_tmpl_literal_oct2() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 11, FNAME), 0o1234)] == PARSER.parse(
        list(tokenize("${{ 0O12_34 }}", START))
    )
예제 #19
0
def test_tmpl_literal_bin2() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 11, FNAME), 0b0110)] == PARSER.parse(
        list(tokenize("${{ 0B01_10 }}", START))
    )
예제 #20
0
def test_text_with_dot() -> None:
    assert [Text(Pos(0, 0, FNAME), Pos(0, 11, FNAME), "some . text")] == PARSER.parse(
        list(tokenize("some . text", START))
    )
예제 #21
0
def test_tmpl_literal_bool1() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 8, FNAME), True)] == PARSER.parse(
        list(tokenize("${{ True }}", START))
    )
예제 #22
0
def test_tmpl_literal_bool2() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 9, FNAME), False)] == PARSER.parse(
        list(tokenize("${{ False }}", START))
    )
예제 #23
0
def test_tmpl_literal_str1() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 9, FNAME), "str")] == PARSER.parse(
        list(tokenize("${{ 'str' }}", START))
    )
예제 #24
0
def test_tmpl_literal_str2() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 13, FNAME), "abc\tdef")] == PARSER.parse(
        list(tokenize("${{ 'abc\tdef' }}", START))
    )
예제 #25
0
def test_tmpl_ok1() -> None:
    assert [Lookup(Pos(0, 4, FNAME), Pos(0, 8, FNAME), "name", [])] == PARSER.parse(
        list(tokenize("${{ name }}", START))
    )
예제 #26
0
def test_tmpl_literal_hex2() -> None:
    assert [Literal(Pos(0, 4, FNAME), Pos(0, 11, FNAME), 0x12AB)] == PARSER.parse(
        list(tokenize("${{ 0X12_ab }}", START))
    )
예제 #27
0
def test_text_ok() -> None:
    assert [Text(Pos(0, 0, FNAME), Pos(0, 9, FNAME), "some text")] == PARSER.parse(
        list(tokenize("some text", START))
    )
예제 #28
0
def test_tmpl_false2() -> None:
    with pytest.raises(NoParseError):
        PARSER.parse(list(tokenize("${{ name sub  param", START)))
예제 #29
0
def test_tmpl_false4() -> None:
    with pytest.raises(NoParseError):
        PARSER.parse(list(tokenize("$[[", START)))
예제 #30
0
def test_func_call_empty() -> None:
    assert [
        Call(Pos(0, 4, FNAME), Pos(0, 11, FNAME), FUNCTIONS["nothing"], [], [])
    ] == PARSER.parse(list(tokenize("${{ nothing() }}", START)))