5

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.

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Using a custom class in obj seems like the best way to me, even though it's not exactly "pure". Oh, and a little correction - find_object searches the whole context hierarchy, not just the immediate parent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.