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_ifandprompt_if_all_ofare 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
--foowill be passed to a custom functionbar(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
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ace4c408c5609ac009087593ea292fb09bb89cc0f9d30ea82292f992015c9681
|
|
| MD5 |
a4a557f4faf7b430e091648dceb89af6
|
|
| BLAKE2b-256 |
6310a522ef19f0af35b23b0f5aebbe73f62b24b63d0a61891a2394b33a0e4490
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe2dd75250434460382725644f6b7e0c09755fe708117c4996c279b570695799
|
|
| MD5 |
fdd0e564609d10be58ad2a7650270653
|
|
| BLAKE2b-256 |
b60ac8a2042760ad61cc6ccd5a0496fbfe11cf5a028b2676d381f05586db3c2f
|