Skip to main content

No project description provided

Project description

click-anno

GitHub Build Status PyPI

use annotation to create click app.

Compare with click api

Basic Arguments

# click
import click

@click.command()
@click.argument('filename')
def touch(filename):
    click.echo(filename)

# click_anno
import click
import click_anno

@click_anno.command
def touch(filename):
    click.echo(filename)

Variadic Arguments

# click
import click

@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))

# click_anno
import click
import click_anno

@click_anno.command
def copy(src: tuple, dst):
    for fn in src:
        click.echo('move %s to folder %s' % (fn, dst))

Basic Value Options

# click
import click

@click.command()
@click.option('--n', default=1)
def dots(n):
    click.echo('.' * n)

# click_anno
import click
import click_anno

@click_anno.command
def dots(n=1):
    click.echo('.' * n)

Required Value Options

# click
import click

@click.command()
@click.option('--n', required=True, type=int)
def dots(n):
    click.echo('.' * n)

# click_anno
import click
import click_anno

@click_anno.command
def dots(*, n: int):
    click.echo('.' * n)

Multi Value Options

# click
import click

@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
    click.echo('%s / %s' % pos)

# click_anno
from typing import Tuple
import click
import click_anno

@click_anno.command
def findme(*, pos: Tuple[float, float]):
    click.echo('%s / %s' % pos)

Tuples as Multi Value Options

# click
import click

@click.command()
@click.option('--item', type=(str, int))
def putitem(item):
    click.echo('name=%s id=%d' % item)

# click_anno
from typing import Tuple
import click
import click_anno

@click_anno.command
def putitem(*, item: (str, int)):
    click.echo('name=%s id=%d' % item)

Boolean Flags

# click
import click

@click.command()
@click.option('--shout', is_flag=True)
def info(shout):
    click.echo(f'{shout!r}')

# click_anno
import click
from click_anno import command
from click_anno.types import flag

@command
def func(shout: flag):
    click.echo(f'{shout!r}')

Inject Context

# click
@command()
@click.pass_context
def sync(ctx): # `ctx` must be the 1st arg
    click.echo(str(type(ctx)))

# click_anno
@command
def sync(a, ctx: click.Context, b): # `ctx` can be any location
    click.echo(str(type(ctx)))

Group

# click
@click.group()
def cli():
    click.echo('Running')

@cli.command()
def sync():
    click.echo('Syncing')

# click_anno
@click_app
class App:
    def __init__(self):
        click.echo('Running')

    def sync(self):
        click.echo('Syncing')

Extensions

Enum

Enum is NOT Choice.

# click
# does not support

# click_anno
import click
from click_anno import command
from enum import Enum, auto

class HashTypes(Enum):
    md5 = auto()
    sha1 = auto()

@command
def digest(hash_type: HashTypes):
    assert isinstance(hash_type, HashTypes)
    click.echo(hash_type)

Alias

# click
# does not support

# click_anno
@click_app
class App:
    def sync(self):
        click.echo('Syncing')

    alias = sync

show default in argument

by default, click.argument did not accept show_default option.

click_anno was modify this.

@command
def func(a=10, *_):
    pass

# with --help
# Usage: func [OPTIONS] [A=10]
# ...

Arguments vs Options

click only has two kinds of parameters:

  • Options
  • Arguments - work similarly to options but are positional.

By default in python, arguments like *args and options like **kwargs.

In example func(a, b=1, *args, d, e=2), a b args are arguments, d e are options.

If you don't want the args *args, rename it to *_. click_anno will ignore all args named _

In example func(a, b=1), *args did not exists. so a is argument, b is option.

Auto Inject Arguments

by default, you can inject click.Context by annotation:

@command
def inject_context(a, ctx: click.Context, b): # `ctx` can be any location
    click.echo(str(type(ctx)))

or impl the Injectable:

from click_anno import Injectable

class Custom(Injectable):
    @classmethod
    def __inject__(cls):
        return cls()

@command
def inject_it(obj: Custom):
    assert isinstance(obj, Custom)

or call inject function:

from click_anno import inject

class Custom: pass

inject(Custom, lambda: Custom())

@command
def inject_it(obj: Custom):
    assert isinstance(obj, Custom)

or if you want to inject from click.Context.ensure_object() or click.Context.find_object(), you can use:

from click_anno import find, ensure

@command
def inject_it(f: find(A), e: ensure(B)):
    ...

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

click_anno-0.1.1.tar.gz (9.4 kB view hashes)

Uploaded Source

Built Distribution

click_anno-0.1.1-py3-none-any.whl (10.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page