Skip to content

A python library for easily exposing dataclass properties as CLI arguments and populating from the CLI and other sources

License

Notifications You must be signed in to change notification settings

bassmanitram/dataclass-args

Repository files navigation

Dataclass Args

Generate command-line interfaces from Python dataclasses.

Tests Lint Code Quality Examples Python 3.8+ PyPI version License: MIT

Features

Quick Start

Installation

pip install dataclass-args

# With optional format support
pip install "dataclass-args[yaml,toml]"  # YAML and TOML config files
pip install "dataclass-args[all]"        # All optional dependencies

Basic Usage

from dataclasses import dataclass
from dataclass_args import build_config

@dataclass
class Config:
    name: str
    count: int = 10
    debug: bool = False

# Generate CLI from dataclass
config = build_config(Config)

# Use your config
print(f"Running {config.name} with count={config.count}, debug={config.debug}")
$ python app.py --name "MyApp" --count 5 --debug
Running MyApp with count=5, debug=True

$ python app.py --help
usage: app.py [-h] [--config CONFIG] [--name NAME] [--count COUNT] [--debug] [--no-debug]

Build Config from CLI

options:
  -h, --help       show this help message and exit
  --config CONFIG  Base configuration file (JSON, YAML, or TOML)
  --name NAME      name
  --count COUNT    count
  --debug          debug (default: False)
  --no-debug       Disable debug

Core Features

Short Options

Add concise short flags to your CLI:

from dataclass_args import cli_short

@dataclass
class ServerConfig:
    host: str = cli_short('h', default="localhost")
    port: int = cli_short('p', default=8000)
    debug: bool = cli_short('d', default=False)
# Use short forms
$ python server.py -h 0.0.0.0 -p 9000 -d

# Or long forms
$ python server.py --host 0.0.0.0 --port 9000 --debug

# Mix and match
$ python server.py -h 0.0.0.0 --port 9000 -d

Boolean Flags

Booleans work as proper CLI flags with negative forms:

@dataclass
class BuildConfig:
    test: bool = True      # Default enabled
    deploy: bool = False   # Default disabled
# Enable a flag
$ python build.py --deploy

# Disable a flag
$ python build.py --no-test

# Use defaults (omit flags)
$ python build.py  # test=True, deploy=False

With short options:

@dataclass
class Config:
    verbose: bool = cli_short('v', default=False)
    debug: bool = cli_short('d', default=False)
$ python app.py -v -d              # Short flags
$ python app.py --verbose --debug  # Long flags
$ python app.py --no-verbose       # Negative form

Value Choices

Restrict field values to a valid set:

from dataclass_args import cli_choices

@dataclass
class DeployConfig:
    environment: str = cli_choices(['dev', 'staging', 'prod'])
    region: str = cli_choices(['us-east-1', 'us-west-2', 'eu-west-1'], default='us-east-1')
    size: str = cli_choices(['small', 'medium', 'large'], default='medium')
# Valid choices
$ python deploy.py --environment prod --region us-west-2

# Invalid choice shows error
$ python deploy.py --environment invalid
error: argument --environment: invalid choice: 'invalid' (choose from 'dev', 'staging', 'prod')

Repeatable Options

Use cli_append() to allow an option to be specified multiple times, with each occurrence collecting its own arguments:

from dataclass_args import cli_append

@dataclass
class Config:
    # Simple tags: each -t adds one value
    tags: List[str] = combine_annotations(
        cli_short('t'),
        cli_append(),
        cli_help("Add a tag"),
        default_factory=list
    )
# Each -t occurrence accumulates
$ python app.py -t python -t cli -t tool
# Result: ['python', 'cli', 'tool']

Repeatable with Multiple Arguments

Each occurrence can take multiple arguments using nargs:

@dataclass
class DockerConfig:
    # Each -p takes exactly 2 arguments (HOST CONTAINER)
    ports: List[List[str]] = combine_annotations(
        cli_short('p'),
        cli_append(nargs=2),
        cli_help("Port mapping (HOST CONTAINER)"),
        default_factory=list
    )

    # Each -v takes exactly 2 arguments (SOURCE TARGET)
    volumes: List[List[str]] = combine_annotations(
        cli_short('v'),
        cli_append(nargs=2),
        cli_help("Volume mount (SOURCE TARGET)"),
        default_factory=list
    )
$ python docker.py -p 8080 80 -p 8443 443 -v /host/data /container/data

Variable Arguments with Validation

