Implement minimal boilerplate CLIs derived from type hints and parse from command line, config files and environment variables.
—
Automatic CLI creation functions that generate command-line interfaces from function and class signatures with minimal boilerplate code. These functions analyze type hints and docstrings to automatically create ArgumentParser instances, parse arguments, and execute the target components.
High-level functions for creating complete command-line interfaces automatically from Python functions, classes, or modules.
def auto_cli(
components: Optional[Union[Callable, List, Dict, Type]] = None,
args: Optional[List[str]] = None,
config_help: str = "Path to a configuration file.",
set_defaults: Optional[Dict[str, Any]] = None,
as_positional: bool = True,
fail_untyped: bool = True,
parser_class: Type[ArgumentParser] = ArgumentParser,
**kwargs
) -> Any:
"""
Create a CLI from components and run it.
Args:
components: Function, class, list, or dict to create CLI from
args: Command line arguments to parse (defaults to sys.argv)
config_help: Help text for configuration file option
set_defaults: Default values to set in parser
as_positional: Whether to add component as positional argument
fail_untyped: Whether to fail on untyped parameters
parser_class: ArgumentParser class to use
**kwargs: Additional arguments for ArgumentParser
Returns:
Any: Result of running the CLI component
"""
def CLI(*args, **kwargs) -> Any:
"""
Alias for auto_cli() function.
Args:
*args: Positional arguments passed to auto_cli
**kwargs: Keyword arguments passed to auto_cli
Returns:
Any: Result of running the CLI component
"""
def auto_parser(
components: Optional[Union[Callable, List, Dict, Type]] = None,
as_positional: bool = True,
fail_untyped: bool = True,
parser_class: Type[ArgumentParser] = ArgumentParser,
**kwargs
) -> ArgumentParser:
"""
Create an ArgumentParser from components without running it.
Args:
components: Function, class, list, or dict to create parser from
as_positional: Whether to add component as positional argument
fail_untyped: Whether to fail on untyped parameters
parser_class: ArgumentParser class to use
**kwargs: Additional arguments for ArgumentParser
Returns:
ArgumentParser: Configured parser ready for parsing
"""from jsonargparse import auto_cli
def greet(
name: str,
age: int = 25,
formal: bool = False,
greeting: str = "Hello"
) -> None:
"""Greet a person.
Args:
name: Person's name
age: Person's age
formal: Use formal greeting
greeting: Greeting word to use
"""
style = "formally" if formal else "casually"
print(f"{greeting} {name}! You are {age} years old. Greeting you {style}.")
if __name__ == "__main__":
# Creates CLI automatically from function signature
auto_cli(greet)Usage:
python script.py --name Alice --age 30 --formal
python script.py --name Bob --greeting "Hi"from dataclasses import dataclass
from jsonargparse import auto_cli
@dataclass
class ProcessorConfig:
input_file: str
output_file: str
batch_size: int = 32
verbose: bool = False
class DataProcessor:
def __init__(self, config: ProcessorConfig):
self.config = config
def process(self) -> None:
"""Process the data."""
if self.config.verbose:
print(f"Processing {self.config.input_file} with batch size {self.config.batch_size}")
# Process data here
print(f"Output saved to {self.config.output_file}")
def main(config: ProcessorConfig) -> None:
"""Main processing function."""
processor = DataProcessor(config)
processor.process()
if __name__ == "__main__":
auto_cli(main)Usage:
python script.py --config.input_file data.csv --config.output_file results.csv --config.verbosefrom jsonargparse import auto_cli
from typing import Literal
def train(
model_type: Literal["cnn", "rnn", "transformer"],
epochs: int = 10,
learning_rate: float = 0.001
) -> None:
"""Train a model."""
print(f"Training {model_type} for {epochs} epochs with lr={learning_rate}")
def evaluate(
model_path: str,
test_data: str,
metrics: list[str] = ["accuracy", "f1"]
) -> None:
"""Evaluate a model."""
print(f"Evaluating model {model_path} on {test_data} using {metrics}")
if __name__ == "__main__":
# CLI with subcommands
auto_cli({
"train": train,
"evaluate": evaluate
})Usage:
python script.py train --model_type cnn --epochs 20
python script.py evaluate --model_path model.pkl --test_data test.csvfrom jsonargparse import auto_parser
def process_data(
input_path: str,
output_path: str,
format: str = "json"
) -> dict:
"""Process data from input to output."""
# Processing logic here
return {"status": "success", "format": format}
# Create parser without running
parser = auto_parser(process_data)
# Add additional arguments
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
# Parse arguments manually
config = parser.parse_args()
# Call function with parsed config
if hasattr(config, 'debug') and config.debug:
print("Debug mode enabled")
result = process_data(
input_path=config.input_path,
output_path=config.output_path,
format=config.format
)
print(result)from jsonargparse import auto_cli
def train_model(
data_dir: str,
model_name: str,
epochs: int = 100,
batch_size: int = 32,
learning_rate: float = 0.001,
optimizer: str = "adam"
) -> None:
"""Train a machine learning model.
Args:
data_dir: Directory containing training data
model_name: Name of the model architecture
epochs: Number of training epochs
batch_size: Training batch size
learning_rate: Learning rate for optimizer
optimizer: Optimizer type (adam, sgd, rmsprop)
"""
print(f"Training {model_name} model")
print(f"Data: {data_dir}")
print(f"Config: epochs={epochs}, batch_size={batch_size}, lr={learning_rate}")
print(f"Optimizer: {optimizer}")
if __name__ == "__main__":
auto_cli(train_model)With configuration file config.yaml:
data_dir: "/path/to/data"
model_name: "resnet50"
epochs: 200
batch_size: 64
learning_rate: 0.0001
optimizer: "adam"Usage:
# Use config file with command line overrides
python script.py --config config.yaml --epochs 300 --learning_rate 0.0005from jsonargparse import auto_cli
from typing import Union, Optional
class ModelA:
def __init__(self, hidden_size: int = 128, dropout: float = 0.1):
self.hidden_size = hidden_size
self.dropout = dropout
def train(self):
print(f"Training ModelA: hidden={self.hidden_size}, dropout={self.dropout}")
class ModelB:
def __init__(self, layers: int = 3, activation: str = "relu"):
self.layers = layers
self.activation = activation
def train(self):
print(f"Training ModelB: layers={self.layers}, activation={self.activation}")
def main(
model: Union[ModelA, ModelB],
epochs: int = 10,
verbose: bool = False
) -> None:
"""Train a model."""
if verbose:
print(f"Starting training for {epochs} epochs")
model.train()
if __name__ == "__main__":
auto_cli(main)Usage:
# Specify model class and its parameters
python script.py --model ModelA --model.hidden_size 256 --model.dropout 0.2 --epochs 50
python script.py --model ModelB --model.layers 5 --model.activation tanh --verbosestr, int, float, boolList, Dict, Set, TupleOptional[T], Union[T, None]Literal["option1", "option2"]Union[TypeA, TypeB]List[int], Dict[str, float]pathlib.Path and custom path typesInstall with Tessl CLI
npx tessl i tessl/pypi-jsonargparse