# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['piou', 'piou.formatter', 'piou.test']

package_data = \
{'': ['*']}

install_requires = \
['rich>=10.11.0,<13.0']

setup_kwargs = {
    'name': 'piou',
    'version': '0.9.6',
    'description': 'A CLI toolkit',
    'long_description': '[<img src="https://github.com/Andarius/piou/raw/dev/docs/piou.jpg" width="250"/>](docs/piou.png)\n\n# Piou\n\n[![Python versions](https://img.shields.io/pypi/pyversions/piou)](https://pypi.python.org/pypi/piou)\n[![Latest PyPI version](https://img.shields.io/pypi/v/piou?logo=pypi)](https://pypi.python.org/pypi/piou)\n[![CircleCI](https://circleci.com/gh/Andarius/piou/tree/master.svg?style=shield)](https://app.circleci.com/pipelines/github/Andarius/piou?branch=master)\n[![Latest conda-forge version](https://img.shields.io/conda/vn/conda-forge/piou?logo=conda-forge)](https://anaconda.org/conda-forge/piou)\n\nA CLI tool to build beautiful command-line interfaces with type validation.\n\nIt is as simple as\n\n```python\nfrom piou import Cli, Option\n\ncli = Cli(description=\'A CLI tool\')\n\n\n@cli.command(cmd=\'foo\', help=\'Run foo command\')\ndef foo_main(\n        bar: int = Option(..., help=\'Bar positional argument (required)\'),\n        baz: str = Option(..., \'-b\', \'--baz\', help=\'Baz keyword argument (required)\'),\n        foo: str = Option(None, \'--foo\', help=\'Foo keyword argument\'),\n):\n    """\n    A longer description on what the function is doing.\n    You can run it with:\n    ```bash\n     poetry run python -m piou.test.simple foo 1 -b baz\n    ```\n    And you are good to go!\n    """\n    pass\n\n\nif __name__ == \'__main__\':\n    cli.run()\n```\n\nThe output will look like this:\n\n- `python -m piou.test.simple -h`\n\n![example](https://github.com/Andarius/piou/raw/master/docs/simple-output.png)\n\n- `python -m piou.test.simple foo -h`\n\n![example](https://github.com/Andarius/piou/raw/master/docs/simple-output-foo.png)\n\n# Why ?\n\nI could not find a library that provided:\n\n- the same developer experience than [FastAPI](https://fastapi.tiangolo.com/)\n- customization of the interface (to build a CLI similar to the one of [Poetry](https://python-poetry.org/))\n- type validation / casting\n\n[Typer](https://github.com/tiangolo/typer) is the closest alternative in terms of experience but lacks the possibility\nto format the output is a custom way using external libraries (like [Rich](https://github.com/Textualize/rich)).\n\n**Piou** provides all these possibilities and lets you define your own [Formatter](#custom-formatter).\n\n# Install\n\nYou can install `piou` with either:\n\n- `pip install piou`\n- `conda install piou -c conda-forge`\n\n# Features\n\n## Commands\n\n```python\nfrom piou import Cli, Option\n\ncli = Cli(description=\'A CLI tool\')\n\n\n@cli.command(cmd=\'foo\',\n             help=\'Run foo command\')\ndef foo_main(\n        foo1: int = Option(..., help=\'Foo arguments\'),\n        foo2: str = Option(..., \'-f\', \'--foo2\', help=\'Foo2 arguments\'),\n        foo3: str = Option(None, \'-g\', \'--foo3\', help=\'Foo3 arguments\'),\n):\n    pass\n\n\n@cli.command(cmd=\'bar\',\n             help=\'Run bar command\')\ndef bar_main(\n        foo1: int = Option(..., help=\'Foo arguments\'),\n        foo2: str = Option(..., \'-f\', \'--foo2\', help=\'Foo2 arguments\'),\n        foo3: str = Option(None, \'-g\', \'--foo3\', help=\'Foo3 arguments\'),\n):\n    pass\n\n\nif __name__ == \'__main__\':\n    cli.run()\n```\n\nIn this case, `foo1` is a positional argument while `foo2` and `foo3` are keyword arguments.\n\nYou can optionally specify global options that will be passed to all commands:\n\n```python\ncli = Cli(description=\'A CLI tool\')\n\ncli.add_option(\'-q\', \'--quiet\', help=\'Do not output any message\')\n```\n\nThe **description** can also be extracted from the function docstring. Both functions here return the same description.\n\n```python\n@cli.command(cmd=\'bar\', description=\'Run foo command\')\ndef bar_main():\n    pass\n\n\n@cli.command(cmd=\'bar2\')\ndef bar_2_main():\n    """\n    Run foo command\n    """\n    pass\n```\n\nA command can also be asynchronous, it will be run automatically using `asyncio.run`.\n\n```python\n@cli.command(cmd=\'bar\', help=\'Run foo command\')\nasync def bar_main():\n    pass\n```\n\n## Command Groups / Sub-commands\n\nYou can group commands into sub-commands:\n\n```python\nfrom piou import Cli, Option\n\ncli = Cli(description=\'A CLI tool\')\n\n\n@cli.command(cmd=\'foo\', help=\'Run foo command\')\ndef foo_main():\n    pass\n\n\nsub_cmd = cli.add_sub_parser(cmd=\'sub\', help=\'A sub command\')\nsub_cmd.add_option(\'--test\', help=\'Test mode\')\n\n\n@sub_cmd.command(cmd=\'bar\', help=\'Run bar command\')\ndef sub_bar_main(**kwargs):\n    pass\n\n\n@sub_cmd.command(cmd=\'foo\', help=\'Run foo command\')\ndef sub_foo_main(\n        test: bool,\n        foo1: int = Option(..., help=\'Foo argument\'),\n        foo2: str = Option(..., \'-f\', \'--foo2\', help=\'Foo2 argument\'),\n):\n    pass\n\n\nif __name__ == \'__main__\':\n    cli.run()\n```\n\nSo when running `python run.py sub -h` it will output the following:\n\n![example](https://github.com/Andarius/piou/raw/master/docs/sub-cmd-output.png)\n\n## Options processor\n\nSometimes, you want to run a function using the global arguments before running the actual command (for instance\ninitialize a logger based on the `verbose` level).\n\nTo do so, you use `set_options_processor` that will receive all the current global options of the CLI.\n\n```python\nfrom piou import Cli\n\ncli = Cli(description=\'A CLI tool\')\n\ncli.add_option(\'--verbose\', help=\'Increase verbosity\')\n\n\ndef processor(verbose: bool):\n    print(f\'Processing {verbose=}\')\n\n\ncli.set_options_processor(processor)\n```\n\nYou can also use the decorator syntax:\n\n```python\nfrom piou import Cli, Option\n\ncli = Cli(description=\'A CLI tool\')\n\n\n@cli.processor()\ndef processor(verbose: bool = Option(False, \'--verbose\', help=\'Increase verbosity\')):\n    print(f\'Processing {verbose=}\')\n```\n\nBy default, when a processor is set, the global arguments will not be passed downstream.\nIf you still want them to be passed to the functions by setting\n\n```python\ncli = Cli(description=\'A CLI tool\', propagate_options=True)\n```\n\nor in the case of a **sub-command**\n\n```python\ncli.add_sub_parser(cmd=\'sub\', help=\'A sub command\', propagate_options=True)\n```\n\n## Derived Options\n\nSometimes, you want to reuse the options in multiple command and group them into a single output to pass to\nthe command. For instance, you might want to group a connection string parameter to connect to a database. Here is a\nfull example:\n\n```python\nfrom piou import Cli, Option, Derived\nimport psycopg2\n\ncli = Cli(description=\'A CLI tool\')\n\n\ndef get_pg_conn(\n        pg_user: str = Option(\'postgres\', \'--pg-user\'),\n        pg_pwd: str = Option(\'postgres\', \'--pg-pwd\'),\n        pg_host: str = Option(\'localhost\', \'--pg-host\'),\n        pg_port: int = Option(5432, \'--pg-port\'),\n        pg_db: str = Option(\'postgres\', \'--pg-db\')\n\n):\n    conn = psycopg2.connect(dbname=pg_db, user=pg_user, password=pg_pwd,\n                            host=pg_host, port=pg_port)\n    return conn\n\n\n@cli.command(help=\'Run foo command\')\ndef foo(pg_conn: str = Derived(get_pg_conn)):\n    ...\n\n\n@cli.command(help=\'Run bar command\')\ndef bar(pg_conn: str = Derived(get_pg_conn)):\n    ...\n```\n\n## On Command Run\n\nIf you want to get the command name and arguments information that are passed to it (in case of general purpose\ndebugging for instance), you can pass `on_cmd_run` to the CLI.\n\n```python\nfrom piou import Cli, Option, CommandMeta, Derived\n\n\ndef on_cmd_run(meta: CommandMeta):\n    pass\n\n\ncli = Cli(description=\'A CLI tool\',\n          on_cmd_run=on_cmd_run)\n\n\ndef processor(a: int = Option(1, \'-a\'),\n              b: int = Option(2, \'-b\')):\n    return a + b\n\n\n@cli.command()\ndef test(\n        value: int = Derived(processor),\n        bar: str = Option(None, \'--bar\')\n):\n    pass\n```\n\nIn this case, `meta` will be equal to:\n\n```python\nCommandMeta(cmd_name=\'test\',\n            fn_args={\'bar\': \'bar\', \'value\': 5},\n            cmd_args={\'a\': 3, \'b\': 2, \'bar\': \'bar\'})\n```\n\n## Help / Errors Formatter\n\nYou can customize the help and the different errors displayed by the CLI by passing a Formatter.\nThe default one is the **Rich formatter** based on the [Rich](https://github.com/Textualize/rich) package:\n\n- `cmd_color`: set the color of the command in the help\n- `option_color`: set the color of the positional / keyword arguments in the help\n- `show_default`: show the default values if the keyword arguments (if available)\n\nYou can create your own Formatter by subclassing the `Formatter` class (see\nthe [Rich formatter](https://github.com/Andarius/piou/blob/master/piou/formatter/rich_formatter.py)\nfor example).\n\n## Complete example\n\nYou can try a more complete example by running `python -m piou.test -h`\n\n## Moving from `argparse`\n\nIf you are migrating code from `argparse` to `piou` here are some differences:\n\n**choices**:\n`add_argument(\'--pick\', choices=[\'foo\', \'bar\'])` can be replaced by\n`pick: Literal[\'foo\', \'bar\'] = Option(None, \'--pick\')`.\n\nYou can also disable the case sensitivity by passing `Option(None, \'--pick\', case_sentitive=False)`\n\n**action=store_true**\n`add_argument(\'--verbose\', action=\'store_true\')` can be replaced by\n`verbose: bool = Option(False, \'--verbose\')`\n',
    'author': 'Julien Brayere',
    'author_email': 'julien.brayere@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/andarius/piou',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.9,<4.0',
}


setup(**setup_kwargs)
