CLI + config application
Project description
Tuler
A tool for building python CLIs
What does it do?
Tuler is heavily inspired by Typer, another CLI tool, with a few key differences.
Here is the basic pattern for Tuler.
from tuler import App
app = App()
@app.command()
def greet_friend():
print("hey friend!")
if __name__ == "__main__":
app.run()
$ python3 foo.py greet_friend
hey friend!
@app.command() registers greet_friend as a command in app. app.run() will parse sys.argv and either run greet_friend() or display a help message.
You can register multiple commands that use arguments and options.
from tuler import App
app = App()
@app.command()
def greet_friend(name):
print(f"hey {name}!")
@app.command()
def greet_with_message(name, message="my friend!"):
print(f"hello {name}, {message}")
if __name__ == "__main__":
app.run()
$ python3 foo.py greet_friend Leo
hey Leo!
$ python3 foo.py greet_with_message Mark --message "a handshake is available on request."
hello Mark, a handshake is available on request.
You also get a built in help screen.
$ python3 foo.py --help
USAGE: foo.py <COMMAND> [OPTIONS]
COMMANDS:
greet_friend
greet_with_message
$ python3 foo.py greet_friend --help
USAGE: foo.py greet_with_message <ARGUMENTS> [OPTIONS]
ARGUMENTS:
<NAME>
GREET_WITH_MESSAGE OPTIONS:
--message [default: 'you fool!']
Tuler handles global options by using templates.
from tuler import App
from dataclasses import dataclass
@dataclass
class GlobalOptionsTemplate:
verbose: bool = False
directory: str = "/"
app = App(GlobalOptionsTemplate)
@app.command()
def print_global_opts():
print("verbose:", app.opts.verbose)
print("directory:", app.opts.directory)
if __name__ == "__main__":
app.run()
$ python3 foo.py print_global_opts
verbose: False
directory: /
$ python3 foo.py print_global_opts --verbose --directory "/dev/"
verbose: True
directory: /dev/
A template is a dataclass that lays out options via fields. All fields must have default values. When a template is passed into App(), app.opts is the initialized template dataclass with the values of your options.
Arguments and options can be annotated to include additional metadata.
from dataclasses import dataclass
from typing import Annotated
from tuler import App, Argument, Flag, Option
@dataclass
class GlobalOptionsTemplate:
verbose: Annotated[
bool,
Flag(
short_name="v",
hint="How much output should the program produce",
),
] = False
directory: Annotated[
str,
Option(
short_name="d",
hint="Which directory to print.",
),
] = "/"
app = App(GlobalOptionsTemplate)
@app.command()
def magic(
x: Annotated[
int,
Argument(
hint="Magical argument",
parser=int,
validator=lambda v: v > 100,
),
],
):
print(x)
if __name__ == "__main__":
app.run()
$ python3 foo.py --help
USAGE: foo.py <COMMAND> [OPTIONS]
COMMANDS:
magic
OPTIONS:
-v --[no-]verbose How much output should the program produce [default: no-verbose]
-d --directory Which directory to print. [default: '/']
$ python3 foo.py magic --help
USAGE: foo.py magic <ARGUMENTS> [OPTIONS]
ARGUMENTS:
<X> Magical number that must be greater than 100
OPTIONS:
-v --[no-]verbose How much output should the program produce [default: no-verbose]
-d --directory Which directory to print. [default: '/']
$ python3 foo.py magic 50
Argument <X> did not pass validation!
You can also pass in a configuration toml file to App().
from tuler import App
from dataclasses import dataclass
@dataclass
class Options:
verbose: bool = False
foo: str = "bar"
app = App(config_file="config.toml")
@app.command()
def greet_friend(name):
print(f"hey {name}!")
@app.command()
def greet_with_message(name, message="my friend!"):
print(f"hello {name}, {message}")
if __name__ == "__main__":
app.run()
config.toml:
verbose = true
foo = "bazz"
[greet_with_message]
message = "from config!"
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 tuler-0.1.0.tar.gz.
File metadata
- Download URL: tuler-0.1.0.tar.gz
- Upload date:
- Size: 9.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a7edcf94eb7bf7a5f30818f8e5873767644c45fd81cf7088ebe7c3a58b0d190
|
|
| MD5 |
38de2176f043ad30d1c9ce0cd0755284
|
|
| BLAKE2b-256 |
b1c7feecd969f89aff95aa4afc707e8718727d8c606fe5049e1c946439cd339d
|
File details
Details for the file tuler-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tuler-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7776c2cbde4fc168ebcff8b45afbb26fa24c1c74f5a7ca7a1548a822faa9fcda
|
|
| MD5 |
568a8eea07bea37d591bd15276b629e7
|
|
| BLAKE2b-256 |
bbc83688d11a3acd3079e47d3e88dd583e772e5615bea47888c6426cf1aedec0
|