Use min_args and max_args for flexible argument counts with automatic validation:

@dataclass
class UploadConfig:
    files: List[List[str]] = combine_annotations(
        cli_short('f'),
        cli_append(min_args=1, max_args=2, metavar="FILE [MIMETYPE]"),
        cli_help("File with optional MIME type"),
        default_factory=list
    )
    # No __post_init__ needed - validation is automatic!
# Mix files with and without MIME types
$ python upload.py -f doc.pdf application/pdf -f image.png -f video.mp4 video/mp4
# Result: [['doc.pdf', 'application/pdf'], ['image.png'], ['video.mp4', 'video/mp4']]

# Validation catches errors automatically
$ python upload.py -f file1 arg2 arg3 arg4
# Error: Expected at most 2 argument(s), got 4

Clean help display:

-f FILE [MIMETYPE], --files FILE [MIMETYPE]
    File with optional MIME type (can be repeated, 1-2 args each)

Parameters:

  • min_args: Minimum arguments per occurrence
  • max_args: Maximum arguments per occurrence
  • Must be used together (both or neither)
  • Mutually exclusive with nargs

nargs Options:

  • None - One value per occurrence → List[T]
  • int (e.g., 2) - Exact count per occurrence → List[List[T]]
  • '+' - One or more per occurrence → List[List[T]]
  • '*' - Zero or more per occurrence → List[List[T]]

Use Cases:

  • Docker-style options: -p 8080:80 -p 8443:443 -v /host:/container -e KEY=value
  • File operations: -f file1 type1 -f file2 -f file3 type3
  • Server pools: -s host1 port1 -s host2 port2
  • Build systems: -I dir1 -I dir2 --define KEY VAL

Positional Arguments

Add positional arguments that don't require -- prefixes:

from dataclass_args import cli_positional

@dataclass
class CopyCommand:
    source: str = cli_positional(help="Source file")
    dest: str = cli_positional(help="Destination file")
    recursive: bool = cli_short('r', default=False)
# Positional arguments are matched by position
$ python cp.py source.txt destination.txt -r

# Optional flags can appear anywhere
$ python cp.py -r source.txt destination.txt

Variable Number of Arguments

Use nargs to accept multiple values:

from typing import List

@dataclass
class GitCommit:
    command: str = cli_positional(help="Git command")
    files: List[str] = cli_positional(nargs='+', help="Files to commit")
    message: str = cli_short('m', default="")

# CLI: python git.py commit file1.py file2.py file3.py -m "Add feature"

nargs Options:

  • None (default) - Exactly one value (required)
  • '?' - Zero or one value (optional)
  • '*' - Zero or more values (optional list)
  • '+' - One or more values (required list)
  • int (e.g., 2) - Exact count (required list)

Optional Positional Arguments

@dataclass
class Convert:
    input_file: str = cli_positional(help="Input file")
    output_file: str = cli_positional(
        nargs='?',
        default='stdout',
        help="Output file (default: stdout)"
    )
    format: str = cli_short('f', default='json')
# With output file
$ python convert.py input.json output.yaml -f yaml

# Without output file (uses default)
$ python convert.py input.json -f xml

⚠️ Positional List Constraints

Positional arguments with variable length have important constraints:

Rules:

  1. At most ONE positional field can use nargs='*' or '+'
  2. If present, the positional list must be the LAST positional argument
  3. For multiple lists, use optional arguments with flags

Valid:

@dataclass
class Valid:
    command: str = cli_positional()          # First
    files: List[str] = cli_positional(nargs='+')  # Last (OK!)
    exclude: List[str] = cli_short('e', default_factory=list)  # Optional list with flag (OK!)

Invalid:

@dataclass
class Invalid:
    files: List[str] = cli_positional(nargs='+')  # Positional list
    output: str = cli_positional()                 # ERROR: positional after list!

# ConfigBuilderError: Positional list argument must be last.
# Fix: Make output an optional argument with a flag

Why? Positional lists are greedy and consume all remaining values. The parser can't determine where one positional list ends and another begins without -- flags.

Combining Annotations

Use combine_annotations() to merge multiple features:

from dataclass_args import combine_annotations, cli_short, cli_choices, cli_help

@dataclass
class AppConfig:
    # Combine short option + help text
    name: str = combine_annotations(
        cli_short('n'),
        cli_help("Application name")
    )

    # Combine short + choices + help
    environment: str = combine_annotations(
        cli_short('e'),
        cli_choices(['dev', 'staging', 'prod']),
        cli_help("Deployment environment"),
        default='dev'
    )

    # Boolean with short + help
    debug: bool = combine_annotations(
        cli_short('d'),
        cli_help("Enable debug mode"),
        default=False
    )
