Skip to main content

A simple task runner that generates command line interfaces

Project description

A simple task runner that generates command line interfaces

from cleek import task

@task
def binary_op(x: int, y: int, op: Literal['add', 'sub'] = 'add') -> None:
    print(x, op, y)

⬇️ Becomes ⬇️

$ clk binary-op -h
usage: clk binary-op [-h] [-o {add,sub}] x y

positional arguments:
  x
  y

options:
  -h, --help          show this help message and exit
  -o, --op {add,sub}  default: add

Install

$ git clone https://github.com/petersuttondev/cleek.git
$ pip install ./cleek

Get Started

  1. Create a cleeks.py file in the root of your project and add tasks
from cleek import task

@task
def greet(name: str) -> None:
    print(f'Hello, {name}!')
  1. Run clk from anywhere inside your project to see your tasks.
$ clk
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Task  ┃ Usage               ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ greet │ clk greet [-h] name │
└───────┴─────────────────────┘
  1. Run clk <task> -h to print a task's help.
$ clk greet
usage: clk greet [-h] name

positional arguments:
  name

options:
  -h, --help  show this help message and exit

Finally, run a task:

$ clk greet Peter
Hello, Peter!

Customizing Tasks

  • Set a task's name:
from cleek import task

@task('bar')
def foo() -> None:
    print('foo function, bar task')
$ clk bar
foo function, bar task
  • Set a task's group:
from cleek import task

@task(group='foo')
def bar() -> None:
    print('bar task in the foo group')
$ clk foo.bar
bar task in the foo group
from cleek import task

@task(style='red')
def foo() -> None:
    print("I'll be red if you run clk")
  • To apply the same customization to many tasks, use customize() to create a pre-configured version of the task decorator.
from cleek import customize

foo_task = customize('foo', style='red')

@foo_task
def a() -> None: ...

@foo_task
def b() -> None: ...

bar_task = customize('bar', style='blue')

@bar_task
def c() -> None: ...

@bar_task
def d() -> None: ...
$ clk
┏━━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ Task  ┃ Usage          ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━┩
│ foo.a │ clk foo.a [-h] │
│ foo.b │ clk foo.b [-h] │
│ bar.c │ clk bar.c [-h] │
│ bar.d │ clk bar.d [-h] │
└───────┴────────────────┘

Async Support

Your tasks can be async functions:

from cleek import task
import trio

@task
async def sleep(duration: float = 1.0) -> None:
    print(f'Sleeping for {duration} seconds')
    await trio.sleep(duration)

At the moment, trio is the only supported event loop. If want to use another event loop (I'm guessing asyncio), open an issue and I'll add it.

Finding Tasks

  1. If the environmental variable CLEEKS_PATH is set, clk treats the value as a path and attempts to load it. If the load fails, clk fails.

  2. clk searches upwards from the current working directory towards the root directory /, looking for a cleeks.py script or a cleeks package. A script takes precedence over a package if both are found in the same directory.

Supported Parameters

If you get an error saying your task's parameters are not supported, open an issue containing the function signature and I'll add support.

bool

  • Keyword bool with False or True default
def foo(a: bool = False): ...
def foo(a: bool = True): ...
  • Keyword optional bool with False, True, or None default
def foo(a: bool | None = False): ...
def foo(a: bool | None = True): ...
def foo(a: bool | None = None): ...

str

  • Positional str
def foo(a: str): ...
  • Positional optional str
def foo(a: str | None): ...
  • Keyword str with str default
def foo(a: str = 'a'): ...
  • Keyword optional str with str or None default
def foo(a: str | None = 'a'): ...
def foo(a: str | None = None): ...
  • Variadic positional str
def foo(*a: str): ...

int

  • Positional int
def foo(a: int): ...
  • Keyword int with int default
def foo(a: int = 1): ...
  • Keyword optional int with int or None default
def foo(a: int | None = 1): ...
def foo(a: int | None = None): ...

float

  • Positional float
def foo(a: float): ...
  • Keyword float with float default
def foo(a: float = 1.0): ...
  • Keyword optional float with float or None default
def foo(a: float | None = 1.0): ...
def foo(a: float | None = None): ...

Literal[T]

  • Positional int literal
@task
def foo(a: Literal[1, 2, 3]): ...
  • Positional str literal
@task
def foo(a: Literal['a', 'b', 'c']): ...
  • Keyword int literal with int default
@task
def foo(a: Literal[1, 2, 3] = 1): ...
  • Keyword str literal with str default
@task
def foo(a: Literal['a', 'b', 'c'] = 'a'): ...

Misc

  • Variadic positional pathlib.Path
from pathlib import Path

@task
def foo(*a: Path): ...
  • Variadic positional trio.Path
from trio import Path

@task
def foo(*a: Path): ...

Shell Completion

clk --completion prints all task names to stdout.

zsh

_complete_clk() {
    reply=($(clk --completion))
}

compctl -K _complete_clk + -f clk

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

cleek-0.0.1.tar.gz (54.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cleek-0.0.1-py3-none-any.whl (9.6 kB view details)

Uploaded Python 3

File details

Details for the file cleek-0.0.1.tar.gz.

File metadata

  • Download URL: cleek-0.0.1.tar.gz
  • Upload date:
  • Size: 54.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for cleek-0.0.1.tar.gz
Algorithm Hash digest
SHA256 bfc3ccfc44024aced5ac0203ca3d8c9c63c68c9a0c3481c9f375bcb9ad830c2c
MD5 85264db4f957a916c4350822643ae62e
BLAKE2b-256 3c31a4777364b5d44ac7fc4d76a31359a81eaa133649c96569fb9ead434b9cd2

See more details on using hashes here.

File details

Details for the file cleek-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: cleek-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 9.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for cleek-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9ccd8e4407110ff51d52168a2b3e40bcb463292a2c1846027e0c223b116b598c
MD5 da9d70bd366e514697850ac8e4020b0c
BLAKE2b-256 73d694627f28828dccec784408d4a931a5698581383c4dae36389fd1e3f32f74

See more details on using hashes here.

Supported by

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