Declarative CLI parser with type hints, config files, and environment variables - zero dependencies
Project description
argclass
Declarative CLI parser with type hints, config files, and environment variables.
Build type-safe command-line interfaces using Python classes. Zero dependencies.
Installation
pip install argclass
Quick Start
import argclass
class Server(argclass.Parser):
host: str = "127.0.0.1"
port: int = 8080
debug: bool = False
server = Server()
server.parse_args(["--host", "0.0.0.0", "--port", "9000", "--debug"])
assert server.host == "0.0.0.0"
assert server.port == 9000
assert server.debug is True
$ python server.py --host 0.0.0.0 --port 9000 --debug
Features
| Feature | argclass | argparse | click/typer |
|---|---|---|---|
| Type hints | Yes | No | Yes |
| IDE autocompletion | Yes | No | Yes |
| Config files | Built-in | No | No |
| Environment variables | Built-in | No | Plugin |
| Secret masking | Built-in | No | No |
| Dependencies | stdlib | stdlib | Many |
Examples
Type Annotations
import argclass
from pathlib import Path
class Parser(argclass.Parser):
name: str # required
count: int = 10 # optional with default
config: Path | None = None # optional path
files: list[str] # list of values
parser = Parser()
parser.parse_args(["--name", "test", "--files", "a.txt", "b.txt"])
assert parser.name == "test"
assert parser.count == 10
assert parser.files == ["a.txt", "b.txt"]
Argument Groups
import argclass
class DatabaseGroup(argclass.Group):
host: str = "localhost"
port: int = 5432
class Parser(argclass.Parser):
debug: bool = False
db = DatabaseGroup()
parser = Parser()
parser.parse_args(["--db-host", "db.example.com", "--db-port", "3306"])
assert parser.db.host == "db.example.com"
assert parser.db.port == 3306
Configuration Files
Load default values from configuration files. INI by default, JSON/TOML via config_parser_class.
See Config Files for details.
import argclass
from pathlib import Path
from tempfile import NamedTemporaryFile
class Parser(argclass.Parser):
host: str = "localhost"
port: int = 8080
# Config file content
CONFIG_CONTENT = """
[DEFAULT]
host = example.com
port = 9000
"""
with NamedTemporaryFile(mode="w", suffix=".ini", delete=False) as f:
f.write(CONFIG_CONTENT)
config_path = f.name
parser = Parser(config_files=[config_path])
parser.parse_args([])
assert parser.host == "example.com"
assert parser.port == 9000
Path(config_path).unlink()
Tip: Use os.getenv() for dynamic config paths. Multiple files are merged
(later overrides earlier), enabling global defaults with user overrides:
import os
import argclass
class Parser(argclass.Parser):
host: str = "localhost"
parser = Parser(config_files=[
os.getenv("MYAPP_CONFIG", "/etc/myapp/config.ini"), # Global defaults
"~/.config/myapp.ini", # User overrides (partial config OK)
])
Environment Variables
import os
import argclass
os.environ["APP_HOST"] = "env.example.com"
os.environ["APP_DEBUG"] = "true"
class Parser(argclass.Parser):
host: str = "localhost"
debug: bool = False
parser = Parser(auto_env_var_prefix="APP_")
parser.parse_args([])
assert parser.host == "env.example.com"
assert parser.debug is True
del os.environ["APP_HOST"]
del os.environ["APP_DEBUG"]
Subcommands
import argclass
class ServeCommand(argclass.Parser):
"""Start the server."""
host: str = "0.0.0.0"
port: int = 8080
def __call__(self) -> int:
print(f"Serving on {self.host}:{self.port}")
return 0
class CLI(argclass.Parser):
verbose: bool = False
serve = ServeCommand()
if __name__ == "__main__":
cli = CLI()
cli.parse_args()
exit(cli())
$ python app.py serve --host 127.0.0.1 --port 9000
Serving on 127.0.0.1:9000
Secrets
import argclass
class Parser(argclass.Parser):
api_key: str = argclass.Secret(env_var="API_KEY")
# SecretString prevents accidental logging
# repr() returns '******', str() returns actual value
Documentation
Full documentation at docs.argclass.com:
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 argclass-1.6.0.tar.gz.
File metadata
- Download URL: argclass-1.6.0.tar.gz
- Upload date:
- Size: 65.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f9f2c60fa577f9f8378019d1d3d8a16cb663b18978b4b0f7fce46efeb74569e
|
|
| MD5 |
8dde42b2e5b8ccd246785a1d77dfc054
|
|
| BLAKE2b-256 |
e650d121e95868a413013f6606a860812bc26d15c9207f423ede5c84550323a1
|
File details
Details for the file argclass-1.6.0-py3-none-any.whl.
File metadata
- Download URL: argclass-1.6.0-py3-none-any.whl
- Upload date:
- Size: 32.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2bb130d4aaa44964de6aefa006d18a1b6570a87d7088062e61a1f1f9bfd92ef
|
|
| MD5 |
77f7b35fdbfc6d2d294369fcbe327d77
|
|
| BLAKE2b-256 |
46269e3be615fcf85e30fece078379732754ce946d75e0a07d604307da5614a5
|