Example #1
0
def test_cli_run_with_various_parameter_kinds_in_callback() -> None:
    """CLI arguments should properly be bound to callback params.

    Tested parameter kinds:
    - positional only
    - var positional
    - keyword only
    - var keyword
    """
    def callback(a: int, *b: int, c: int, **d: int) -> t.Any:
        return a, b, c, d

    cli = make_cli(
        params=[
            Param("a", ["-a"], parser=comb.One(int)),
            Param("b", ["-b"], parser=comb.Repeat(comb.One(int))),
            Param("c", ["-c"], parser=comb.One(int)),
            Param("d", ["-d"],
                  parser=comb.Repeat(
                      comb.And(comb.One(str), comb.One(int)),
                      then=dict,
                  )),
        ],
        callback=callback,
    )

    assert cli.run("-a 1 -b 2 -c 3 -d k 4".split()) == (1, (2, ), 3, {"k": 4})
    assert cli.run("-a 1 -c 2".split()) == (1, (), 2, {})
Example #2
0
def test_genbu_params_get_overwritten() -> None:
    """If multiple Params have the same dest, existing Param is overwritten."""
    def callback() -> None:
        """Does nothing."""

    foo1 = Param("foo", ["-a"])
    foo2 = Param("foo", ["-b"])

    cli = Genbu(callback, params=[foo1, foo2])
    params = cli.params
    assert len(params) == 1
    assert params[0] is foo2
Example #3
0
def test_cli_run_with_ambiguous_long_options() -> None:
    """Program should abort if long option prefix is ambiguous."""
    cli = make_cli(params=[
        Param("bar", ["--bar"], parser=comb.Emit(True)),
        Param("baz", ["--baz"], parser=comb.Emit(True)),
    ])

    for source in ["--b", "--ba"]:
        with pytest.raises(SystemExit):
            cli.run(source.split())
    cli.run(["--bar"])
    cli.run(["--baz"])
