How to implement –version using python click?

Question:

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()
Asked By: wonton

||

Answers:

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
Answered By: wonton

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
Answered By: EsmaeelE

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()
Answered By: will-wright-eng