Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/__pycache__/
doc/conf.shelve.db
docs/
# pixi environments
Expand Down
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,40 @@ options:
-d, --debug debug mode
```

### Customizing the underlying `argparse.ArgumentParser`

It is possible to pass argument `parser_config` to `call`, which then gets
passed on to the underlying `argparse.ArgumentParser` as keyword arguments.
This allows for advanced control of behavior, such as using a custom
help formatter.

For example, you may want to add a line break in the help string for
a parameter, to make it more readable in case it's long. In such case
`plac` will automatically remove these line breaks by default, whether
you create them using escape newline characters (`\n`) or using
a multi-line string literal. To preserve line breaks in argument
help strings, you can use a custom `HelpFormatter` by passing a parser
config containing the `formatter_class` key to `plac.call()`:

```python
class MyCustomFormatter(argparse.HelpFormatter):
...

if __name__ == '__main__':
plac.call(
main,
parser_config=dict(
formatter_class=MyCustomFormatter
)
)
```

If you wish to preserve the help strings verbatim, you can use
`argparse.RawTextHelpFormatter` as the `formatter_class`; however,
there are some caveats, e.g. it does not de-dent the text like
the standard formatter does (although this can be easily accomplished
using `textwrap.dedent`).

## Decorator reference

To use `plac` all you need to know are the following three decorators:
Expand Down
6 changes: 4 additions & 2 deletions plac_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,17 +419,19 @@ def iterable(obj):
return hasattr(obj, '__iter__') and not inspect.isclass(obj) and not isinstance(obj, (str, bytes))


def call(obj, arglist=None, eager=True, version=None):
def call(obj, arglist=None, eager=True, version=None, parser_config={}):
"""
If obj is a function or a bound method, parse the given arglist
by using the parser inferred from the annotations of obj
and call obj with the parsed arguments.
If obj is an object with attribute .commands, dispatch to the
associated subparser.

:param parser_config: dict of keyword arguments passed to ArgumentParser
"""
if arglist is None:
arglist = sys.argv[1:]
parser = parser_from(obj)
parser = parser_from(obj, **parser_config)
if version:
parser.add_argument(
'--version', '-v', action='version', version=version)
Expand Down