When command names contain a - character, automatic environment variable name generation is broken
#!/usr/bin/env python3
import click
@click.group()
@click.option('--debug/--no-debug')
def cli(debug):
click.echo('Debug mode is %s' % ('on' if debug else 'off'))
@click.command(name="greet-me")
@click.option('--username', show_envvar=True)
def greet(username):
click.echo('Hello %s!' % username)
if __name__ == '__main__':
cli.add_command(greet)
cli(auto_envvar_prefix='GREETER')
$ pipenv run python ./test.py greet-me --help
Loading .env environment variables…
Debug mode is off
Usage: test.py greet-me [OPTIONS]
Options:
--username TEXT [env var: GREETER_GREET-ME_USERNAME]
--help Show this message and exit.
This seems to be solved by changing core.py:329 to
# If there is no envvar prefix yet, but the parent has one and
# the command on this level has a name, we can expand the envvar
# prefix automatically.
if auto_envvar_prefix is None:
if parent is not None \
and parent.auto_envvar_prefix is not None and \
self.info_name is not None:
auto_envvar_prefix = '%s_%s' % (parent.auto_envvar_prefix,
self.info_name.upper().replace("-", "_"))
I'm not opening a pull request though as I'm not familiar with click's codebase and
<something>.name.upper() found in core.py- with _ covers all the tricky casesIn fact, it also happens when not setting the command name explicitly but letting click renaming function names with underscore to command names.
#!/usr/bin/env python3
import click
@click.group()
@click.option('--debug/--no-debug')
def cli(debug):
click.echo('Debug mode is %s' % ('on' if debug else 'off'))
@cli.command()
@click.option('--username', show_envvar=True)
def greet_me(username, foo):
click.echo('Hello %s!' % username)
if __name__ == '__main__':
cli(auto_envvar_prefix='GREETER')
$ pipenv run python ./test.py greet-me --help
Loading .env environment variables…
Debug mode is off
Usage: test.py greet-me [OPTIONS]
Options:
--username TEXT [env var: GREETER_GREET-ME_USERNAME]
--help Show this message and exit.
This issue is causing me problems as well. Thank you @gpakosz for submitting a fix!
I guess it's related to https://github.com/pallets/click/commit/5d1df0e042b2f8b0dee8f6dd9ce74edce331a950
@davidism can this be added to the next milestone by chance?
Stumbled over this today as well. Maybe Command Aliases might be a workaround until #1261 is merged?
Unfortunately, Command Aliases can not be used as a workaround here (at least not how I am doing it):
import click
# this Group allows specifying both "greet_me" and "greet-me"
# (https://click.palletsprojects.com/en/7.x/advanced/?highlight=alias#command-aliases)
class AliasedGroup(click.Group):
def get_command(self, ctx, cmd_name):
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
matches = [
x
for x in self.list_commands(ctx)
if x in (cmd_name, cmd_name.replace("-", "_"))
]
if not matches:
return None
elif len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])
@click.group(
cls=AliasedGroup,
# setting the auto_envvar_prefix here works better with
# setuptools/console_scripts
context_settings={"auto_envvar_prefix": "GREETER"},
)
def cli():
click.echo("click version {}".format(click.__version__))
@cli.command(name="greet_me") # force the name to include the underscore
@click.option("--username", show_envvar=True)
def greet_me(username):
click.echo("Hello %s!" % username)
if __name__ == "__main__":
cli()
This can be invoked both with greet_me and greet-me. However, using the dash still results in the broken environment variable:
python3 -m test greet_me --help
click version 7.0
Usage: test.py greet_me [OPTIONS]
Options:
--username TEXT [env var: GREETER_GREET_ME_USERNAME]
--help Show this message and exit.
python3 -m test greet-me --help
click version 7.0
Usage: test.py greet-me [OPTIONS]
Options:
--username TEXT [env var: GREETER_GREET-ME_USERNAME]
--help Show this message and exit.
Most helpful comment
This issue is causing me problems as well. Thank you @gpakosz for submitting a fix!