# Concise CLI usage
$ python app.py -n myapp -e prod -d

# Clear help output
$ python app.py --help
options:
  -n NAME, --name NAME  Application name
  -e {dev,staging,prod}, --environment {dev,staging,prod}
                        Deployment environment (default: dev)
  -d, --debug           Enable debug mode (default: False)
  --no-debug            Disable Enable debug mode

Real-World Example

from dataclasses import dataclass
from dataclass_args import build_config, cli_short, cli_choices, cli_help, combine_annotations

@dataclass
class DeploymentConfig:
    """Configuration for application deployment."""

    # Basic settings with short options
    name: str = combine_annotations(
        cli_short('n'),
        cli_help("Application name")
    )

    version: str = combine_annotations(
        cli_short('v'),
        cli_help("Version to deploy"),
        default='latest'
    )

    # Validated choices
    environment: str = combine_annotations(
        cli_short('e'),
        cli_choices(['dev', 'staging', 'prod']),
        cli_help("Target environment"),
        default='dev'
    )

    region: str = combine_annotations(
        cli_short('r'),
        cli_choices(['us-east-1', 'us-west-2', 'eu-west-1']),
        cli_help("AWS region"),
        default='us-east-1'
    )

    size: str = combine_annotations(
        cli_short('s'),
        cli_choices(['small', 'medium', 'large', 'xlarge']),
        cli_help("Instance size"),
        default='medium'
    )

    # Boolean flags
    dry_run: bool = combine_annotations(
        cli_short('d'),
        cli_help("Perform dry run without deploying"),
        default=False
    )

    notify: bool = combine_annotations(
        cli_short('N'),
        cli_help("Send deployment notifications"),
        default=True
    )

if __name__ == "__main__":
    config = build_config(DeploymentConfig)

    print(f"Deploying {config.name} v{config.version}")
    print(f"Environment: {config.environment}")
    print(f"Region: {config.region}")
    print(f"Size: {config.size}")
    print(f"Dry run: {config.dry_run}")
    print(f"Notify: {config.notify}")
# Production deployment
$ python deploy.py -n myapp -v 2.1.0 -e prod -r us-west-2 -s large

# Dry run in staging
$ python deploy.py -n myapp -e staging -d --no-notify

# Help shows everything clearly
$ python deploy.py --help

Advanced Features

File-Loadable Parameters

Load string parameters from files using the @filename syntax. Supports home directory expansion with ~:

from dataclass_args import cli_file_loadable

@dataclass
class AppConfig:
    name: str = cli_help("Application name")
    system_prompt: str = cli_file_loadable(default="You are a helpful assistant")
    welcome_message: str = cli_file_loadable()

config = build_config(AppConfig)
# Use literal values
$ python app.py --system-prompt "You are a coding assistant"

# Load from files (absolute paths)
$ python app.py --system-prompt "@/etc/prompts/assistant.txt"

# Load from home directory
$ python app.py --system-prompt "@~/prompts/assistant.txt"

# Load from another user's home
$ python app.py --system-prompt "@~alice/shared/prompt.txt"

# Load from relative paths
$ python app.py --welcome-message "@messages/welcome.txt"

# Mix literal and file-loaded values
$ python app.py --name "MyApp" --system-prompt "@~/prompts/assistant.txt"

Path Expansion:

  • @~/file.txt → Expands to user's home directory (e.g., /home/user/file.txt)
  • @~username/file.txt → Expands to specified user's home directory
  • @/absolute/path → Used as-is
  • @relative/path → Relative to current working directory

config.yaml

name: "DefaultApp" count: 100 database: host: "localhost" port: 5432 timeout: 30