Example #4
0
def test_usage_with_custom_arg_descriptions() -> None:
    """usage(...) should use custom description instead of default one."""
    cli = Genbu(
        name="test-cli",
        description="Test Genbu",
        params=[
            Param("default", ["-a"], parser=comb.Repeat(comb.One(int))),
            Param(
                "custom",
                ["-b"],
                parser=comb.Repeat(comb.One(int)),
                arg_description="custom-arg-description",
            )
        ],
        callback=callback,
    )
    assert usage(cli) == """usage:  test-cli [options]
Example #5
0
def test_cli_run_with_missing_options() -> None:
    """Program should abort if there are missing arguments."""
    cli = make_cli(
        params=[
            Param("a", parser=comb.One(int)),
            Param("b", ["-b"], parser=comb.One(int)),
            Param("c", ["--c"], parser=comb.One(int)),
        ],
        callback=lambda a, b, c: (a, b, c),
    )
    for source in [
            "-b 1 --c 2",
            "1 --c 2",
            "1 -b 2",
    ]:
        with pytest.raises(SystemExit):
            cli.run(source.split())
    assert cli.run("1 -b 2 --c 3".split()) == (1, 2, 3)
Example #6
0
def test_cli_run_with_arguments() -> None:
    """Test with positional arguments."""
    cli = make_cli(
        params=[Param("numbers", parser=comb.Repeat(comb.One(float)))],
        callback=lambda numbers: sum(numbers)  # pylint: disable=W0108
    )
    assert cli.run([]) == 0
    assert cli.run(["1.5", "2"]) == 3.5
    assert cli.run(["0.45e-5"]) == 0.45e-5
Example #7
0
def test_cli_run_with_long_options_with_equals() -> None:
    """Test with long options with equals (e.g. --foo=bar)."""
    cli = make_cli(
        params=[Param("value", ["--value"], parser=comb.One(int))],
        callback=lambda value: value,
    )

    cases = [("--value=5", 5), ("--valu=6", 6), ("--val=7", 7)]
    for source, expected in cases:
        assert cli.run(source.split()) == expected
Example #8
0
def test_cli_run_without_arguments(argv: t.List[str]) -> None:
    """It should use sys.argv[1:]."""
    with pytest.MonkeyPatch.context() as mp:
        mp.setattr(sys, "argv", argv)
        cli = make_cli(
            params=[
                Param("arg", parser=comb.Repeat(comb.One(str), then=list)),
            ],
            callback=lambda arg: arg,
        )
        assert cli.run() == argv[1:]
Example #9
0
def test_cli_run_with_short_options() -> None:
    """Test with short options."""
    cli = make_cli(
        params=[
            Param(
                "x",
                ["-a", "-b", "-c"],
                parser=comb.One(int),
                aggregator=sum,
            ),
        ],
        callback=lambda x: x,
    )
    assert cli.run("-a4 -b 5 -c=6".split()) == 15
Example #10
0
def test_cli_run_with_long_options() -> None:
    """Test with long options."""
    cli = make_cli(
        params=[
            Param(
                "x",
                ["--foo", "--bar", "--baz"],
                parser=comb.One(float),
                aggregator=sum,
            ),
        ],
        callback=lambda x: x,
    )
    assert cli.run("--foo 1 --bar 2 --baz 3".split()) == 6
Example #11
0
def test_cli_run_with_stacked_options() -> None:
    """Test with stacked short options."""
    def callback(a: str = "", b: str = "", c: str = "") -> str:
        return a + b + c

    cli = make_cli(
        params=[
            Param("a", ["-a"], parser=comb.Emit("a")),
            Param("b", ["-b"], parser=comb.Emit("b")),
            Param("c", ["-c"], parser=comb.Emit("c")),
        ],
        callback=callback,
    )
    cases = [
        ("", ""),
        ("-a", "a"),
        ("-ab", "ab"),
        ("-ac", "ac"),
        ("-bc", "bc"),
        ("-abc", "abc"),
        ("-cba", "abc"),
    ]
    for source, expected in cases:
        assert cli.run(source.split()) == expected
Example #12
0
def test_usage_with_multiple_examples() -> None:
    """usage(...) should have properly indented example lines."""
    bar = Genbu(
        name="bar",
        description="Bar subcommand",
        callback=callback,
    )
    foo = Genbu(
        name="foo",
        description="Foo command.",
        params=[
            Param("help_", ["-?", "-h"], parser=comb.Emit(True)),
        ],
        callback=callback,
        subparsers=[bar],
    )
    assert usage(foo).startswith("""usage:  foo [options]
        foo <command> ...""")
Example #13
0
    def test_genbu_params_with_ellipsis(
        self,
        function: t.Callable[..., t.Any],
    ) -> None:
        """Params in params args should override inferred params."""
        inferred = infer_params(function)
        assert Genbu(function, params=["..."]).params == inferred

        cli = Genbu(function, params=[
            "...",
            Param("foo"),
        ])

        assert cli.params[0].optargs != inferred[0].optargs
        for actual, expected in zip(cli.params[1:], inferred[1:]):
            assert actual == expected
            assert actual.optargs == expected.optargs
            assert actual.parser == expected.parser
            assert actual.aggregator == expected.aggregator
            assert actual.description == expected.description
            assert actual.arg_description == expected.arg_description
Example #14
0
def test_usage_with_params() -> None:
    """usage(...) should contain description of options."""
    cli = Genbu(
        name="test-cli",
        description="Test Genbu.",
        callback=callback,
        params=[
            Param("foo", parser=comb.One(str)),
            Param("aaa", ["-a", "--aaa"],
                  comb.One(str),
                  description="Set aaa."),
            Param("ahh", ["--ahh"], comb.One(str), description="Set ahh."),
            Param("baa", ["-b", "--baa"],
                  comb.One(str),
                  description="Set baa."),
            Param("bar", ["--bar"], comb.One(str)),
            Param("baz", ["--baz"], comb.One(str)),
        ],
    )
    assert usage(cli) == """usage:  test-cli [options] <foo:str>
