Skip to content

4piu/click-constrained-option

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

click-constrained-option

PyPI version Build Status

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'}

About

An extension package that adds constrains to click.Option

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages