Click + option groups + constraints + aliases + help themes + ...
Cloup — originally from "Click + option groups" — enriches Click with several features that make it more expressive and configurable:
- option groups
- constraints, like
mutually_exclusive, that can be applied to option groups or to any group of parameters, even conditionally - subcommand aliases
- subcommands sections, i.e. the possibility of organizing the subcommands of a
Groupin multiple help sections - a themeable HelpFormatter that:
- has more parameters for adjusting widths and spacing, which can be provided at the context and command level
- use a different layout when the terminal width is below a certain threshold in order to improve readability
- additional parameter types, e.g. path types that use
pathlib.Pathinstead ofstrby default. - command decorators with individually typed keyword arguments, plus typed helpers
such as
Context.settings()andHelpFormatter.settings(), for better IDE and static type checker support.
Cloup is statically type-checked with Mypy and Pyrefly and extensively tested against multiple versions of Python with nearly 100% coverage.
Since version 4.0.0, Cloup makes an effort to re-export the public symbols in Click's
top-level namespace. Applications using Cloup can therefore access most Click
functionality through cloup without maintaining separate top-level imports from
both packages.
from cloup import (
HelpFormatter, HelpTheme, Style,
command, option, option_group
)
from cloup.constraints import RequireAtLeast, mutually_exclusive
# Check the docs for all available arguments of HelpFormatter and HelpTheme.
formatter_settings = HelpFormatter.settings(
theme=HelpTheme(
invoked_command=Style(fg='bright_yellow'),
heading=Style(fg='bright_white', bold=True),
constraint=Style(fg='magenta'),
col1=Style(fg='bright_yellow'),
)
)
# In a multi-command app, you can pass formatter_settings as part
# of your context_settings so that they are propagated to subcommands.
@command(formatter_settings=formatter_settings)
@option_group(
"Cool options",
option('--foo', help='This text should describe the option --foo.'),
option('--bar', help='This text should describe the option --bar.'),
constraint=mutually_exclusive,
)
@option_group(
"Other cool options",
"This is the optional description of this option group.",
option('--pippo', help='This text should describe the option --pippo.'),
option('--pluto', help='This text should describe the option --pluto.'),
constraint=RequireAtLeast(1),
)
def cmd(**kwargs):
"""This is the command description."""
pass
if __name__ == '__main__':
cmd(prog_name='invoked-command')If you don't provide --pippo or --pluto:
Usage: invoked-command [OPTIONS]
Try 'invoked-command --help' for help.
Error: at least 1 of the following parameters must be set:
--pippo
--pluto
This simple example just scratches the surface. Read more in the documentation (links below).
- Documentation (release | development)
- Release notes
- GitHub repository
- Q&A and discussions