Example #15
0
import sys
from genbu import Genbu, Param, combinators as comb, infer_parser, usage


def hello(*names: str, greeting: str = "Hello") -> str:
    """Say hello."""
    if not names:
        names = ("stranger",)
    return "{}, {}!".format(greeting, ", ".join(names))


cli = Genbu(
    hello,
    params=[
        Param("greeting", ["-g", "--greeting"], comb.One(str)),
        Param("names", parser=infer_parser(tuple[str, ...])),
        Param(
            "help_",
            ["-?", "-h", "--help"],
            comb.Emit(True),
            aggregator=lambda _: sys.exit(usage(cli))
        ),
    ],
)

if __name__ == "__main__":
    print(cli.run())
Example #16
0
import sys
from genbu import Genbu, Param, combinators as comb, usage


def ellipsis(n: int) -> str:
    return n * "*"


cli = Genbu(ellipsis,
            params=[
                "...",
                Param(
                    dest="_",
                    optargs=["-?", "-h", "--help"],
                    parser=comb.Emit(True),
                    aggregator=lambda _: sys.exit(usage(cli)),
                ),
            ])

if __name__ == "__main__":
    print(cli.run())
Example #17
0
from pathlib import Path
import sys

from genbu import Genbu, Param, combinators as comb, usage


def cat(path: Path) -> str:
    """Concatenate contents of path to stdout."""
    return path.read_text()


cli = Genbu(
    cat,
    params=[
        Param("path", ["-p", "--path"], comb.One(Path)),
        Param(
            "help_",
            ["-?", "-h", "--help"],
            comb.Emit(True),
            aggregator=lambda _: sys.exit(usage(cli)),
        ),
    ],
)

if __name__ == "__main__":
    try:
        print(cli.run())
    except Exception as exc:
        name = " ".join(cli.complete_name())
        print(f"{name}: {exc}\nTry '{name} -h' for more information.")
Example #18
0
    name = " ".join(cli.complete_name()) or "cli"
    footer = f"Try '{name} -h' for more information."
    _usage = usage(cli, "Genbu CLI example with subcommands.", footer)
    if error:
        sys.exit(_usage)
    print(_usage)
    sys.exit(0)


cli = Genbu(
    name=sys.argv[0],
    description="router example",
    params=[
        Param(
            "help",
            ["-h", "--help"],
            parser=comb.Emit(True),
            aggregator=lambda _: show_usage(cli),
        ),
    ],
    subparsers=[
        add.cli, cat.cli, echo.cli, ellipsis.cli, hello.cli, simple.cli,
    ],
    callback=lambda: show_usage(cli),
    error_handler=lambda cli, exc: show_usage(cli, error=True),
)


if __name__ == "__main__":
    try:
        print(cli.run())
    except Exception as exc:
Example #19
0
"""Add items."""

import sys

from genbu import Genbu, Param, combinators as comb, usage


def add(*args: float) -> float:
    """Add items."""
    return sum(args)


cli = Genbu(
    add,
    params=[
        Param("args", parser=comb.Repeat(comb.One(float))),
        Param(
            "_",
            ["-?", "-h", "-H"],
            description="Show help message",
            parser=comb.Emit(True),
            aggregator=lambda _: sys.exit(usage(cli)),
        ),
    ],
)

if __name__ == "__main__":
    print(cli.run())
Example #20
0
import sys
from genbu import Genbu, Param, combinators as comb, usage

cli = Genbu(
    lambda: print("Hello, world!"),
    params=[
        Param("_", ["-?", "-h", "--help"],
              parser=comb.Emit(True),
              aggregator=lambda _: sys.exit(usage(cli))),
    ],
)

if __name__ == "__main__":
    cli.run()
Example #21
0
def test_param_with_invalid_option(dest: str, optargs: t.List[str]) -> None:
    """Param should raise InvalidOption if option dest has = or whitespace."""
    with pytest.raises(InvalidOption):
        Param(dest=dest, optargs=optargs)
    assert Param(dest=dest)