Turn any Python function into a CLI command with zero boilerplate. Just add @cmdline and your function signature becomes the interface.
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file optfunc2-0.2.8.tar.gz.
File metadata
- Download URL: optfunc2-0.2.8.tar.gz
- Upload date:
- Size: 7.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29cc0012525b7352bd48163a3c8babb4fda523ebd0664a09faa1fe74b0475b72
|
|
| MD5 |
79d3e50289728ec706e3f5b441883694
|
|
| BLAKE2b-256 |
274f84106eae475e2ec521d99c19c6866e5b8d04f8ec12c4b1d357923adbe713
|
File details
Details for the file optfunc2-0.2.8-py3-none-any.whl.
File metadata
- Download URL: optfunc2-0.2.8-py3-none-any.whl
- Upload date:
- Size: 8.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24ce8a5537302aa81e27f8f1e97ec585cb19de3c564169bce40dee8f145cc779
|
|
| MD5 |
8870c5718fd420363ad9739da86fff0b
|
|
| BLAKE2b-256 |
eabcd44545c35c007ea7f8cf476f40619c0f844d72bb84bd243024eec04509a9
|