protocli
Signature-driven CLI dispatcher: typed function signatures become argparse parsers, modules become lazily-imported subcommands, with nested dispatch, --help-all and lazy shell completions.
# mytool/__main__.py
from protocli import Dispatcher
Dispatcher(
"mytool",
{
"greet": greet, # a callable: its signature IS the parser
"db": "mytool.db", # a module path: lazy-imported on dispatch
"cache": Dispatcher( # a nested group, listed with its doc
"mytool cache", {"clear": clear}, doc="Cache tools."
),
},
).run()
run(argv=None) dispatches argv (default sys.argv[1:]) and returns the leaf's int result as the exit code, 0 for anything else, so main = Dispatcher(...).run serves as a console-script entry point and main(["greet", "ada"]) drives it from tests.
A callable (or a module's main) maps to CLI arguments by signature:
def greet(
name: str, # required positional
title: str | None = None, # optional positional
*rest: str, # variadic
loud: bool = False, # --loud (keyword-only, default False)
times: int = 1, # --times N
lang: Literal["en", "hu"] = "en", # --lang restricted to choices
tags: list[str] = [], # --tags a,b,c (comma-separated)
): ...
Each parameter's --help text comes from the function's Google-style Args: section; continuation lines are joined:
def pull(source: str, *, dest: str | None = None):
"""Download a published dataset.
Args:
source: project URL or path
dest: target directory, the pull cache when omitted
"""
Dynamic completions
Literal fixes a closed set the parser enforces. Complete carries candidates the parser never sees — computed on demand, when the shell asks and only then:
from typing import Annotated
from protocli import Complete, FILES
Machine = Annotated[str, Complete(inventory.get_names)] # any () -> Sequence[str]
def deploy(*names: Machine, config: Annotated[str, FILES] = ""): ...
deploy <TAB> offers the machine names, dropping the ones already typed (Complete(fn, repeat=True) keeps them); --config <TAB> defers to the shell's native pathname completion.
The completer runs on the --complete path alone — never on dispatch, never under --help-all. Its values are advisory and never become argparse choices, so an unknown value reaches the function and is rejected there, with the function's own error. That is the difference from Literal, and the reason the two are exclusive on one parameter.
Completion resolves which parameter the cursor sits on, so positionals, variadics and flag values all complete, and a flag already given is not offered again. A module can instead expose a get_completions(rest) hook when candidates depend on more than one argument, or its own nested _dispatcher = Dispatcher(...).
mytool --help-all prints every parser in the tree.
Auto-discovery over a package's public modules:
Dispatcher.from_package("mytool").run()
Bash completion
mytool --bash-completion prints the bash script that completes mytool and every alias onto it; on each TAB it asks mytool --complete <words before the cursor> for candidates. Load it from ~/.bashrc, after the aliases:
eval "$(mytool --bash-completion)"
To start the tool only on its first TAB, put this line in a file named after the tool in ~/.local/share/bash-completion/completions/. The line is the same for every tool, and an alias onto the tool completes once the tool's script has loaded:
eval "$("${BASH_SOURCE##*/}" --bash-completion 2>/dev/null)"
Metadata
Release files for protocli 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| protocli-0.4.0.tar.gz | 16.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| protocli-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.8 kB
Release files / protocli-0.4.0.tar.gz
| Download URL | protocli-0.4.0.tar.gz |
|---|---|
| Size | 16.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef0900eff589b60f5f47f0da21a7af0bbae07a3f3e7bd6260b6d766fda8edad0
|
|
BLAKE2b-256 checksum How to use checksums |
1c93cdd906600764870eed113b1cc2e08ea33f747bdd5d56a954f001b0466ae5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / protocli-0.4.0-py3-none-any.whl
| Download URL | protocli-0.4.0-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d2267837a3ade1ebcaf609d5671652954346eeca976b717391e1582540e7c904
|
|
BLAKE2b-256 checksum How to use checksums |
0fd096e53710f3b7c1398226aaf61d67fab0c939166fd9aaa71f46012b9b2caa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for protocli 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.