Obtener params enviados a un subcomando de un click.group ()

Si tengo un click.group() con varios subcomandos, ¿hay alguna manera de que pueda pasar los argumentos de la línea de comandos a esos subcomandos dentro del propio grupo?

Sé que puede ir del grupo hacia abajo a través del context , y sé que puedo usar una función de callback que se ejecutará antes del comando, pero no sabía si había una mejor manera de hacerlo que usar una callback .

Un ejemplo:

 @click.group() def cli(): pass @cli.command() @click.argument('task') @click.argument('task_id') def sync(task, task_id): click.echo('Synching: {}'.format(task)) 

En este ejemplo, ¿hay alguna forma de obtener task o task_id en el método de grupo?

Esto se puede hacer sobrepasando el método click.Group.invoke() como:

Clase personalizada:

 class MyGroup(click.Group): def invoke(self, ctx): ctx.obj = tuple(ctx.args) super(MyGroup, self).invoke(ctx) 

Usando la clase personalizada:

Luego, para usar el grupo personalizado, cls como el argumento cls al decorador de group como:

 @click.group(cls=MyGroup) @click.pass_context def cli(ctx): args = ctx.obj .... 

¿Como funciona esto?

Esto funciona porque click es un marco OO bien diseñado. El @click.group() generalmente click.Group una instancia de click.Group pero permite que este comportamiento se anule con el parámetro cls . Por lo tanto, es relativamente fácil heredar de click.Group en nuestra propia clase y click.Group los métodos deseados.

En este caso, sobrepasamos click.Group.invoke() y click.Group.invoke() los argumentos y los ctx.obj en el campo ctx.obj . Entonces son accesibles en la función cli() .

Código de prueba:

 import click class MyGroup(click.Group): def invoke(self, ctx): ctx.obj = tuple(ctx.args) super(MyGroup, self).invoke(ctx) @click.group(cls=MyGroup) @click.pass_context def cli(ctx): args = ctx.obj click.echo('cli: {} {}'.format(ctx.invoked_subcommand, ' '.join(args))) @cli.command() @click.argument('task') @click.argument('task_id') def sync(task, task_id): click.echo('Synching: {}'.format(task)) cli('sync task taskid'.split()) 

Resultados:

 cli: sync task taskid Synching: task