without-cli
Command-line parsing as values. A token is one declaration that is the parse, the help entry, and the typed read at once; a command is a value you can pass around rather than a decorator's side effect; and parsing is a pure function from argv to an outcome, so nothing is registered anywhere and nothing exits out from under you.
@dataclass(frozen=True, slots=True)
class Session(Streams):
client: Client
@command("add", argument("text", once(STR)), option(("-t", "--tag"), many(STR)), summary="Add a todo.")
async def add(session: Session, text: str, tags: tuple[str, ...]) -> int:
todo = await session.client.create(text, tags)
session.stdout.write(f"{todo.id}\n")
return 0
app = group("todos", verbose, endpoint, state=session, commands=(add, show, db))
if __name__ == "__main__":
raise SystemExit(run(app))
state is an async context manager, entered only when something beneath it is
selected, so every command receives a live client it did not open and does not
close, typed and checked, with no ambient context object. There is no separate
root concept: the top of a tree is an ordinary group whose parent is the shell,
which supplies the Streams it derives from, so a CLI with no shared resource
declares no state and its commands take that Streams directly. An option can name
where else its value may come from (sources=(FromFile(...), FromEnv(...))),
which covers environment variables and Kubernetes or Docker secret mounts through
the same validation the command line goes through.
Help is a Usage value that plain text is one rendering of, so no styling
library sits on the path every program crosses and this package depends on
nothing. The streams are injected, so a test asserts on output by passing
Streams.captured(), with no subprocess and no runner.
See the
without-cli guide
(with the API reference)
for the full surface, including what is deliberately absent, and
alternatives for the same
program written against argparse, click, and typer.
Release files for without-cli 0.0.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| without_cli-0.0.9.tar.gz | 24.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| without_cli-0.0.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.4 kB
Release files / without_cli-0.0.9.tar.gz
| Download URL | without_cli-0.0.9.tar.gz |
|---|---|
| Size | 24.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7c377a73760be3772ff579b758c7cf1b2f7614224327e46784e9fd1ad962a879
|
|
BLAKE2b-256 checksum How to use checksums |
c2bcd506aa12e9b2d444ee14d1a8dd7cf70169ac516fdcd83f1d21f5f086db2b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.14 {"installer":{"name":"uv","version":"0.12.14","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 / without_cli-0.0.9-py3-none-any.whl
| Download URL | without_cli-0.0.9-py3-none-any.whl |
|---|---|
| Size | 29.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0f4f5284e1ac65643e25a246cee39116f844689b71431e7a0f12903d285a09dd
|
|
BLAKE2b-256 checksum How to use checksums |
f700b6b93ef8824c50d701c7613e1719f52f42bff6d549a3e0a738c7b9dd1f96
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.14 {"installer":{"name":"uv","version":"0.12.14","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}
|