Click: can't set context_settings with chain=true

Created on 10 Apr 2020  路  5Comments  路  Source: pallets/click

@click.group(chain=True) cannot be combined with @click.command(context_settings=CONTEXT_SETTINGS).


Expected Behavior

I should see Error: No such command "test".

Suppose we name the following script debug, and we invoke using debug test. This works:

#!/usr/bin/env python
import click

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@click.group(chain=True)
@click.pass_context
@click.command(context_settings=CONTEXT_SETTINGS)
def main(ctx):
    print("hi")

if __name__ == '__main__':
    main()

Also works:

#!/usr/bin/env python
import click

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@click.group()
@click.command(context_settings=CONTEXT_SETTINGS)
def main():
    print("hi")

if __name__ == '__main__':
    main()

Actual Behavior

Both, however, fail if we instead do @click.group(chain=True). The error messages are confusing. In case (1): TypeError: 'Context' object is not iterable. For (2): TypeError: Attempted to convert a callback into a command twice.

Environment

  • Python version: 3.7
  • Click version: 7.0
chain

Most helpful comment

I think you're getting that error message because you're decorating your main function with @click.group and @click.command, which AFAIK is not legal?

If I create separate functions for the group and the command it seems to work as expected:

#!/usr/bin/env python
import click

CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
@click.group(chain=True, context_settings=CONTEXT_SETTINGS)
@click.pass_context
def cli(ctx):
    print("cli")

@cli.command()
@click.pass_context
def foo(ctx):
    print("foo")

if __name__ == '__main__':
    cli()

use:

$ python debug.py foo -h
cli
Usage: debug.py foo [OPTIONS]

Options:
  -h, --help  Show this message and exit.
$ python debug.py test
cli
Usage: debug.py [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
Try "debug.py -h" for help.

Error: No such command "test".

All 5 comments

Chain is not supported going forward #1323. If you have a fix for this, I'm happy to consider a PR, but given its issues I don't plan to do more work on it myself.

First, I really appreciate your work on Click--it's a fantastic library. Thank you.

I've been using chain for 3 years in production, including 7.0, and haven't had any issues with Chain until this one, and even then this is a minor one that I can live with. The only restriction I've noticed was described in https://github.com/pallets/click/issues/1269#issuecomment-478374133.

I use Click specifically because I can design pipeline CLI tools for scientific applications.

E.g. I have a command create_nwb from_tiff -n calcium_imaging ca.tif from_tiff -n potassium_imaging k.tif that allows for arbitray number of from_tiff subcommands. Is there another way to implement this without chain?

We're no longer planning to remove chain, so no worries about that at least.

I think you're getting that error message because you're decorating your main function with @click.group and @click.command, which AFAIK is not legal?

If I create separate functions for the group and the command it seems to work as expected:

#!/usr/bin/env python
import click

CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
@click.group(chain=True, context_settings=CONTEXT_SETTINGS)
@click.pass_context
def cli(ctx):
    print("cli")

@cli.command()
@click.pass_context
def foo(ctx):
    print("foo")

if __name__ == '__main__':
    cli()

use:

$ python debug.py foo -h
cli
Usage: debug.py foo [OPTIONS]

Options:
  -h, --help  Show this message and exit.
$ python debug.py test
cli
Usage: debug.py [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
Try "debug.py -h" for help.

Error: No such command "test".

Thank you both so much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dhstack picture dhstack  路  4Comments

antoine-gallix picture antoine-gallix  路  3Comments

rbonthond picture rbonthond  路  4Comments

ror6ax picture ror6ax  路  4Comments

joveice picture joveice  路  3Comments