optfunc2
Auto-generate CLI from Python functions — zero boilerplate.
Turn any Python function into a CLI command — no
argparse, noclick, no boilerplate. Just add a decorator and your function's signature becomes the interface.
Why optfunc2?
| optfunc2 | argparse | click | typer | |
|---|---|---|---|---|
| Lines to add a CLI command | ~1 (decorator) | ~15 | ~8 | ~5 |
| Auto-generated help from docstring | ✅ | ❌ | ❌ | ✅ |
| Type coercion from annotations | ✅ | Manual | Manual | ✅ |
Shell abbreviation (-a for --arg) |
✅ | ❌ | ❌ | ❌ |
Hex input support (0x2A) |
✅ | ❌ | ❌ | ❌ |
| Dependencies | 1 (docstring-parser) |
stdlib | click | typer+click |
| External dependencies | prettytable (optional) | 0 | 7+ | 20+ |
Union types (int | float) |
✅ | ❌ | ❌ | ✅ |
Install
pip install optfunc2
Quick Start
from optfunc2 import cmdline, cmdline_default, cmdline_start
@cmdline_default
def add(a: float, b: float):
"""Add two numbers
Args:
a: The first number
b: The second number
"""
print(f"{a} + {b} = {a + b}")
@cmdline
def multiply(x: int | float, y: int = 5):
"""Multiply two numbers
Args:
x: The first number
y: The second number (default 5)
"""
print(f"{x} × {y} = {x * y}")
if __name__ == "__main__":
cmdline_start(header_doc="✨ calc CLI", has_abbrev=True)
$ python calc.py add --a 2.3 --b 3 # 2.3 + 3.0 = 5.3
$ python calc.py add -a 2.3 -b 3 # abbreviation works too
$ python calc.py multiply --x 3 # 3 × 5 = 15
$ python calc.py # uses default command
$ python calc.py help # show all commands
$ python calc.py add -h # show command help
Features
Decorators
| Decorator | Description |
|---|---|
@cmdline |
Register a function as a CLI command |
@cmdline_default |
Same as above, but also the default when no command is given |
Type Support
| Type | Input Example | Notes |
|---|---|---|
int |
--n 42 or --n 0x2A |
Hex format supported |
float |
--r 3.14 |
|
str |
--name hello |
|
bool |
--verbose (no value needed) |
|
list |
--items '[1, 2, 3]' |
Parsed via ast.literal_eval |
dict |
--cfg '{"key": "val"}' |
Parsed via ast.literal_eval |
int | float |
--x 3 or --x 2.5 |
Union types supported |
Argument Styles
# All of these are equivalent:
python app.py my_cmd --name hello --count 3
python app.py my_cmd --name=hello --count=3
python app.py my_cmd -n hello -c 3 # abbreviations (when has_abbrev=True)
python app.py my_cmd -nhello -c3 # abbreviation + value combined
cmdline_start() Options
cmdline_start(
header_doc="My App", # Header text shown in help
has_abbrev=True, # Enable single-char abbreviation (-a for --arg)
print_retval=False, # Print return value to stdout
)
called_directly()
Check if the current function was invoked by optfunc2 (vs. called by another function):
@cmdline
def main():
if called_directly():
print("Called from CLI")
else:
print("Called from another function")
Help Output
$ python calc.py help
Usage: calc.py [command] [<args>|--help]
✨ calc CLI
commands:
add [default] Add two numbers
multiply Multiply two numbers
$ python calc.py add -h
Usage: calc.py add [OPTIONS]
Add two numbers
Arguments:
+------+--------+-------+---------+------------------+
| Opt | Abbrev | Type | Default | Desc |
+------+--------+-------+---------+------------------+
| --a | -a | float | | The first number |
| --b | -b | float | | The second number|
+------+--------+-------+---------+------------------+
Real-World Example
from optfunc2 import cmdline, cmdline_default, cmdline_start
import os
@cmdline_default
def list_files(directory: str = ".", show_size: bool = False):
"""List files in a directory
Args:
directory: Target directory (default ".")
show_size: Show file size in bytes
"""
for f in os.listdir(directory):
path = os.path.join(directory, f)
if show_size and os.path.isfile(path):
print(f"{f} ({os.path.getsize(path)} bytes)")
else:
print(f)
if __name__ == "__main__":
cmdline_start(header_doc="📁 file manager", has_abbrev=True)
Limitations
- Variadic arguments (
*args,**kwargs) are not supported - Abbreviation conflicts (e.g.,
textandtestboth want-t) are resolved silently — first one wins - Negative numbers as values require
--arg=-1syntax (not--arg -1)
License
PyPA License — see LICENSE.txt
Metadata
Release files for optfunc2 0.2.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| optfunc2-0.2.8.tar.gz | 7.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| optfunc2-0.2.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.7 kB
Release files / optfunc2-0.2.8.tar.gz
| Download URL | optfunc2-0.2.8.tar.gz |
|---|---|
| Size | 7.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
29cc0012525b7352bd48163a3c8babb4fda523ebd0664a09faa1fe74b0475b72
|
|
BLAKE2b-256 checksum How to use checksums |
274f84106eae475e2ec521d99c19c6866e5b8d04f8ec12c4b1d357923adbe713
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / optfunc2-0.2.8-py3-none-any.whl
| Download URL | optfunc2-0.2.8-py3-none-any.whl |
|---|---|
| Size | 8.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
24ce8a5537302aa81e27f8f1e97ec585cb19de3c564169bce40dee8f145cc779
|
|
BLAKE2b-256 checksum How to use checksums |
eabcd44545c35c007ea7f8cf476f40619c0f844d72bb84bd243024eec04509a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|