Package: click-constrained-option
click-constrained-optionclick-constrained-optionis an extension package that adds constrains to option inClick.Tested under click 7.xWhat it doesBuild option that:mutually exclusive with othersdepend on other optionsis required conditionallyis promoted conditionallyset its default value conditionallyset its type conditionallyQuick startpipinstallclick-constrained-option# example.pyimportclickfromclick_constrained_optionimportConstrainedOption@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)defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py

Error:requireexactoneof'--apple''--orange''--pear'$pythonexample.py--apple--pear

Error:requireexactoneof'--apple''--orange''--pear'APIkwargtypeusageallowed_funcfunctionreturn True to indicate allowance, vice versaallowed_ifstrname of the optionallowed_if_notstrname of the optionallowed_if_all_oflistlist of the option namesallowed_if_none_oflistlist of the option namesallowed_if_any_oflistlist of the option namesallowed_if_one_oflistlist of the option namesrequired_funcfunctionreturn True to indicate requirement, vice versarequired_ifstrname of the optionrequired_if_notstrname of the optionrequired_if_all_oflistlist of the option namesrequired_if_none_oflistlist of the option namesrequired_if_any_oflistlist of the option namesrequired_if_one_oflistlist of the option namesprompt_funcfunctionreturn True to indicate prompt, vice versaprompt_ifstrname of the optionprompt_if_notstrname of the optionprompt_if_all_oflistlist of the option namesprompt_if_none_oflistlist of the option namesprompt_if_any_oflistlist of the option namesprompt_if_one_oflistlist of the option namesgroup_require_onelistlist of the option namesgroup_require_anylistlist of the option namesgroup_require_alllistlist of the option namesdefault_funcfunctionreturn a value to use as the defaulttype_funcfunctionreturn a valid type of the optionNoteIf multiple kwargs are used, then all of them must be satisfied. For example, ifprompt_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).ExamplesDependency and exclusive relation--usernameis allowed if--loginis set:importclickfromclick_constrained_optionimportConstrainedOption@click.command()@click.option("--username",cls=ConstrainedOption,allowed_if="login")@click.option("--login",is_flag=True)defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py--username=foo

Error:Usagefor'--username':require'--login'--loginis allowed if at least one of--useridand--emailis specified, and--oauthis not set:importclickfromclick_constrained_optionimportConstrainedOption@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)defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py--login--userid=foo--oauth

Error:Usagefor'--login':conflictwith'--oauth'$pythonexample.py--login

Error:Usagefor'--login':requireatleastoneof'--userid''--email'--portis required if--listenis an IP address:importclickimportrefromclick_constrained_optionimportConstrainedOption@click.command()@click.option("--port",cls=ConstrainedOption,required_func=lambdab:re.match(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",b))@click.option("--listen")defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py--listen=127.0.0.1

Error:Missingoption'--port'Mutually exclusive groupExact one of the--order-by-date--order-by-name--order-by-rankmust be set:importclickfromclick_constrained_optionimportConstrainedOption@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)defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py

Error:requireexactoneof'--order-by-name''--order-by-rank''--order-by-date'Conditional prompt--passwordwill be prompted if one of--userid--emailis specifiedimportclickfromclick_constrained_optionimportConstrainedOption@click.command()@click.option("--userid")@click.option("--email")@click.option("--password",hide_input=True,prompt_if_one_of=["userid","email"])defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py--userid

Password:Conditional typeType of--timewill be int if--time-format=timestampimportclickfromclick_constrained_optionimportConstrainedOption@click.command()@click.option("--time-format",type=click.Choice(["iso-8601","timestamp"]))@click.option("--time",cls=ConstrainedOption,type_func=lambdatime_format:click.INTiftime_format=="timestamp"elseclick.STRING)defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$python--time-format="timestamp"--time=str_not_int

Error:Invalidvaluefor'--time':str_not_intisnotavalidintegerConditional defaultDefault of--luckyis set through custom functionimportclickfromclick_constrained_optionimportConstrainedOptionfromrandomimportrandint@click.command()@click.option("--lucky",default=lambda:randint(0,9))defcli(**kwargs):click.echo(kwargs)if__name__=="__main__":cli()$pythonexample.py{'lucky':'5'}