```python
@dataclass
class DatabaseConfig:
    host: str = "localhost"
    port: int = 5432
    timeout: float = 30.0

@dataclass
class AppConfig:
    name: str
    count: int = 10
    database: Dict[str, Any] = None

config = build_config_from_cli(AppConfig, [
    '--config', 'config.yaml',  # Load base configuration
    '--name', 'OverriddenApp',  # Override name
    '--database', 'db.json',    # Load additional database config
    '--d', 'timeout:60'         # Override database.timeout property
])

Custom Help and Annotations

from dataclass_args import cli_help, cli_exclude, cli_file_loadable

@dataclass
class ServerConfig:
    # Custom help text
    host: str = cli_help("Server bind address", default="127.0.0.1")
    port: int = cli_help("Server port number", default=8000)

    # File-loadable with help
    ssl_cert: str = cli_file_loadable(cli_help("SSL certificate content"))

    # Hidden from CLI
    secret_key: str = cli_exclude(default="auto-generated")

    # Multiple values
    allowed_hosts: List[str] = cli_help("Allowed host headers", default_factory=list)

Complex Types and Validation

from typing import List, Dict, Optional
from pathlib import Path

@dataclass
class MLConfig:
    # Basic types
    model_name: str = cli_help("Model identifier")
    learning_rate: float = cli_help("Learning rate", default=0.001)
    epochs: int = cli_help("Training epochs", default=100)

    # Complex types
    layer_sizes: List[int] = cli_help("Neural network layer sizes", default_factory=lambda: [128, 64])
    hyperparameters: Dict[str, Any] = cli_help("Model hyperparameters")

    # Optional types
    checkpoint_path: Optional[Path] = cli_help("Path to model checkpoint")

    # File-loadable configurations
    training_config: str = cli_file_loadable(cli_help("Training configuration"))

    def __post_init__(self):
        # Custom validation
        if self.learning_rate <= 0:
            raise ValueError("Learning rate must be positive")
        if self.epochs <= 0:
            raise ValueError("Epochs must be positive")

Configuration Merging

Dataclass-args supports hierarchical configuration merging from multiple sources with clear precedence rules.

Merge Order (Highest Priority Last)

Configuration sources are merged in this order, with later sources overriding earlier ones:

  1. Programmatic base_configs (if provided) - Lowest priority
  2. Config file from --config CLI argument (if provided)
  3. CLI arguments - Highest priority

Basic Usage

Load a base configuration file and override with CLI arguments:

from dataclasses import dataclass
from dataclass_args import build_config

@dataclass
class AppConfig:
    name: str
    count: int = 10
    region: str = "us-east-1"

# Load from file, override with CLI
config = build_config(
    AppConfig,
    args=['--config', 'prod.yaml', '--count', '100']
)

prod.yaml:

name: "ProductionApp"
count: 50
region: "eu-west-1"

Result:

  • name: "ProductionApp" (from file)
  • count: 100 (CLI override)
  • region: "eu-west-1" (from file)

Programmatic Base Configs

For advanced use cases, provide base configuration programmatically using the base_configs parameter:

# Single file path
config = build_config(AppConfig, base_configs='defaults.yaml')

# Single configuration dict
config = build_config(AppConfig, base_configs={'debug': True, 'count': 50})

# List mixing files and dicts (applied in order)
config = build_config(
    AppConfig,
    args=['--config', 'user.yaml', '--name', 'override'],
    base_configs=[
        'company-defaults.yaml',      # Company-wide defaults
        {'environment': 'production'}, # Programmatic override
        'team-overrides.json',        # Team-specific settings
    ]
)

Merge order for the list example:

  1. company-defaults.yaml (loaded and applied first)
  2. {'environment': 'production'} (overrides company defaults)
  3. team-overrides.json (loaded and overrides previous)
  4. user.yaml (from --config, overrides all base_configs)
  5. --name 'override' (CLI arg, highest priority)

Merge Behavior by Type

Type Behavior Example
Scalar (str, int, float) Replace Later value replaces earlier value
List Replace Later list replaces earlier list (not appended)
Dict Shallow merge Keys are merged; later sources override earlier keys

Dict merge example:

# base_configs[0]
{'name': 'app', 'db': {'host': 'localhost', 'port': 5432}}

# base_configs[1]
{'db': {'port': 3306, 'timeout': 30}}

# Result after merging:
{'name': 'app', 'db': {'host': 'localhost', 'port': 3306, 'timeout': 30}}
#  ^unchanged    ^merged: host kept, port updated, timeout added

Real-World Example

import os
from dataclasses import dataclass
from dataclass_args import build_config

@dataclass
class DeployConfig:
    app_name: str
    environment: str
    region: str = "us-east-1"
    instance_count: int = 1

# Determine environment
env = os.getenv('ENV', 'dev')

# Multi-layer configuration
config = build_config(
    DeployConfig,
    args=['--config', '~/.myapp/personal.yaml', '--region', 'us-west-2'],
    base_configs=[
        'config/base.yaml',           # Company-wide defaults
        f'config/{env}.yaml',         # Environment-specific (dev/staging/prod)
        {'debug': True},              # Quick programmatic toggle
    ]
)

# Configuration is built from all sources with clear precedence
print(f"Deploying {config.app_name} to {config.environment}")

Use Cases:

  1. Multi-environment deployments:

    config = build_config(
        Config,
        args=['--config', f'{env}.yaml'],
        base_configs='base.yaml'
    )
  2. Testing with fixtures:

    test_config = {'database': 'test_db', 'debug': True}
    config = build_config(
        AppConfig,
        args=['--name', 'test-run'],
        base_configs=test_config
    )
  3. Team and personal settings:

    config = build_config(
        Config,
        base_configs=[
            'company.yaml',      # Company defaults
            'team.yaml',         # Team overrides
            '~/.myapp/personal.yaml',  # Personal settings
        ]
    )

Complete Example

See examples/config_merging_example.py for a comprehensive demonstration of configuration merging with multiple sources.

# Run the example
python examples/config_merging_example.py multi-source

See Also

API Reference

đź“– Full API Documentation: See docs/API.md for complete API reference with detailed examples.

Quick API Reference

Main Functions

build_config(config_class, args=None)

Generate CLI from dataclass and parse arguments.

config = build_config(MyDataclass)  # Uses sys.argv automatically

build_config_from_cli(config_class, args=None, **options)

Generate CLI with additional options.

config = build_config_from_cli(
    MyDataclass,
    args=['--name', 'test'],

Annotations

cli_short(letter, **kwargs)

Add a short option flag to a field.

field: str = cli_short('f', default="value")

# Or combine with other annotations
field: str = combine_annotations(
    cli_short('f'),
    cli_help("Help text"),
    default="value"
)

cli_choices(choices_list, **kwargs)

Restrict field to a set of valid choices.

env: str = cli_choices(['dev', 'prod'], default='dev')

# Or combine
env: str = combine_annotations(
    cli_short('e'),
    cli_choices(['dev', 'prod']),
    cli_help("Environment"),
    default='dev'
)

cli_help(help_text, **kwargs)

Add custom help text to CLI arguments.

field: str = cli_help("Custom help text", default="default_value")

cli_positional(nargs=None, metavar=None, **kwargs)

Mark a field as a positional CLI argument (no -- prefix required).

# Required positional
source: str = cli_positional(help="Source file")

# Optional positional
output: str = cli_positional(nargs='?', default='stdout')

# Variable number (list)
files: List[str] = cli_positional(nargs='+', help="Files")

# Exact count
coords: List[float] = cli_positional(nargs=2, metavar='X Y')

# Combined with other annotations
input: str = combine_annotations(
    cli_positional(),
    cli_help("Input file path")
)

Important: At most one positional can use nargs='*' or '+', and it must be the last positional.

cli_exclude(**kwargs)

Exclude fields from CLI argument generation.

internal_field: str = cli_exclude(default="hidden")

cli_file_loadable(**kwargs)

Mark string fields as file-loadable via '@filename' syntax.

content: str = cli_file_loadable(default="default content")

combine_annotations(*annotations, **kwargs)

Combine multiple annotations on a single field.

field: str = combine_annotations(
    cli_short('f'),
    cli_choices(['a', 'b', 'c']),
    cli_help("Description"),
    default='a'
)

Type Support

Dataclass CLI supports standard Python types:

Type CLI Behavior Example
str Direct string value --name "hello"
int Parsed as integer --count 42
float Parsed as float --rate 0.1
bool Flag with negative --debug or --no-debug
List[T] Multiple values --items a b c
Dict[str, Any] Config file + overrides --config file.json --c key:value
Optional[T] Optional parameter --timeout 30 (or omit)
Path Path object --output /path/to/file
Custom types String representation --custom "value"

Configuration File Formats

Supports multiple configuration file formats:

JSON

{
  "name": "MyApp",
  "count": 42,
  "database": {
    "host": "localhost",
    "port": 5432
  }
}

YAML (requires pip install "dataclass-args[yaml]")

name: MyApp
count: 42
database:
  host: localhost
  port: 5432

TOML (requires pip install "dataclass-args[toml]")

name = "MyApp"
count = 42

[database]
host = "localhost"
port = 5432

Examples

Check the examples/ directory for complete working examples:

  • positional_example.py - Positional arguments and variable length args
  • boolean_flags_example.py - Boolean flags with --flag and --no-flag
  • cli_choices_example.py - Value validation with choices
  • cli_short_example.py - Short option flags
  • all_features_example.py - All features together
  • And more...

Web Server Configuration

from dataclasses import dataclass
from typing import List
from dataclass_args import build_config, cli_short, cli_help, cli_exclude, cli_file_loadable, combine_annotations

@dataclass
class ServerConfig:
    # Basic server settings
    host: str = combine_annotations(
        cli_short('h'),
        cli_help("Server bind address"),
        default="127.0.0.1"
    )

    port: int = combine_annotations(
        cli_short('p'),
        cli_help("Server port number"),
        default=8000
    )

    workers: int = combine_annotations(
        cli_short('w'),
        cli_help("Number of worker processes"),
        default=1
    )

    # Security settings
    ssl_cert: str = cli_file_loadable(cli_help("SSL certificate content"))
    ssl_key: str = cli_file_loadable(cli_help("SSL private key content"))

    # Application settings
    debug: bool = combine_annotations(
        cli_short('d'),
        cli_help("Enable debug mode"),
        default=False
    )

    allowed_hosts: List[str] = cli_help("Allowed host headers", default_factory=list)

    # Internal fields (hidden from CLI)
    _server_id: str = cli_exclude(default_factory=lambda: f"server-{os.getpid()}")

if __name__ == "__main__":
    config = build_config(ServerConfig)
    print(f"Starting server on {config.host}:{config.port}")
# Start server with short options
$ python server.py -h 0.0.0.0 -p 9000 -w 4 -d

# Load SSL certificates from files
$ python server.py --ssl-cert "@certs/server.crt" --ssl-key "@certs/server.key"

Contributing

Contributions are welcome! Please see our Contributing Guide for details.

Development Setup

git clone https://github.com/bassmanitram/dataclass-args.git
cd dataclass-args
pip install -e ".[dev,all]"

Development Setup

git clone https://github.com/bassmanitram/dataclass-args.git
cd dataclass-args
pip install -e ".[dev,all]"
make setup  # Install dev dependencies and pre-commit hooks

Running Tests

# Run all tests (coverage is automatic)
pytest
make test

# Run tests with detailed coverage report
make coverage

# Run tests with coverage and open HTML report
make coverage-html

# Run specific test file
pytest tests/test_cli_short.py

# Verbose output
pytest -v

Code Coverage

This project maintains 94%+ code coverage. Coverage reports are generated automatically when running tests.

  • Quick check: make coverage
  • Detailed report: See htmlcov/index.html
  • Coverage docs: COVERAGE.md

All code changes should maintain or improve coverage. The minimum required coverage is 90%.

Code Formatting

# Format code
make format
black dataclass_args/ tests/ examples/
isort dataclass_args/ tests/ examples/

# Check formatting
make lint
black --check dataclass_args/ tests/
flake8 dataclass_args/ tests/
mypy dataclass_args/

Full Check (like CI)

# Run all checks: linting, tests, and examples
make check

Changelog

See CHANGELOG.md for version history and changes.

Support

  • Issues: GitHub Issues
  • Documentation: This README and comprehensive docstrings
  • Examples: See the examples/ directory

Quick Reference

from dataclasses import dataclass
from dataclass_args import (
    build_config,                # Main function
    cli_short,                   # Short options: -n
    cli_positional,              # Positional args
    cli_choices,                 # Value validation
    cli_help,                    # Custom help text
    cli_exclude,                 # Hide from CLI
    cli_file_loadable,           # @file loading
    combine_annotations,         # Combine features
)

@dataclass
class Config:
    # Simple field
    name: str

    # Positional argument
    input_file: str = cli_positional()

    # With short option
    port: int = cli_short('p', default=8000)

    # With choices
    env: str = cli_choices(['dev', 'prod'], default='dev')

    # Boolean flag
    debug: bool = False  # Creates --debug and --no-debug

    # Combine everything
    region: str = combine_annotations(
        cli_short('r'),
        cli_choices(['us-east-1', 'us-west-2']),
        cli_help("AWS region"),
        default='us-east-1'
    )

    # Hidden from CLI
    secret: str = cli_exclude(default="hidden")

    # File-loadable
    config_text: str = cli_file_loadable(default="")

# Build and use
config = build_config(Config)

Define your dataclass, add annotations as needed, and call build_config() to parse command-line arguments.

About

A python library for easily exposing dataclass properties as CLI arguments and populating from the CLI and other sources

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages