Skip to main content

Constrained option support for click

Project description

click-constrained-option

click-constrained-option is an extension package that adds constrains to option in Click.

Tested under click 7.x

What it does

Build option that:

  • mutually exclusive with others
  • depend on other options
  • is required conditionally
  • is promoted conditionally
  • set its default value conditionally
  • set its type conditionally

Quick start

pip install click-constrained-option
# example.py

import click
from click_constrained_option import ConstrainedOption

@click.command()
@click.option(cls=ConstrainedOption,
              group_require_one=["apple", "orange", "pear"])
@click.option("--apple",
              cls=ConstrainedOption,
              is_flag=True)
@click.option("--orange",
              cls=ConstrainedOption,
              is_flag=True)
@click.option("--pear",
              cls=ConstrainedOption,
              is_flag=True)
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py

Error: require exact one of '--apple' '--orange' '--pear'

$ python example.py --apple --pear

Error: require exact one of '--apple' '--orange' '--pear'

API

kwarg type usage
allowed_func function return True to indicate allowance, vice versa
allowed_if str name of the option
allowed_if_not str name of the option
allowed_if_all_of list list of the option names
allowed_if_none_of list list of the option names
allowed_if_any_of list list of the option names
allowed_if_one_of list list of the option names
required_func function return True to indicate requirement, vice versa
required_if str name of the option
required_if_not str name of the option
required_if_all_of list list of the option names
required_if_none_of list list of the option names
required_if_any_of list list of the option names
required_if_one_of list list of the option names
prompt_func function return True to indicate prompt, vice versa
prompt_if str name of the option
prompt_if_not str name of the option
prompt_if_all_of list list of the option names
prompt_if_none_of list list of the option names
prompt_if_any_of list list of the option names
prompt_if_one_of list list of the option names
group_require_one list list of the option names
group_require_any list list of the option names
group_require_all list list of the option names
default_func function return a value to use as the default
type_func function return a valid type of the option

Note

  • If multiple kwargs are used, then all of them must be satisfied. For example, if prompt_if and prompt_if_all_of are specified, then the option is prompted only when both condition hold true.

  • If the custom function has an argument equals an option name in the command, then the value of that option will be used as argument. For example, value of --foo will be passed to a custom function bar(foo).

Examples

Dependency and exclusive relation

--username is allowed if --login is set:

import click
from click_constrained_option import ConstrainedOption

@click.command()
@click.option("--username",
              cls=ConstrainedOption,
              allowed_if="login")
@click.option("--login", is_flag=True)
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py --username=foo

Error: Usage for '--username': require '--login'

--login is allowed if at least one of --userid and --email is specified, and --oauth is not set:

import click
from click_constrained_option import ConstrainedOption

@click.command()
@click.option("--login",
              cls=ConstrainedOption,
              is_flag=True,
              allowed_if_any_of=["userid", "email"],
              allowed_if_not="cookie")
@click.option("--userid")
@click.option("--email")
@click.option("--oauth", is_flag=True)
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py --login --userid=foo --oauth

Error: Usage for '--login': conflict with '--oauth'

$ python example.py --login

Error: Usage for '--login': require at least one of '--userid' '--email'

--port is required if --listen is an IP address:

import click
import re
from click_constrained_option import ConstrainedOption

@click.command()
@click.option("--port",
              cls=ConstrainedOption,
              required_func=lambda b: re.match(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", b))
@click.option("--listen")
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py --listen=127.0.0.1

Error: Missing option '--port'

Mutually exclusive group

Exact one of the --order-by-date --order-by-name --order-by-rank must be set:

import click
from click_constrained_option import ConstrainedOption

@click.option(cls=ConstrainedOption,
              group_require_one=["order_by_name", "order_by_rank", "order_by_date"])
@click.option("--order-by-name",
              cls=ConstrainedOption,
              is_flag=True)
@click.option("--order-by-rank",
              cls=ConstrainedOption,
              is_flag=True)
@click.option("--order-by-date",
              cls=ConstrainedOption,
              is_flag=True)
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py

Error: require exact one of '--order-by-name' '--order-by-rank' '--order-by-date'

Conditional prompt

--password will be prompted if one of --userid --email is specified

import click
from click_constrained_option import ConstrainedOption

@click.command()
@click.option("--userid")
@click.option("--email")
@click.option("--password", 
              hide_input=True,
              prompt_if_one_of=["userid", "email"])
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py --userid

Password: 

Conditional type

Type of --time will be int if --time-format=timestamp

import click
from click_constrained_option import ConstrainedOption

@click.command()
@click.option("--time-format",
              type=click.Choice(["iso-8601", "timestamp"]))
@click.option("--time",
              cls=ConstrainedOption,
              type_func=lambda time_format: click.INT if time_format == "timestamp" else click.STRING)
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python --time-format="timestamp" --time=str_not_int

Error: Invalid value for '--time': str_not_int is not a valid integer

Conditional default

Default of --lucky is set through custom function

import click
from click_constrained_option import ConstrainedOption
from random import randint

@click.command()
@click.option("--lucky",
              default=lambda : randint(0, 9))
def cli(**kwargs):
    click.echo(kwargs)


if __name__ == "__main__":
    cli()
$ python example.py

{'lucky': '5'}

Project details


Release history Release notifications | RSS feed

This version

0.1

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

click-constrained-option-0.1.tar.gz (6.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

click_constrained_option-0.1-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file click-constrained-option-0.1.tar.gz.

File metadata

  • Download URL: click-constrained-option-0.1.tar.gz
  • Upload date:
  • Size: 6.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.1 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.8.2

File hashes

Hashes for click-constrained-option-0.1.tar.gz
Algorithm Hash digest
SHA256 ace4c408c5609ac009087593ea292fb09bb89cc0f9d30ea82292f992015c9681
MD5 a4a557f4faf7b430e091648dceb89af6
BLAKE2b-256 6310a522ef19f0af35b23b0f5aebbe73f62b24b63d0a61891a2394b33a0e4490

See more details on using hashes here.

File details

Details for the file click_constrained_option-0.1-py3-none-any.whl.

File metadata

  • Download URL: click_constrained_option-0.1-py3-none-any.whl
  • Upload date:
  • Size: 6.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.1 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.8.2

File hashes

Hashes for click_constrained_option-0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fe2dd75250434460382725644f6b7e0c09755fe708117c4996c279b570695799
MD5 fdd0e564609d10be58ad2a7650270653
BLAKE2b-256 b60ac8a2042760ad61cc6ccd5a0496fbfe11cf5a028b2676d381f05586db3c2f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page