23

I want to implement mycommand --version using python click. I have something like this working but it feels kinda clunky.

@click.group(invoke_without_command=True, no_args_is_help=True)
@click.pass_context
@click.option('--version', 'version')
def cli(ctx, version):
    if version:
        ctx.echo(f'{sys.argv[0]} {__version__}')
        ctx.exit()
wonton
  • 7,568
  • 9
  • 56
  • 93

3 Answers3

49

As it turns out, click has a builtin decorator click.version_option to accomplish this. The code now becomes:

@click.group()
@click.version_option(__version__)
@click.pass_context
def cli(ctx):
    pass
melvio
  • 762
  • 6
  • 24
wonton
  • 7,568
  • 9
  • 56
  • 93
  • 4
    Thanks; here's a link to the docs for more info on `click.version_option` too: https://click.palletsprojects.com/en/7.x/api/?highlight=version_option#click.version_option – Hawkins Jan 28 '20 at 18:06
  • I added this in my click cli but it does not work on trying to run command clickcli --version – Raj Jul 16 '21 at 13:13
2

You can use click.version_option decorator to implement --version option.

If your setup.py like this and have version click will read it automatically.

from setuptools import setup

setup(
    name='application',
    version='0.1',
    py_modules=['application'],
    install_requires=[
        'Click',
    ],
)

The click.version_option option without any argument will read version from setup.py.

@click.group(invoke_without_command=True, no_args_is_help=True)
@click.pass_context
@click.version_option()
def cli(ctx):
   ...

Run and Result

$ application --version 
application, version 0.1
EsmaeelE
  • 2,331
  • 6
  • 22
  • 31
0

I want to add another scenario that I ran into but isn't explicitly stated here:

Your CLI name can be different from your entry point, which can mean you'll need to provide the name explicitly if importlib_metadata can't automatically find the name

Error

Without package_name='my_command_line_interface':

mycli --version

RuntimeError: 'mycli' is not installed. Try passing 'package_name' instead.

Setup

setup.py

setup(
    name='my_command_line_interface',
    version='0.1',
    py_modules=['application'],
    install_requires=[
        'Click',
    ],
    entry_points="""
        [console_scripts]
        mycli=my_command_line_interface.cli:cli
    """,
)

cli.py

@click.group()
@click.version_option(package_name='my_command_line_interface') # <-- ADDED
@click.pass_context
def cli(ctx):
    pass

__main__.py

from .cli import cli

if __name__ == "__main__":
    cli()
willwrighteng
  • 1,411
  • 11
  • 25