Metadata-Version: 2.1
Name: clargs
Version: 0.5.1
Summary: Easily generate commandline apps from your functions, based on type hints
Author-email: Claude <pypi@claude.nl>
Project-URL: Homepage, https://github.com/reinhrst/clargs
Project-URL: Bug Tracker, https://github.com/reinhrst/clargs/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENCE.txt

# Clargs

The goal of the `clargs` package is to create commandline interfaces from function signatures.

- With a single line, an existing function is turned into a command line program
- However it also has the flexibility to be the command line interface of a finished product
- Explicit goal is **Don't Repeat Yourself**. All information is in a single spot (where you define the function)
- Pure python and no dependencies (except for running test)
- Support for `int`, `float`, `bool`, `pathlib.Path`, `list` and `typing.Literal` built-in (more coming)
- Support for flags (`--foo/--no-foo`)
- Automatic underscore-to-dash conversion (`foo_bar` becomes `--foo-bar`), and creation of short flags (`--foo-bar` and `-f` are both supported)
- Type of a parameter is set through [PEP 484][2]-style type hints
- Defaults are taken from the function signature
- Based on the built-in `argparse` module
- Function documentation creates command line arguments documentation


## Example
Check out the [list of examples][3] to see the package in action


A quick example (just to get you excited):
```python
import clargs


def count(
    singular: str,
    plural: str,
    maxitems: int = 10,
    *,
    shout: bool = False,
):
    """
    Counts from 1 to given number (default = 10)

    This text should not appear

    @param singular: The singular form of the thing to count
    @param plural: The plural form of the thing to count
    @param maxitems: The number to count to
    @param shout: If True, will convert all expressions to capitals
    """
    for i in range(maxitems):
        text = f"{i + 1} {singular if i == 0 else plural}"
        if shout:
            text = text.upper()
        print(text)


if __name__ == "__main__":
    clargs.create_parser_and_run(count)
```

```console
> python main.py --help
usage: main.py [-h] [--shout [SHOUT]] singular plural [maxitems]

Counts from 1 to given number (default = 10)

positional arguments:
  singular              The singular form of the thing to count
  plural                The plural form of the thing to count
  maxitems              The number to count to

options:
  -h, --help            show this help message and exit
  --shout [SHOUT], -s [SHOUT]
                        If True, will convert all expressions to capitals> python main.py bottle bottles
1 bottle
2 bottles
3 bottles
4 bottles
5 bottles
6 bottles
7 bottles
8 bottles
9 bottles
10 bottles
> python main.py bottle bottles 5 --shout=yes
1 BOTTLE
2 BOTTLES
3 BOTTLES
4 BOTTLES
5 BOTTLES
```

## Supported types

The type of the parameter (given through a type-hint) determines what the input is parsed at.
If no type-hint is given, `str` is assumed.

#### `str`, `int`, `float`, `pathlib.Path`

These types just call the constructor on the string (e.g. `python main.py --input-file /tmp/myfile.txt --repeat 5` will assign `pathlib.Path("/tmp/myfile.txt")` to `input_file` and `int("5")` to `repeat` (assuming a function signature like: `def run(*, input_file: pathlib.Path, repeat: int)`).

#### `bool`

Booleans need some special work internally (since `bool("False") == True`). Any parameter of type `bool` will accept `Yes`, `No`, `True` and `False` (case-insensitive) as values.
Booleans can also be made `Flag`s, see below under "Extra Types".

#### `typing.Literal["foo", "bar", "baz"]`

Using `typing.Literal` parameters can be made that can only have certain values.
The type of the parameters can be any of the types above

#### `list[X]` or `typing.Sequence[X]`

Lists of items is supported (for all pf the above types). For instance a signature of `def sum(*, terms: typing.List[float]) -> float` means you can use `python sum.py --terms 1.2 4 -5`

#### `typing.Optional[X]` and `None | X`

`typing.Optional` or a union with `None` is ignored, so this won't affect the command line signature.


### Extra Types

In addition to normal types, the `clargs` package defines some special types.

#### `clargs.Flag`

Is an alias for `bool` (should be recognised by static type-checkers).
Creates `--foo/--no-foo` parameter pair to control booleans


#### `clargs.Count`

Is an alias for `int` (should be recognised by static type-checkers).
Counts how often a parameter is present (mostly used in `--verbose --verbose --verbose` parameters)

### Custom Type

I hope to add types quickly in future versions.

In the meantime, any type not listed here will also work as long as an explicit conversion function is defined.

## Subparsers

Using subparsers it's possible to add multiple functions to your cli. See [an example here][5]


## Compare to other solutions

`clargs` is far from the first solutions. Before development I looked at some of the alternatives out there, and found them
- [`clize`][4] is an amazing product, however it's just getting started with PEP 484 typing support (and made some decisions in the past to use the type hints for other things, which feel limits flexibility now).
- [TODO]

[1]: https://docs.python.org/3/library/typing.html#typing.Annotated
[2]: https://peps.python.org/pep-0484/
[3]: examples/
[4]: https://github.com/epsy/clize
[5]: examples/4_parse_groups.py
