proper-cli


Nameproper-cli JSON
Version 1.4.1 PyPI version JSON
download
home_pagehttps://github.com/jpsca/proper-cli
SummaryReplace your HTML templates with Python server-Side components
upload_time2024-03-31 18:33:48
maintainerNone
docs_urlNone
authorJuan-Pablo Scaletti
requires_python<4.0,>=3.9
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Proper CLI

Proper CLI is a Python library for creating composable, nestable, and ridiculously good looking command-line-**user**-interfaces from simple classes.

![proper_cli output](https://raw.githubusercontent.com/jpsca/proper-cli/main/output.png)

## Features

- Made for interfacing **with humans**.
- Arbitrary nesting and composition of commands.
- Automatic help page generation
- No need to redeclare paramaters and options with decorators, just write Python methods
- The help of a command is its docstring, why make it more complex?


## Usage

Declare a class that inherits from `proper_cli.Cli`. Every method/attribute that does not starts with an underscore will be a command.

```python
from proper_cli import Cli

class Manage(Cli):
    def first(self, arg1, arg2=3):
        pass

    def second(self):
        pass

    def _not_a_command(self):
        pass
```

Then, instance that class and call it.

```python
# run.py
cli = Manage()

if __name__ == "__main__":
    cli()
```

The class dosctring will be printed at the beginning of the help page.

The arguments can be then passed by position:

```bash
python run.py first foo bar
```

or by name:

```bash
python run.py first -arg1 foo -arg2 bar
```

To pass a `True` use the name without a value, for a `False`, prepend the name of the argument with `no-`:

```bash
python run.py first -arg1 -no-arg2
```


### Subgroups

If an attribute is a subclass of `proper_cli.Cli`, it will be a subgroup:

```python
from proper_cli import Cli

class DBSub(Cli):
    def migrate(self):
        pass

class Manage(Cli):
    # A subgroup
    db = DBSub  # NOT `DBSub()`
```

### Context

You can pass any named argument as context to be used by your commands. This will be stored at the `_env` attribute.

Example:

```python
>>> cli = Manage(lorem="ipsum")
>>> print(cli._env)
{"lorem": "ipsum"}
```


## An example

The image at the top was autogenerated by running this example:

```python
# example.py
from proper_cli import Cli


class DBCli(Cli):
    """Database-related commands
    """

    def migrate(self, message):
        """Autogenerate a new revision file.

        This is an alias for "revision --autogenerate".

        Arguments:

        - message: Revision message

        """
        pass

    def branches(self):
        """Show all branches."""
        pass


class MyCli(Cli):
    """Welcome to Proper CLI 3
    """

    def new(self, path, quiet=False):
        """Creates a new Proper application at `path`.

        Arguments:

        - path: Where to create the new application.
        - quiet [False]: Supress all output.
        """
        pass

    def hello(count, name):
        """Simple program that greets NAME for a total of COUNT times."""
        pass

    # A subgroup!
    db = DBCli


cli = MyCli()

if __name__ == "__main__":
    cli()

```


## Coloring the Output

Whenever you output text, you can surround the text with tags to color its output (thanks to https://github.com/sdispater/pastel).
This is automatically enabled for the docstrings, but you can also have it by using `proper_cli.echo()`
as a drop-in replacement of `print()`.

```python
# green text
echo("<fg=green>foo</fg=green>")

# black text on a cyan background
echo("<fg=black;bg=cyan>foo</>")

# bold text on a yellow background
echo("<bg=yellow;options=bold>foo</>")
```

Available foreground and background colors are: black, red, green, yellow, blue, magenta, cyan and white.

The available options are: bold, underscore, blink, reverse and conceal.

The closing tag can be replaced by `</>`, which revokes all formatting options established by the last opened tag.


## Custom styles

These four styles are available by default:

```python
# green text
echo("<info>foo</info>")

# yellow text
echo("<comment>foo</comment>")

# black text on a cyan background
echo("<question>foo</question>")

# white text on a red background
echo("<error>foo</error>")
```

It is possible to define your own styles using the `proper_cli.add_style()` method:

```python
add_style("fire", fg="red", bg="yellow", options=["bold", "blink"])
echo("<fire>foo</fire>")
```


## Helpers

Beyond the CLI builder, proper_cli also includes some commonly-used helper functions

### `confirm(question, default=False, yes_choices=YES_CHOICES, no_choices=NO_CHOICES)`

Ask a yes/no question via and return their answer.

### `ask(question, default=None, alternatives=None)`

Ask a question via input() and return their answer.


## FAQ

### Why don't just use optparse or argparse?

I find it too verbose.

### Why don't just use click?

Are you kidding? Because this looks better and is easier to use and understand.

### Why don't just use...?

Because this library fits better my mental model. I hope it matches yours as well.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jpsca/proper-cli",
    "name": "proper-cli",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.9",
    "maintainer_email": null,
    "keywords": null,
    "author": "Juan-Pablo Scaletti",
    "author_email": "juanpablo@jpscaletti.com",
    "download_url": "https://files.pythonhosted.org/packages/b8/39/018909db196921e8f3f944bf4d938f694236e1914d38256c78430563d384/proper_cli-1.4.1.tar.gz",
    "platform": null,
    "description": "# Proper CLI\n\nProper CLI is a Python library for creating composable, nestable, and ridiculously good looking command-line-**user**-interfaces from simple classes.\n\n![proper_cli output](https://raw.githubusercontent.com/jpsca/proper-cli/main/output.png)\n\n## Features\n\n- Made for interfacing **with humans**.\n- Arbitrary nesting and composition of commands.\n- Automatic help page generation\n- No need to redeclare paramaters and options with decorators, just write Python methods\n- The help of a command is its docstring, why make it more complex?\n\n\n## Usage\n\nDeclare a class that inherits from `proper_cli.Cli`. Every method/attribute that does not starts with an underscore will be a command.\n\n```python\nfrom proper_cli import Cli\n\nclass Manage(Cli):\n    def first(self, arg1, arg2=3):\n        pass\n\n    def second(self):\n        pass\n\n    def _not_a_command(self):\n        pass\n```\n\nThen, instance that class and call it.\n\n```python\n# run.py\ncli = Manage()\n\nif __name__ == \"__main__\":\n    cli()\n```\n\nThe class dosctring will be printed at the beginning of the help page.\n\nThe arguments can be then passed by position:\n\n```bash\npython run.py first foo bar\n```\n\nor by name:\n\n```bash\npython run.py first -arg1 foo -arg2 bar\n```\n\nTo pass a `True` use the name without a value, for a `False`, prepend the name of the argument with `no-`:\n\n```bash\npython run.py first -arg1 -no-arg2\n```\n\n\n### Subgroups\n\nIf an attribute is a subclass of `proper_cli.Cli`, it will be a subgroup:\n\n```python\nfrom proper_cli import Cli\n\nclass DBSub(Cli):\n    def migrate(self):\n        pass\n\nclass Manage(Cli):\n    # A subgroup\n    db = DBSub  # NOT `DBSub()`\n```\n\n### Context\n\nYou can pass any named argument as context to be used by your commands. This will be stored at the `_env` attribute.\n\nExample:\n\n```python\n>>> cli = Manage(lorem=\"ipsum\")\n>>> print(cli._env)\n{\"lorem\": \"ipsum\"}\n```\n\n\n## An example\n\nThe image at the top was autogenerated by running this example:\n\n```python\n# example.py\nfrom proper_cli import Cli\n\n\nclass DBCli(Cli):\n    \"\"\"Database-related commands\n    \"\"\"\n\n    def migrate(self, message):\n        \"\"\"Autogenerate a new revision file.\n\n        This is an alias for \"revision --autogenerate\".\n\n        Arguments:\n\n        - message: Revision message\n\n        \"\"\"\n        pass\n\n    def branches(self):\n        \"\"\"Show all branches.\"\"\"\n        pass\n\n\nclass MyCli(Cli):\n    \"\"\"Welcome to Proper CLI 3\n    \"\"\"\n\n    def new(self, path, quiet=False):\n        \"\"\"Creates a new Proper application at `path`.\n\n        Arguments:\n\n        - path: Where to create the new application.\n        - quiet [False]: Supress all output.\n        \"\"\"\n        pass\n\n    def hello(count, name):\n        \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n        pass\n\n    # A subgroup!\n    db = DBCli\n\n\ncli = MyCli()\n\nif __name__ == \"__main__\":\n    cli()\n\n```\n\n\n## Coloring the Output\n\nWhenever you output text, you can surround the text with tags to color its output (thanks to https://github.com/sdispater/pastel).\nThis is automatically enabled for the docstrings, but you can also have it by using `proper_cli.echo()`\nas a drop-in replacement of `print()`.\n\n```python\n# green text\necho(\"<fg=green>foo</fg=green>\")\n\n# black text on a cyan background\necho(\"<fg=black;bg=cyan>foo</>\")\n\n# bold text on a yellow background\necho(\"<bg=yellow;options=bold>foo</>\")\n```\n\nAvailable foreground and background colors are: black, red, green, yellow, blue, magenta, cyan and white.\n\nThe available options are: bold, underscore, blink, reverse and conceal.\n\nThe closing tag can be replaced by `</>`, which revokes all formatting options established by the last opened tag.\n\n\n## Custom styles\n\nThese four styles are available by default:\n\n```python\n# green text\necho(\"<info>foo</info>\")\n\n# yellow text\necho(\"<comment>foo</comment>\")\n\n# black text on a cyan background\necho(\"<question>foo</question>\")\n\n# white text on a red background\necho(\"<error>foo</error>\")\n```\n\nIt is possible to define your own styles using the `proper_cli.add_style()` method:\n\n```python\nadd_style(\"fire\", fg=\"red\", bg=\"yellow\", options=[\"bold\", \"blink\"])\necho(\"<fire>foo</fire>\")\n```\n\n\n## Helpers\n\nBeyond the CLI builder, proper_cli also includes some commonly-used helper functions\n\n### `confirm(question, default=False, yes_choices=YES_CHOICES, no_choices=NO_CHOICES)`\n\nAsk a yes/no question via and return their answer.\n\n### `ask(question, default=None, alternatives=None)`\n\nAsk a question via input() and return their answer.\n\n\n## FAQ\n\n### Why don't just use optparse or argparse?\n\nI find it too verbose.\n\n### Why don't just use click?\n\nAre you kidding? Because this looks better and is easier to use and understand.\n\n### Why don't just use...?\n\nBecause this library fits better my mental model. I hope it matches yours as well.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Replace your HTML templates with Python server-Side components",
    "version": "1.4.1",
    "project_urls": {
        "Homepage": "https://github.com/jpsca/proper-cli",
        "Repository": "https://github.com/jpsca/proper-cli"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e588c338d55e4813c3d5427e87800f6067765436872908fc05a18683aca563aa",
                "md5": "efd667c818131a775e559bc705b7ad7b",
                "sha256": "82ba74f7b0b756ce5e48a3357d1e1ca8fc9c44bfea956f587eeecc6a8ebb37d1"
            },
            "downloads": -1,
            "filename": "proper_cli-1.4.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "efd667c818131a775e559bc705b7ad7b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.9",
            "size": 13640,
            "upload_time": "2024-03-31T18:33:47",
            "upload_time_iso_8601": "2024-03-31T18:33:47.774908Z",
            "url": "https://files.pythonhosted.org/packages/e5/88/c338d55e4813c3d5427e87800f6067765436872908fc05a18683aca563aa/proper_cli-1.4.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b839018909db196921e8f3f944bf4d938f694236e1914d38256c78430563d384",
                "md5": "a424b14a0f1a5f2818fd03283f2b2440",
                "sha256": "33317610f73a6f3919bd0d31b33753067fbf18f8ae11368a0cd729122d12ba07"
            },
            "downloads": -1,
            "filename": "proper_cli-1.4.1.tar.gz",
            "has_sig": false,
            "md5_digest": "a424b14a0f1a5f2818fd03283f2b2440",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.9",
            "size": 12882,
            "upload_time": "2024-03-31T18:33:48",
            "upload_time_iso_8601": "2024-03-31T18:33:48.935740Z",
            "url": "https://files.pythonhosted.org/packages/b8/39/018909db196921e8f3f944bf4d938f694236e1914d38256c78430563d384/proper_cli-1.4.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-31 18:33:48",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jpsca",
    "github_project": "proper-cli",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "proper-cli"
}
        
Elapsed time: 0.21487s