YadOpt - User's manual
Description: A layout example with a side menu that hides on mobile, just like the Pure website.

## YadOpt - Yet another docopt

## What's YadOpt?

YadOpt is a Python re-implementation of docopt and docopt-ng, a human-friendly command-line argument parser with type hinting and utility functions. YadOpt helps you create beautiful command-line interfaces, just like docopt and docopt-ng. However, YadOpt also supports (1) date type hinting, (2) conversion to dictionaries and named tuples, and (3) save and load functions.

The following is the typical usage of YadOpt:

    """
    Usage:
        train.py <config_path> [--epochs INT] [--model STR] [--lr FLT]
        train.py --help

    Train a neural network model.

    Arguments:
        config_path     Path to a config file.

    Training options:
        --epochs INT    The number of training epochs.   [default: 100]
        --model STR     Neural network model name.       [default: mlp]
        --lr FLT        Learning rate.                   [default: 1.0E-3]

    Other options:
        -h, --help      Show this help message and exit.
    """

    import yadopt

    if __name__ == "__main__":
        args = yadopt.parse(__doc__)
        print(args)

Please save the above code as `sample.py` and run it as follows:

    $ python3 sample.py config.toml --epochs 10 --model=cnn
    YadOptArgs(config_path=config.toml, epochs=10, model=cnn, lr=0.001, help=False)

In the above code, the parsed command-line arguments are stored in the `args` variable, and you can access each argument using dot notation, like `arg.config_path`. Also, the parsed command-line arguments are typed, in other words, the `args` variable satisfies the following assertions:

    assert isinstance(args.config_path, pathlib.Path)
    assert isinstance(args.epochs, int)
    assert isinstance(args.model, str)
    assert isinstance(args.lr, float)
    assert isinstance(args.help, bool)

More realistic examples can be found in the examples directory of the YadOpt repository.

## Installation

Please install from pip.

    $ pip install yadopt

## Usage

### Use the yadopt.parse function

The `yadopt.parse` function allows you to parse command-line arguments based on your docstring. The function is designed to parse `sys.argv` by default, but you can explicitly specify the argument vector by using the second argument of the function, just like as follows:

    # Parse sys.argv
    args = yadopt.parse(__doc__)

    # Parse the given argv.
    args = yadopt.parse(__doc__, argv)

### Use the yadopt.wrap function

YadOpt supports the decorator approach for command-line parsing by the decorator `@yadopt.wrap` which takes the same arguments as the function `yadopt.parse`.

    @yadopt.wrap(__doc__)
    def main(args: yadopt.YadOptArgs, real_arg: str):
        ...

    if __name__ == "__main__":
        main("real argument")

### How to type arguments and options

YadOpt provides two ways to type arguments and options: (1) type name postfix and (2) description head declaration.

(1) Type name postfix: Users can type arguments and options by adding a type name at the end of the arguments/options name, such as the following:

    Options:
        --opt1 FLT    Option of float type.
        --opt2 STR    Option of string type.

(2) Description head declaration: An alternative way to type arguments and options is to precede the description with the type name in parentheses.

    Options:
        --opt1 VAL1    (float) Option of float type.
        --opt2 VAL2    (str)   Option of string type.

The following is the list of available type names.

Data type in Python | Type name in YadOpt
--- | ---
`bool` | bool, BOOL, boolean, BOOLEAN
`int` | int, INT, integer, INTEGER
`float` | flt, FLT, float FLOAT
`str` | str, STR, string, STRING
`pathlib.Path` | path, PATH

### Dictionary and named tuple support

The returned value of `yadopt.parse` is an instance of YadOptArgs, a regular mutable Python class. However, sometimes a dictionary with the get accessor, or an immutable named tuple, may be preferable. In such cases, please try `yadopt.to_dict` or `yadopt.to_namedtuple` function.

    # Convert the returned value to a dictionary.
    args = yadopt.to_dict(yadopt.parse(__doc__))

    # Convert the returned value to a named tuple.
    args = yadopt.to_namedtuple(yadopt.parse(__doc__))

### Restore arguments from a JSON file

YadOpt has a function to save parsed argument instances as a JSON file and to restore the argument instances from the JSON files. These functions are probably useful when recalling the same arguments previously executed, for example, in machine learning code.

    # At first, create a parsed argument (i.e. YadOptArgs instance).
    args = yadopt.parse(__doc__)

    # Save the parsed arguments as a JSON file.
    yadopt.save("args.json", args)

    # Resotre parsed YadOptArgs instance from the JSON file.
    args_restored = yadopt.load("args.json")

    # The restored arguments are the same as the original.
    assert args == args_restored

