Package: click-anno
click-annouse annotation to create click app.Compare with click apiBasic Arguments# clickimportclick@click.command()@click.argument('filename')deftouch(filename):click.echo(filename)# click_annoimportclickimportclick_anno@click_anno.commanddeftouch(filename):click.echo(filename)Variadic Arguments# clickimportclick@click.command()@click.argument('src',nargs=-1)@click.argument('dst',nargs=1)defcopy(src,dst):forfninsrc:click.echo('move%sto folder%s'%(fn,dst))# click_annoimportclickimportclick_anno@click_anno.commanddefcopy(src:tuple,dst):forfninsrc:click.echo('move%sto folder%s'%(fn,dst))Basic Value Options# clickimportclick@click.command()@click.option('--n',default=1)defdots(n):click.echo('.'*n)# click_annoimportclickimportclick_anno@click_anno.commanddefdots(n=1):click.echo('.'*n)Required Value Options# clickimportclick@click.command()@click.option('--n',required=True,type=int)defdots(n):click.echo('.'*n)# click_annoimportclickimportclick_anno@click_anno.commanddefdots(*,n:int):click.echo('.'*n)Multi Value Options# clickimportclick@click.command()@click.option('--pos',nargs=2,type=float)deffindme(pos):click.echo('%s/%s'%pos)# click_annofromtypingimportTupleimportclickimportclick_anno@click_anno.commanddeffindme(*,pos:Tuple[float,float]):click.echo('%s/%s'%pos)Tuples as Multi Value Options# clickimportclick@click.command()@click.option('--item',type=(str,int))defputitem(item):click.echo('name=%sid=%d'%item)# click_annofromtypingimportTupleimportclickimportclick_anno@click_anno.commanddefputitem(*,item:(str,int)):click.echo('name=%sid=%d'%item)Boolean Flags# clickimportclick@click.command()@click.option('--shout',is_flag=True)definfo(shout):click.echo(f'{shout!r}')# click_annoimportclickfromclick_annoimportcommandfromclick_anno.typesimportflag@commanddeffunc(shout:flag):click.echo(f'{shout!r}')Inject Context# click@command()@click.pass_contextdefsync(ctx):# `ctx` must be the 1st argclick.echo(str(type(ctx)))# click_anno@commanddefsync(a,ctx:click.Context,b):# `ctx` can be any locationclick.echo(str(type(ctx)))Group# click@click.group()defcli():click.echo('Running')@cli.command()defsync():click.echo('Syncing')# click_anno@click_appclassApp:def__init__(self):click.echo('Running')defsync(self):click.echo('Syncing')ExtensionsEnumEnum isNOTChoice.# click# does not support# click_annoimportclickfromclick_annoimportcommandfromenumimportEnum,autoclassHashTypes(Enum):md5=auto()sha1=auto()@commanddefdigest(hash_type:HashTypes):assertisinstance(hash_type,HashTypes)click.echo(hash_type)Alias# click# does not support# click_anno@click_appclassApp:defsync(self):click.echo('Syncing')alias=syncshow default in argumentby default,click.argumentdid not acceptshow_defaultoption.click_anno was modify this.@commanddeffunc(a=10,*_):pass# with --help# Usage: func [OPTIONS] [A=10]# ...Arguments vs Optionsclick only has two kinds of parameters:OptionsArguments - work similarly to options but are positional.By default in python, arguments like*argsand options like**kwargs.In examplefunc(a, b=1, *args, d, e=2),abargsare arguments,deare options.If you don't want the args*args, rename it to*_.click_anno will ignore all args named_In examplefunc(a, b=1),*argsdid not exists. soais argument,bis option.Auto Inject Argumentsby default, you can injectclick.Contextby annotation:@commanddefinject_context(a,ctx:click.Context,b):# `ctx` can be any locationclick.echo(str(type(ctx)))or impl theInjectable:fromclick_annoimportInjectableclassCustom(Injectable):@classmethoddef__inject__(cls):returncls()@commanddefinject_it(obj:Custom):assertisinstance(obj,Custom)or callinjectfunction:fromclick_annoimportinjectclassCustom:passinject(Custom,lambda:Custom())@commanddefinject_it(obj:Custom):assertisinstance(obj,Custom)or if you want to inject fromclick.Context.ensure_object()orclick.Context.find_object(), you can use:fromclick_annoimportfind,ensure@commanddefinject_it(f:find(A),e:ensure(B)):...