cloup

More features for Click: option groups, constraints, subcommands sections and a custom help formatter supporting themes.

Cloup (originally from: Click + option groups) extends Click with several features:

  • Option groups with the @option_group decorator.
  • Constraints like mutually_exclusive, RequireAtLeast(n) etc., which can be applied, even conditionally, to option groups or to any group of parameters (including positional arguments).
  • Possibility to organize the subcommands of a Group in multiple help sections.
  • A themeable HelpFormatter that:
    • allows you to style several elements of the help page according to a theme
    • switches to a different layout when the terminal width is small for the standard 2-column layout, so that the help page is readable in all circumstances
    • has more parameters, which give you more control on the format of the help page.

Besides, Cloup is:

  • type-annotated and provides additional methods so that you can always be assisted by your IDE (e.g. Context.settings() for creating a context_settings dict leveraging auto-completion)
  • extensively tested with multiple versions of Python and Click (see Tests)
  • well-documented.

Basic example

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 would pass formatter_settings inside context_settings
# so that settings 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')

basic-example

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

Supporting the project

Designing, testing and documenting a library takes a lot of time. The most concrete way to show your appreciation and to support future development is by donating. Any amount is appreciated.