I'm trying to implement a command line app using the Flask CLI infrastructure based on Click. Its interface should work like this:
app.py -c config.cfg cmd_a
app.py -c config.cfg cmd_b
I have the following code:
@click.group
@click.option('-c', 'config')
@click.pass_context
def cli(ctx, config):
ctx.obj = ObjA(config)
ctx.obj = ObjB(config) # Just for illustration
@cli.command()
@click.pass_context()
def cmd_a(ctx):
ctx.find_object(ObjA)
@cli.command()
@cli.pass_context()
def cmd_b(ctx):
ctx.find_object(ObjB)
cli()
The problem is, I need to create two different objects based on the -c
flag and make them both available to the underlying commands, which seems impossible. Is there any workaround for this?
I know I could use the meta
property of the Context object, but that would mean writing a lot of boilerplate.
find_object
will search object in parent context by type. If you want to use multiple objects the easiest way is to make obj
a dictionary. Here example:
@click.group
@click.option('-c', 'config')
@click.pass_context
def cli(ctx, config):
if ctx.obj is None:
ctx.obj = dict()
# add any data to obj here...
ctx.obj['a'] = 'example_A'
ctx.obj['b'] = 'example_B'
@cli.command()
@click.pass_context()
def cmd_a(ctx):
# check prepared data
print(ctx.obj['a'])
@cli.command()
@cli.pass_context()
def cmd_b(ctx):
# check prepared data
print(ctx.obj['b'])
Slightly different way - use custom class for obj
:
class Config(object):
def __init__(self, config):
# do something with config here ...
self.a = 'example_A'
self.b = 'example_B'
# in your def cli()
ctx.obj = Config(config)
# in your commands you can works with your prepared data like this:
print(ctx.obj.a)
print(ctx.obj.b)
Hope this helps.