On Github telemaco / python-click
virtualenv .venv source .venv/bin/activate pip install click
#!/usr/bin/env python import click @click.command() def hello(): click.echo('Hello World!') if __name__ == '__main__': hello()
./hello_world.py Hello World!
#!/usr/bin/env python import click @click.group() def cli(): pass @cli.command() def say_hello(): click.echo('Hello hacker!') @cli.command() def say_bye(): click.echo('Bye hacker!') if __name__ == '__main__': cli()
$ anidando Usage: anidando [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: say_bye say_hello
#!/usr/bin/env python import click @click.command() @click.option('--count-down', default=10, help='suprise countdown') @click.argument('name') def surprise(count_down, name): while count_down != 0: click.echo("%s..." % count_down) count_down = count_down - 1 click.echo("Supriseeeeee!!!! %s" % name) if __name__ == '__main__': surprise()
$ surprise --help Usage: surprise [OPTIONS] NAME Options: --count-down INTEGER suprise countdown --help Show this message and exit. $ surprise --count-down 3 roberto 3... 2... 1... Supriseeeeee!!!! roberto
from setuptools import setup setup( name='yourscript', version='0.1', py_modules=['yourscript'], install_requires=[ 'Click', ], entry_points=''' [console_scripts] yourscript=yourscript:cli ''', )
@click.command() @click.option('--n', default=1) def dots(n): click.echo('.' * n)
@click.command() @click.option('--pos', nargs=2, type=float) def findme(pos): click.echo('%s / %s' % pos)
@click.command() @click.option('--item', type=(unicode, int)) def putitem(item): click.echo('name=%s id=%d' % item)
@click.command() @click.option('--message', '-m', multiple=True) def commit(message): click.echo('\n'.join(message))
$ commit -m foo -m bar foo bar
@click.command() @click.option('-v', '--verbose', count=True) def log(verbose): click.echo('Verbosity: %s' % verbose)
$ log -vvv Verbosity: 3
@click.command() @click.option('--shout/--no-shout', default=False) def info(shout): if shout: click.echo('Eeeeeeeyyyyy!!!!!') else: click.echo('Ey')
import sys @click.command() @click.option('--upper', 'transformation', flag_value='upper', default=True) @click.option('--lower', 'transformation', flag_value='lower') def info(transformation): click.echo(getattr(sys.platform, transformation)())
$ info --upper DARWIN $ info --lower darwin $ info DARWIN
@click.command() @click.option('--hash-type', type=click.Choice(['md5', 'sha1'])) def digest(hash_type): click.echo(hash_type)
@click.command() @click.option('--name', prompt=True) def hello(name): click.echo('Hello %s!' % name)
$ hello --name=John Hello John! $ hello Name: John Hello John!
@click.command() @click.password_option() def encrypt(password): click.echo('Encrypting password to %s' % password.encode('rot13')) # # Asi seria sin el decorator @click.password_option() # # @click.command() # @click.option('--password', prompt=True, hide_input=True, # confirmation_prompt=True) # def encrypt(password): # click.echo('Encrypting password to %s' % password.encode('rot13'))
$ encrypt Password: Repeat for confirmation: Encrypting password to frperg
@click.command() @click.option('--username') def greet(username): click.echo('Hello %s!' % username) if __name__ == '__main__': greet(auto_envvar_prefix='GREETER')
$ export GREETER_USERNAME=john $ greet Hello john!
@click.command() @click.option('--username', envvar='USERNAME') def greet(username): click.echo('Hello %s!' % username) if __name__ == '__main__': greet()
$ export USERNAME=john $ greet Hello john!
def validate_rolls(ctx, param, value): try: rolls, dice = map(int, value.split('d', 2)) return (dice, rolls) except ValueError: raise click.BadParameter('rolls need to be in format NdM') @click.command() @click.option('--rolls', callback=validate_rolls, default='1d6') def roll(rolls): click.echo('Rolling a %d-sided dice %d time(s)' % rolls) if __name__ == '__main__': roll()
roll --rolls=42 Usage: roll [OPTIONS] Error: Invalid value for "--rolls": rolls need to be in format NdM $ roll --rolls=2d12 Rolling a 12-sided dice 2 time(s)
@click.command() @click.argument('filename') def touch(filename): click.echo(filename)
$ touch foo.txt foo.txt
@click.command() @click.argument('src', nargs=-1) @click.argument('dst', nargs=1) def copy(src, dst): for fn in src: click.echo('move %s to folder %s' % (fn, dst))
$ copy foo.txt bar.txt my_folder move foo.txt to folder my_folder move bar.txt to folder my_folder
@click.command() @click.argument('input', type=click.File('rb')) @click.argument('output', type=click.File('wb')) def inout(input, output): while True: chunk = input.read(1024) if not chunk: break output.write(chunk)
$ inout - hello.txt hello ^D $ inout hello.txt - hello
@click.command() @click.argument('f', type=click.Path(exists=True)) def touch(f): click.echo(click.format_filename(f))
$ touch hello.txt hello.txt $ touch missing.txt Usage: touch [OPTIONS] F Error: Invalid value for "f": Path "missing.txt" does not exist.
@click.command() @click.argument('name') def say_hello(name): """This script say hello to user NAME.""" click.echo('Hello %s!' % name)
$ say_hello --help Usage: say_hello [OPTIONS] NAME This script say hello to user NAME. Options: --help Show this message and exit.
@click.group() def cli(): """A simple command line tool.""" @cli.command('init', short_help='init the repo') def init(): """Initializes the repository.""" @cli.command('delete', short_help='delete the repo') def delete(): """Deletes the repository."""
$ repo.py Usage: repo.py [OPTIONS] COMMAND [ARGS]... A simple command line tool. Options: --help Show this message and exit. Commands: delete delete the repo init init the repo
value = click.prompt('Please enter a valid integer', type=int)
value = click.prompt('Please enter a number', default=42.0)
if click.confirm('Do you want to continue?'): click.echo('Well done!')
click.confirm('Do you want to continue?', abort=True)
import click click.echo('Hello World!') click.echo('Hello World!', err=True) click.secho('Hello World!', fg='green') click.secho('Some more text', bg='blue', fg='white') click.secho('ATTENTION', blink=True, bold=True)
@click.command() def less(): click.echo_via_pager('\n'.join('Line %d' % idx for idx in range(200)))
import click def get_commit_message(): MARKER = '# Everything below is ignored\n' message = click.edit('\n\n' + MARKER) if message is not None: return message.split(MARKER, 1)[0].rstrip('\n')
click.edit(filename='/etc/passwd')
@click.group() @click.option('--debug/--no-debug', default=False) @click.pass_context def cli(ctx, debug): ctx.obj['DEBUG'] = debug @cli.command() @click.pass_context def sync(ctx): click.echo('Debug is %s' % (ctx.obj['DEBUG'] and 'on' or 'off')) if __name__ == '__main__': cli(obj={})
$ cmd --debug sync Debug is on $ cmd sync Debug is off
import click import os plugin_folder = os.path.join(os.path.dirname(__file__), 'commands') class MyCLI(click.MultiCommand): def list_commands(self, ctx): rv = [] for filename in os.listdir(plugin_folder): if filename.endswith('.py'): rv.append(filename[:-3]) rv.sort() return rv def get_command(self, ctx, name): ns = {} fn = os.path.join(plugin_folder, name + '.py') with open(fn) as f: code = compile(f.read(), fn, 'exec') eval(code, ns, ns) return ns['cli'] @click.command(cls=MyCLI) def cli(): pass
import click @click.group() def cli1(): pass @cli1.command() def cmd1(): """Command on cli1""" @click.group() def cli2(): pass @cli2.command() def cmd2(): """Command on cli2""" cli = click.CommandCollection(sources=[cli1, cli2]) if __name__ == '__main__': cli()
@click.group(chain=True) def cli(): pass @cli.command('sdist') def sdist(): click.echo('sdist called') @cli.command('bdist_wheel') def bdist_wheel(): click.echo('bdist_wheel called')
$ setup.py sdist bdist_wheel sdist called bdist_wheel called
import click CONTEXT_SETTINGS = dict( default_map={'runserver': {'port': 5000}} ) @click.group(context_settings=CONTEXT_SETTINGS) def cli(): pass @cli.command() @click.option('--port', default=8000) def runserver(port): click.echo('Serving on http://127.0.0.1:%d/' % port) if __name__ == '__main__': cli()
$ cli runserver Serving on http://127.0.0.1:5000/
cli = click.Group() @cli.command() @click.option('--count', default=1) def test(count): click.echo('Count: %d' % count) @cli.command() @click.option('--count', default=1) @click.pass_context def dist(ctx, count): ctx.forward(test) ctx.invoke(test, count=42)
$ cli dist Count: 1 Count: 42
http://telemaco.github.io/python-click