Warning
startle is alpha and should be considered unstable as its interface is fluid 😅, consider pinning to a version.
startle lets you transform a python function into a command line entry point, e.g:
wc.py
:
from pathlib import Path
from typing import Literal
from startle import start
def word_count(
fname: Path, /, kind: Literal["word", "char"] = "word", *, verbose: bool = False
) -> None:
"""
Count the number of words or characters in a file.
Args:
fname: The file to count.
kind: Whether to count words or characters.
verbose: Whether to print additional info.
"""
text = open(fname).read()
count = len(text.split()) if kind == "word" else len(text)
print(f"{count} {kind}s in {fname}" if verbose else count)
start(word_count)
❯ python wc.py --help
:
When you invoke start
, it will construct an argparser (based on type hints and docstring),
parse the arguments, and invoke word_count
.
❯ python wc.py wc.py -k char --verbose
:
startle is inspired by Typer, and Fire, but aims to be non-intrusive, to have stronger type support, and to have saner defaults. Thus, some decisions are done differently:
- Use of positional-only or keyword-only argument separators (
/
,*
, see PEP 570, 3102) are naturally translated into positional arguments or options. See above example (wc.py). - Like Typer and unlike Fire, type hints strictly determine how the individual arguments are parsed and typed.
- Short forms (e.g.
-k
,-v
above) are automatically provided based on the initial of the argument. - Variable length arguments are more intuitively handled.
You can use
--things a b c
(in addition to--things=a --things=b --things=c
). See example. - Like Typer and unlike Fire, help is simply printed and not displayed in pager mode by default, so you can keep referring to it as you type your command.
- Like Fire and unlike Typer, docstrings determine the description of each argument in the help text, instead of having to individually add extra type annotations. This allows for a very non-intrusive design, you can adopt (or un-adopt) startle with no changes to your functions.
*args
but also**kwargs
are supported, to parse unknown arguments as well as unknown options (--unk-key unk-val
). See example.
See all examples.