Want to turn your script into a command line utility, but don't want the overhead of argparse?
You've come to the right place!
Simply import and wrap whatever function you'd like to expose. That's it!
Function variables are turned into CLI parameters, complete with input validation and help text generated from inline comments.
pip install pysimplecli
To convert a Python function into a CLI command, simply use the wrap
decorator from the simplecli
module. Here is a simple example:
import simplecli
@simplecli.wrap
def main(
name: str, # Person to greet
) -> None:
print(f"Hello, {name}!")
$ python3 myprogram.py --name="Dade Murphy"
Hello, Dade Murphy!
That's it!
Everything Just Works™ out of the box.
Parameters show up automatically and comments make them more friendly.
$ python3 hello.py --help
Usage:
hello.py [name]
Options:
--name Person to greet
--help Display hello.py version
$ python3 hello.py --name="Donatello 🐢"
Hello, Donatello 🐢!
Tested on Windows/Linux/Mac with Python >= 3.9.
Want to pass positional instead of named parameters? All required parameters are available in top-down order.
$ python3 hello.py "El Duderino"
Hello, El Duderino!
If you have the dunder variable __version__
set, you get a --version
parameter.
import simplecli
___version___ = "1.2.3"
@simplecli.wrap
def main(
name: str, # Person to greet
) -> None:
print(f"Hello, {name}!")
$ python3 hello.py --version
hello.py version 1.2.3
Want to add some detail to your help output? Just make a docstring in the function that's being wrapped.
import simplecli
__version__ = "1.2.3"
@simplecli.wrap
def main(
name: str, # Person to greet
) -> None:
"""
This is a utility that greets whoever engages it. It's a simple example
of how to use the `simplecli` utility module. Give it a try!
"""
print(f"Hello, {name}!")
$ python3 hello.py --help
Usage:
hello.py [name]
Description:
This is a utility that greets whoever engages it. It's a simple example
of how to use the `simplecli` utility module. Give it a try!
Options:
--name Person to greet
--help Show this message
--version Display hello.py version
A parameter becomes "required" if it is an int
, float
or str
and does not have a default.
bool
arguments cannot be required as there are only two possible states. Instead, they are False
by default and become True
when passed as a flag.
Only simple variable types (bool
, float
, int
, str
) are currently supported. Mapping and sequence types might be supported in the future but anything else is beyond the scope of this utility.
With more than one decorator, it's impossible to tell which function you'd like to wrap. Because of this, we enforce a single @wrap
per file. Importing modules using pysimplecli
is supported, as is calling said wrapped functions.
Parameter Default | Without Argument | With Argument |
---|---|---|
True |
True |
False |
False |
False |
True |
no default | False |
True |
The wrap
decorator takes the annotated parameters of a given function and maps them to corresponding command-line arguments. It relies heavily on Python's inspect
and tokenize
modules to gather parameters, parse comments for parameter descriptions, determine default functionality, etc... In fact, a core part of this module is a are heavily extended inspect.Parameter
objects.
argparse
is great for advanced input control. Unfortunately, that level of control means considerably more overhead for simple utilities. To be clear, this is not intended to replace argparse
. simplecli
is meant to easily expose a python function as a script.
(I've also felt conflicted about dunder names being used openly in if __name__ == "__main__":
)
Here's an example of an argparse
solution
import argparse
import sys
__version__ = "1.2.3"
def add(a: int = 5, b: int = 10) -> None:
print(a + b)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--a", default=5, required=True, type=int,
help="First integer to add")
parser.add_argument("--b", default=10, required=True, type=int,
help="Second integer to add")
parser.add_argument("--version", action="version",
version=f"{sys.argv[0]} version {__version__}")
args = parser.parse_args()
add(args.a, args.b)
Here's the same example, but with simplecli
from simplecli import wrap
__version__ = "1.2.3"
@wrap
def add(
a: int = 5, # First integer to add
b: int = 10, # Second integer to add
) -> None:
print(a + b)
Feel free to open an issue and create a pull request!
pysimplecli © 2024 by Clif Bratcher is licensed under CC BY 4.0