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