Skip to main content

A simple typed argument parser using dataclasses and type hints. This project is largely generated by LLMs.

Project description

SimpleArgParser

A simple typed argument parser for Python built on dataclasses. Define your config as a class, get CLI parsing, validation, and serialization.

This project is largely generated by LLMs.

Installation

pip install -U simpleArgParser
uv add simpleArgParser

Quick Start

from dataclasses import dataclass
from simpleArgParser import parse_args

@dataclass
class Config:
    name: str           # required (no default)
    epochs: int = 10    # optional with default
    lr: float = 0.001

config = parse_args(Config)
python main.py --name experiment1 --epochs 20

Features

Required and Optional Arguments

Fields without defaults are required. Fields with defaults are optional.

@dataclass
class Config:
    required_field: str                # must be provided
    optional_field: int = 42           # has a default
    optional_none: float | None = None # optional, defaults to None
python main.py --required_field hello
python main.py --required_field hello --optional_none 3.14
python main.py --required_field hello --optional_none none  # explicitly set to None

Bool Arguments

Accepts true/false, yes/no, t/f, y/n, 1/0 (case-insensitive).

@dataclass
class Config:
    verbose: bool = False
python main.py --verbose true
python main.py --verbose yes

Enum Arguments

Pass in the enum member name. Choices are displayed in --help.

import enum

class Mode(enum.Enum):
    train = "train"
    eval = "eval"

@dataclass
class Config:
    mode: Mode = Mode.train
python main.py --mode eval

List Arguments

Comma-separated values. Supports none to pass None.

@dataclass
class Config:
    devices: list[int] | None = None
python main.py --devices 0,1,2
python main.py --devices none

Nested Dataclasses

Nest dataclasses as fields. Arguments use dot-separated names. Unique field names get short aliases automatically.

@dataclass
class OptimizerConfig:
    lr: float = 0.001
    weight_decay: float = 0.01

@dataclass
class Config:
    name: str = "exp"
    optimizer: OptimizerConfig = field(default_factory=OptimizerConfig)
# full path always works
python main.py --optimizer.lr 0.01

# short alias works when the name is unique across all fields
python main.py --lr 0.01 --weight_decay 0.05

Inheritance

Child dataclasses inherit parent fields. You can override defaults.

@dataclass
class BaseConfig:
    seed: int = 42
    verbose: bool = False

@dataclass
class TrainConfig(BaseConfig):
    lr: float = 0.001
    verbose: bool = True  # override parent default
python main.py --seed 123 --lr 0.01

Comments as Help Text

Comments above or inline with fields are extracted and shown in --help.

@dataclass
class Config:
    # Learning rate for the optimizer
    lr: float = 0.001
    epochs: int = 10  # number of training epochs
python main.py --help
# shows:
#   --lr      (type: float) (default: 0.001) Learning rate for the optimizer
#   --epochs  (type: int) (default: 10) number of training epochs

JSON Config Loading

Use SpecialLoadMarker to load defaults from a JSON file. Priority: command line > pass_in > JSON config > default values.

from simpleArgParser import SpecialLoadMarker

@dataclass
class Config:
    lr: float = 0.001
    epochs: int = 10
    load_from: str | None = SpecialLoadMarker()
{"lr": 0.01, "epochs": 50}
python main.py --load_from config.json            # uses JSON values
python main.py --load_from config.json --lr 0.1   # CLI overrides JSON

Pre/Post Processing

Define pre_process() and post_process() methods for validation or side effects. They are called recursively on all nested dataclasses (pre_process top-down, post_process bottom-up).

@dataclass
class Config:
    tp: int = 1

    def pre_process(self):
        print("validating...")

    def post_process(self):
        if self.tp < 1:
            raise ValueError("tp must be >= 1")

Serialization

Convert configs to JSON or dict. Enum values are serialized by name.

from simpleArgParser import to_json, to_dict

config = parse_args(Config)
print(to_json(config))   # JSON string
print(to_dict(config))   # Python dict

Programmatic Usage

Use pass_in to provide arguments from code. Use disable_cmd=True to ignore sys.argv. Very useful for debugging and testing.

config = parse_args(Config, pass_in=["--lr", "0.01", "--epochs", "5"])

# ignore command line entirely
config = parse_args(Config, pass_in=["--lr", "0.01"], disable_cmd=True)

Subcommands (CLI Tools)

Build multi-command CLI tools with parse_args_with_commands. Define commands using enums for type-safe dispatching. Supports arbitrary nesting.

import enum
from simpleArgParser import parse_args_with_commands

class Command(enum.Enum):
    train = "train"   # start training
    eval = "eval"     # run evaluation

@dataclass
class TrainConfig:
    lr: float = 0.001
    epochs: int = 10

@dataclass
class EvalConfig:
    checkpoint: str  # required

command, config = parse_args_with_commands(
    commands={
        Command.train: TrainConfig,
        Command.eval: EvalConfig,
    },
)

if command == (Command.train,):
    print(f"Training with lr={config.lr}")
elif command == (Command.eval,):
    print(f"Evaluating {config.checkpoint}")
mycli train --lr 0.01 --epochs 20
mycli eval --checkpoint best.pt
mycli --help

Nested Commands

Group commands into modules with nested dicts and separate enums per level. The returned command is a tuple of enum members.

class Top(enum.Enum):
    model = "model"  # model operations
    data = "data"    # data operations

class ModelCmd(enum.Enum):
    train = "train"
    eval = "eval"

class DataCmd(enum.Enum):
    process = "process"

command, config = parse_args_with_commands(
    commands={
        Top.model: {
            ModelCmd.train: TrainConfig,
            ModelCmd.eval: EvalConfig,
        },
        Top.data: {
            DataCmd.process: ProcessConfig,
        },
    },
    description="My ML CLI",
)

# command == (Top.model, ModelCmd.train)
if command[0] == Top.model:
    if command[1] == ModelCmd.train:
        ...
mycli model train --lr 0.01
mycli data process --workers 8
mycli --help          # shows command tree
mycli model --help    # shows model sub-commands

Shared Config Across Commands

Embed a common config as a nested field. Short aliases are created automatically for unique field names.

@dataclass
class CommonConfig:
    verbose: bool = False

@dataclass
class TrainConfig:
    lr: float = 0.001
    common: CommonConfig = field(default_factory=CommonConfig)
mycli train --verbose true          # alias for --common.verbose
mycli train --common.verbose true   # full path always works

Help Output Ordering

Arguments in --help are sorted by: required first, then by nesting depth (shallow first), then alphabetically.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simpleargparser-0.2.2.tar.gz (28.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simpleargparser-0.2.2-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file simpleargparser-0.2.2.tar.gz.

File metadata

  • Download URL: simpleargparser-0.2.2.tar.gz
  • Upload date:
  • Size: 28.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for simpleargparser-0.2.2.tar.gz
Algorithm Hash digest
SHA256 04ae7bf90832f14a1b475a128c1ffc8d598be834c11a830ab84a1b55e9cdfd2b
MD5 1b6a65fce40def10f162380b4c40c152
BLAKE2b-256 f8e617f1706c1cb6a65bce0baa719a2a494195c9f8a4884f9bcc1d5fd3b2b70c

See more details on using hashes here.

File details

Details for the file simpleargparser-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for simpleargparser-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ed6adb9426ac3278bef3f2b554c7afbb3665e3d33f2756be8ebb33123d8f1ef5
MD5 12eaf28556df6b9cfe4e7b5d19d5ce5a
BLAKE2b-256 ca1113523c4ac47de1ad5e3e5195227fc045180e96ca615e10875c69a2bbe2a9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page