The format of the JSON file is pretty straightforward — what the user types on the command line (i.e. argument vector) is stored in the `"argv"` key and the docstring is stored in the `"docstr"` key in the JSON file. If users want to write the JSON file manually, the author recommends making a JSON file using the `yadopt.save` function and modify the file.

## API reference

### Contents

- yadopt.parse
- yadopt.wrap
- yadopt.to_dict
- yadopt.to_namedtuple
- yadopt.save
- yadopt.load

### yadopt.parse

    def yadopt.parse(docstr: str,
                     argv: list[str] = sys.argv,
                     default_type: Callable = auto_type,
                     verbose: bool = False) -> YadOptArgs:

Parse docstring and return YadoptArgs instance.

#### Args

Name | Type | Default value | Description
--- | --- | --- | ---
`docstr` | `str` | - | A help message string that will be parsed to create an object of command line arguments. We recommend to write a help message in the docstring of your Python script and use `__doc__` here.
`argv` | `list[str]` | `sys.argv` | An argument vector to be parsed. YadOpt uses the command line arguments passed to your Python script, `sys.argv[1:]`, by default.
`default_type` | `Callable` | `auto_type` | A function that assigns types to arguments and option values. The default value `None` means using default function.
`verbose` | `bool` | `False` | Displays verbose messages that are useful for debugging.

#### Returns

Type | Description
--- | ---
`YadOptArgs` | The returned value is an instance of the `YadOptArgs` class that represents parsed command line arguments. The `YadOptArgs` class is a regular mutable Python class and users can access to parsed command line arguments by the dot notation. If you wish to convert `YadOptArgs` to dictionary type, please use `yadopt.to_dict` function. Likewise, if you prefer an immutable data type, please try `yadopt.to_namedtuple` function.

### yadopt.wrap

    def yadopt.wrap(*pargs: Any, **kwargs: Any) -> Callable:

Wrapper function for the command line parsing. This function actually returns a decorator function because this function is designed as a decorator function with arguments.

#### Args

The same as the arguments of `yadopt.parse` function.

#### Returns

Type | Description
--- | ---
`Callable` | The `yadopt.wrap` is a Python decorator function that allows users to modify the behavior of functions or methods, therefore the returned value of this function is a callable object. The first argument of the target function of this decorator is curried by the result of `yadopt.parse` and the curried object will be returned.

### yadopt.to_dict

    def yadopt.to_dict(args: YadOptArgs) -> dict:

Convert the `YadOptArgs` instance to a dictionary.

#### Args

Name | Type | Default value | Description
--- | --- | --- | ---
`args` | `YadOptArgs` | - | Parsed command line arguments.

#### Returns

Type | Description
--- | ---
`dict` | Dictionary of the given parsed arguments.

### yadopt.to_namedtuple

    def to_namedtuple(args: YadOptArgs) -> tuple[Any, ...]:

Convert YadOptArgs instance to a named tuple.

#### Args

Name | Type | Default value | Description
--- | --- | --- | ---
`args` | `YadOptArgs` | - | Parsed command line arguments.

#### Returns

Type | Description
--- | ---
`tuple[Any, ...]` | Named tuple of the given parsed arguments.

### yadopt.save

    def save(path: str, args: YadOptArgs, indent: int = 4) -> None:

Save the parsed command-line arguments as a JSON file. The suffix of the `path` should be `.json` or `.json.gz`. This function will support other data formats, like TOML and CSV, but now it supports JSON format only.

#### Args

Name | Type | Default value | Description
--- | --- | --- | ---
`path` | `str` | - | Destination path.
`args` | `YadOptArgs` | - | Parsed command line arguments to be saved.
`indent` | `int` | 4 | Indent size of the output JSON file.

#### Returns

Type | Description
--- | ---
`None` | -

### yadopt.load

    def load(path: str) -> YadOptArgs:

Load a parsed command line arguments from a file.

#### Args

Name | Type | Default value | Description
--- | --- | --- | ---
`path` | `str` | - | Source path.

#### Returns

Type | Description
--- | ---
`YadOptArgs` | Restored parsed command line arguments.