dataclass-args


Namedataclass-args JSON
Version 1.1.0 PyPI version JSON
download
home_pageNone
SummaryZero-boilerplate CLI generation from Python dataclasses with advanced type support and file loading
upload_time2025-11-03 18:25:58
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords cli dataclass argparse configuration command-line type-safe validation file-loading config-merging
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Dataclass Args

Generate command-line interfaces from Python dataclasses.

[![Tests](https://github.com/bassmanitram/dataclass-args/actions/workflows/test.yml/badge.svg)](https://github.com/bassmanitram/dataclass-args/actions/workflows/test.yml)
[![Code Quality](https://github.com/bassmanitram/dataclass-args/actions/workflows/lint.yml/badge.svg)](https://github.com/bassmanitram/dataclass-args/actions/workflows/lint.yml)
[![Examples](https://github.com/bassmanitram/dataclass-args/actions/workflows/examples.yml/badge.svg)](https://github.com/bassmanitram/dataclass-args/actions/workflows/examples.yml)
[![codecov](https://codecov.io/gh/bassmanitram/dataclass-args/branch/main/graph/badge.svg)](https://codecov.io/gh/bassmanitram/dataclass-args)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![PyPI version](https://badge.fury.io/py/dataclass-args.svg)](https://badge.fury.io/py/dataclass-args)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

- **Automatic CLI Generation** - Generate CLI from dataclass definitions
- **Type-Safe Parsing** - Type-aware argument parsing for standard Python types
- **Positional Arguments** - Support for positional args with `cli_positional()`
- **Short Options** - Concise `-n` flags in addition to `--name`
- **Boolean Flags** - Proper `--flag` and `--no-flag` boolean handling
- **Value Validation** - Restrict values with `cli_choices()`
- **File Loading** - Load parameters from files using `@filename` syntax
- **Config Merging** - Combine configuration files with CLI overrides
- **Flexible Types** - Support for `List`, `Dict`, `Optional`, and custom types
- **Rich Annotations** - Custom help text, exclusions, and combinations
- **Minimal Dependencies** - Lightweight with optional format support

## Quick Start

### Installation

```bash
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

```python
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}")
```

```bash
$ 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:

```python
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)
```

```bash
# 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:

```python
@dataclass
class BuildConfig:
    test: bool = True      # Default enabled
    deploy: bool = False   # Default disabled
```

```bash
# 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:

```python
@dataclass
class Config:
    verbose: bool = cli_short('v', default=False)
    debug: bool = cli_short('d', default=False)
```

```bash
$ 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:

```python
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')
```

```bash
# 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')
```



### Positional Arguments

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

```python
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)
```

```bash
# 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:

```python
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

```python
@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')
```

```bash
# 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:**
```python
@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:**
```python
@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:

```python
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
    )
```

```bash
# 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

```python
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}")
```

```bash
# 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 `~`:

```python
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)
```

```bash
# 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

```python
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

```python
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")
```

## API Reference

> **📖 Full API Documentation:** See [docs/API.md](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.

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

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

Generate CLI with additional options.

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

### Annotations

#### `cli_short(letter, **kwargs)`

Add a short option flag to a field.

```python
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.

```python
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.

```python
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).

```python
# 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.

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

#### `cli_file_loadable(**kwargs)`

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

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

#### `combine_annotations(*annotations, **kwargs)`

Combine multiple annotations on a single field.

```python
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
```json
{
  "name": "MyApp",
  "count": 42,
  "database": {
    "host": "localhost",
    "port": 5432
  }
}
```

### YAML (requires `pip install "dataclass-args[yaml]"`)
```yaml
name: MyApp
count: 42
database:
  host: localhost
  port: 5432
```

### TOML (requires `pip install "dataclass-args[toml]"`)
```toml
name = "MyApp"
count = 42

[database]
host = "localhost"
port = 5432
```

## Examples

Check the [`examples/`](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

```python
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}")
```

```bash
# 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](CONTRIBUTING.md) for details.

### Development Setup

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

### Development Setup

```bash
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

```bash
# 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](COVERAGE.md)

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

### Code Formatting

```bash
# 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)

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

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for version history and changes.

## Support

- **Issues**: [GitHub Issues](https://github.com/bassmanitram/dataclass-args/issues)
- **Documentation**: This README and comprehensive docstrings
- **Examples**: See the [examples/](examples/) directory

## Quick Reference

```python
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.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "dataclass-args",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "cli, dataclass, argparse, configuration, command-line, type-safe, validation, file-loading, config-merging",
    "author": null,
    "author_email": "Martin Bartlett <martin.j.bartlett@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/7a/80/d29499a1952b5e393b9fe66cf9f07605c48547ce517af617c1d6a92ce9e6/dataclass_args-1.1.0.tar.gz",
    "platform": null,
    "description": "# Dataclass Args\n\nGenerate command-line interfaces from Python dataclasses.\n\n[![Tests](https://github.com/bassmanitram/dataclass-args/actions/workflows/test.yml/badge.svg)](https://github.com/bassmanitram/dataclass-args/actions/workflows/test.yml)\n[![Code Quality](https://github.com/bassmanitram/dataclass-args/actions/workflows/lint.yml/badge.svg)](https://github.com/bassmanitram/dataclass-args/actions/workflows/lint.yml)\n[![Examples](https://github.com/bassmanitram/dataclass-args/actions/workflows/examples.yml/badge.svg)](https://github.com/bassmanitram/dataclass-args/actions/workflows/examples.yml)\n[![codecov](https://codecov.io/gh/bassmanitram/dataclass-args/branch/main/graph/badge.svg)](https://codecov.io/gh/bassmanitram/dataclass-args)\n[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\n[![PyPI version](https://badge.fury.io/py/dataclass-args.svg)](https://badge.fury.io/py/dataclass-args)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n- **Automatic CLI Generation** - Generate CLI from dataclass definitions\n- **Type-Safe Parsing** - Type-aware argument parsing for standard Python types\n- **Positional Arguments** - Support for positional args with `cli_positional()`\n- **Short Options** - Concise `-n` flags in addition to `--name`\n- **Boolean Flags** - Proper `--flag` and `--no-flag` boolean handling\n- **Value Validation** - Restrict values with `cli_choices()`\n- **File Loading** - Load parameters from files using `@filename` syntax\n- **Config Merging** - Combine configuration files with CLI overrides\n- **Flexible Types** - Support for `List`, `Dict`, `Optional`, and custom types\n- **Rich Annotations** - Custom help text, exclusions, and combinations\n- **Minimal Dependencies** - Lightweight with optional format support\n\n## Quick Start\n\n### Installation\n\n```bash\npip install dataclass-args\n\n# With optional format support\npip install \"dataclass-args[yaml,toml]\"  # YAML and TOML config files\npip install \"dataclass-args[all]\"        # All optional dependencies\n```\n\n### Basic Usage\n\n```python\nfrom dataclasses import dataclass\nfrom dataclass_args import build_config\n\n@dataclass\nclass Config:\n    name: str\n    count: int = 10\n    debug: bool = False\n\n# Generate CLI from dataclass\nconfig = build_config(Config)\n\n# Use your config\nprint(f\"Running {config.name} with count={config.count}, debug={config.debug}\")\n```\n\n```bash\n$ python app.py --name \"MyApp\" --count 5 --debug\nRunning MyApp with count=5, debug=True\n\n$ python app.py --help\nusage: app.py [-h] [--config CONFIG] [--name NAME] [--count COUNT] [--debug] [--no-debug]\n\nBuild Config from CLI\n\noptions:\n  -h, --help       show this help message and exit\n  --config CONFIG  Base configuration file (JSON, YAML, or TOML)\n  --name NAME      name\n  --count COUNT    count\n  --debug          debug (default: False)\n  --no-debug       Disable debug\n```\n\n## Core Features\n\n### Short Options\n\nAdd concise short flags to your CLI:\n\n```python\nfrom dataclass_args import cli_short\n\n@dataclass\nclass ServerConfig:\n    host: str = cli_short('h', default=\"localhost\")\n    port: int = cli_short('p', default=8000)\n    debug: bool = cli_short('d', default=False)\n```\n\n```bash\n# Use short forms\n$ python server.py -h 0.0.0.0 -p 9000 -d\n\n# Or long forms\n$ python server.py --host 0.0.0.0 --port 9000 --debug\n\n# Mix and match\n$ python server.py -h 0.0.0.0 --port 9000 -d\n```\n\n### Boolean Flags\n\nBooleans work as proper CLI flags with negative forms:\n\n```python\n@dataclass\nclass BuildConfig:\n    test: bool = True      # Default enabled\n    deploy: bool = False   # Default disabled\n```\n\n```bash\n# Enable a flag\n$ python build.py --deploy\n\n# Disable a flag\n$ python build.py --no-test\n\n# Use defaults (omit flags)\n$ python build.py  # test=True, deploy=False\n```\n\nWith short options:\n\n```python\n@dataclass\nclass Config:\n    verbose: bool = cli_short('v', default=False)\n    debug: bool = cli_short('d', default=False)\n```\n\n```bash\n$ python app.py -v -d              # Short flags\n$ python app.py --verbose --debug  # Long flags\n$ python app.py --no-verbose       # Negative form\n```\n\n### Value Choices\n\nRestrict field values to a valid set:\n\n```python\nfrom dataclass_args import cli_choices\n\n@dataclass\nclass DeployConfig:\n    environment: str = cli_choices(['dev', 'staging', 'prod'])\n    region: str = cli_choices(['us-east-1', 'us-west-2', 'eu-west-1'], default='us-east-1')\n    size: str = cli_choices(['small', 'medium', 'large'], default='medium')\n```\n\n```bash\n# Valid choices\n$ python deploy.py --environment prod --region us-west-2\n\n# Invalid choice shows error\n$ python deploy.py --environment invalid\nerror: argument --environment: invalid choice: 'invalid' (choose from 'dev', 'staging', 'prod')\n```\n\n\n\n### Positional Arguments\n\nAdd positional arguments that don't require `--` prefixes:\n\n```python\nfrom dataclass_args import cli_positional\n\n@dataclass\nclass CopyCommand:\n    source: str = cli_positional(help=\"Source file\")\n    dest: str = cli_positional(help=\"Destination file\")\n    recursive: bool = cli_short('r', default=False)\n```\n\n```bash\n# Positional arguments are matched by position\n$ python cp.py source.txt destination.txt -r\n\n# Optional flags can appear anywhere\n$ python cp.py -r source.txt destination.txt\n```\n\n#### Variable Number of Arguments\n\nUse `nargs` to accept multiple values:\n\n```python\nfrom typing import List\n\n@dataclass\nclass GitCommit:\n    command: str = cli_positional(help=\"Git command\")\n    files: List[str] = cli_positional(nargs='+', help=\"Files to commit\")\n    message: str = cli_short('m', default=\"\")\n\n# CLI: python git.py commit file1.py file2.py file3.py -m \"Add feature\"\n```\n\n**nargs Options:**\n- `None` (default) - Exactly one value (required)\n- `'?'` - Zero or one value (optional)\n- `'*'` - Zero or more values (optional list)\n- `'+'` - One or more values (required list)\n- `int` (e.g., `2`) - Exact count (required list)\n\n#### Optional Positional Arguments\n\n```python\n@dataclass\nclass Convert:\n    input_file: str = cli_positional(help=\"Input file\")\n    output_file: str = cli_positional(\n        nargs='?',\n        default='stdout',\n        help=\"Output file (default: stdout)\"\n    )\n    format: str = cli_short('f', default='json')\n```\n\n```bash\n# With output file\n$ python convert.py input.json output.yaml -f yaml\n\n# Without output file (uses default)\n$ python convert.py input.json -f xml\n```\n\n#### \u26a0\ufe0f Positional List Constraints\n\nPositional arguments with variable length have important constraints:\n\n**Rules:**\n1. At most ONE positional field can use `nargs='*'` or `'+'`\n2. If present, the positional list must be the LAST positional argument\n3. For multiple lists, use optional arguments with flags\n\n**Valid:**\n```python\n@dataclass\nclass Valid:\n    command: str = cli_positional()          # First\n    files: List[str] = cli_positional(nargs='+')  # Last (OK!)\n    exclude: List[str] = cli_short('e', default_factory=list)  # Optional list with flag (OK!)\n```\n\n**Invalid:**\n```python\n@dataclass\nclass Invalid:\n    files: List[str] = cli_positional(nargs='+')  # Positional list\n    output: str = cli_positional()                 # ERROR: positional after list!\n\n# ConfigBuilderError: Positional list argument must be last.\n# Fix: Make output an optional argument with a flag\n```\n\n**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.\n\n### Combining Annotations\n\nUse `combine_annotations()` to merge multiple features:\n\n```python\nfrom dataclass_args import combine_annotations, cli_short, cli_choices, cli_help\n\n@dataclass\nclass AppConfig:\n    # Combine short option + help text\n    name: str = combine_annotations(\n        cli_short('n'),\n        cli_help(\"Application name\")\n    )\n\n    # Combine short + choices + help\n    environment: str = combine_annotations(\n        cli_short('e'),\n        cli_choices(['dev', 'staging', 'prod']),\n        cli_help(\"Deployment environment\"),\n        default='dev'\n    )\n\n    # Boolean with short + help\n    debug: bool = combine_annotations(\n        cli_short('d'),\n        cli_help(\"Enable debug mode\"),\n        default=False\n    )\n```\n\n```bash\n# Concise CLI usage\n$ python app.py -n myapp -e prod -d\n\n# Clear help output\n$ python app.py --help\noptions:\n  -n NAME, --name NAME  Application name\n  -e {dev,staging,prod}, --environment {dev,staging,prod}\n                        Deployment environment (default: dev)\n  -d, --debug           Enable debug mode (default: False)\n  --no-debug            Disable Enable debug mode\n```\n\n### Real-World Example\n\n```python\nfrom dataclasses import dataclass\nfrom dataclass_args import build_config, cli_short, cli_choices, cli_help, combine_annotations\n\n@dataclass\nclass DeploymentConfig:\n    \"\"\"Configuration for application deployment.\"\"\"\n\n    # Basic settings with short options\n    name: str = combine_annotations(\n        cli_short('n'),\n        cli_help(\"Application name\")\n    )\n\n    version: str = combine_annotations(\n        cli_short('v'),\n        cli_help(\"Version to deploy\"),\n        default='latest'\n    )\n\n    # Validated choices\n    environment: str = combine_annotations(\n        cli_short('e'),\n        cli_choices(['dev', 'staging', 'prod']),\n        cli_help(\"Target environment\"),\n        default='dev'\n    )\n\n    region: str = combine_annotations(\n        cli_short('r'),\n        cli_choices(['us-east-1', 'us-west-2', 'eu-west-1']),\n        cli_help(\"AWS region\"),\n        default='us-east-1'\n    )\n\n    size: str = combine_annotations(\n        cli_short('s'),\n        cli_choices(['small', 'medium', 'large', 'xlarge']),\n        cli_help(\"Instance size\"),\n        default='medium'\n    )\n\n    # Boolean flags\n    dry_run: bool = combine_annotations(\n        cli_short('d'),\n        cli_help(\"Perform dry run without deploying\"),\n        default=False\n    )\n\n    notify: bool = combine_annotations(\n        cli_short('N'),\n        cli_help(\"Send deployment notifications\"),\n        default=True\n    )\n\nif __name__ == \"__main__\":\n    config = build_config(DeploymentConfig)\n\n    print(f\"Deploying {config.name} v{config.version}\")\n    print(f\"Environment: {config.environment}\")\n    print(f\"Region: {config.region}\")\n    print(f\"Size: {config.size}\")\n    print(f\"Dry run: {config.dry_run}\")\n    print(f\"Notify: {config.notify}\")\n```\n\n```bash\n# Production deployment\n$ python deploy.py -n myapp -v 2.1.0 -e prod -r us-west-2 -s large\n\n# Dry run in staging\n$ python deploy.py -n myapp -e staging -d --no-notify\n\n# Help shows everything clearly\n$ python deploy.py --help\n```\n\n## Advanced Features\n\n### File-Loadable Parameters\n\nLoad string parameters from files using the `@filename` syntax. Supports home directory expansion with `~`:\n\n```python\nfrom dataclass_args import cli_file_loadable\n\n@dataclass\nclass AppConfig:\n    name: str = cli_help(\"Application name\")\n    system_prompt: str = cli_file_loadable(default=\"You are a helpful assistant\")\n    welcome_message: str = cli_file_loadable()\n\nconfig = build_config(AppConfig)\n```\n\n```bash\n# Use literal values\n$ python app.py --system-prompt \"You are a coding assistant\"\n\n# Load from files (absolute paths)\n$ python app.py --system-prompt \"@/etc/prompts/assistant.txt\"\n\n# Load from home directory\n$ python app.py --system-prompt \"@~/prompts/assistant.txt\"\n\n# Load from another user's home\n$ python app.py --system-prompt \"@~alice/shared/prompt.txt\"\n\n# Load from relative paths\n$ python app.py --welcome-message \"@messages/welcome.txt\"\n\n# Mix literal and file-loaded values\n$ python app.py --name \"MyApp\" --system-prompt \"@~/prompts/assistant.txt\"\n```\n\n**Path Expansion:**\n- `@~/file.txt` \u2192 Expands to user's home directory (e.g., `/home/user/file.txt`)\n- `@~username/file.txt` \u2192 Expands to specified user's home directory\n- `@/absolute/path` \u2192 Used as-is\n- `@relative/path` \u2192 Relative to current working directory\n\n# config.yaml\nname: \"DefaultApp\"\ncount: 100\ndatabase:\n  host: \"localhost\"\n  port: 5432\n  timeout: 30\n```\n\n```python\n@dataclass\nclass DatabaseConfig:\n    host: str = \"localhost\"\n    port: int = 5432\n    timeout: float = 30.0\n\n@dataclass\nclass AppConfig:\n    name: str\n    count: int = 10\n    database: Dict[str, Any] = None\n\nconfig = build_config_from_cli(AppConfig, [\n    '--config', 'config.yaml',  # Load base configuration\n    '--name', 'OverriddenApp',  # Override name\n    '--database', 'db.json',    # Load additional database config\n    '--d', 'timeout:60'         # Override database.timeout property\n])\n```\n\n### Custom Help and Annotations\n\n```python\nfrom dataclass_args import cli_help, cli_exclude, cli_file_loadable\n\n@dataclass\nclass ServerConfig:\n    # Custom help text\n    host: str = cli_help(\"Server bind address\", default=\"127.0.0.1\")\n    port: int = cli_help(\"Server port number\", default=8000)\n\n    # File-loadable with help\n    ssl_cert: str = cli_file_loadable(cli_help(\"SSL certificate content\"))\n\n    # Hidden from CLI\n    secret_key: str = cli_exclude(default=\"auto-generated\")\n\n    # Multiple values\n    allowed_hosts: List[str] = cli_help(\"Allowed host headers\", default_factory=list)\n```\n\n### Complex Types and Validation\n\n```python\nfrom typing import List, Dict, Optional\nfrom pathlib import Path\n\n@dataclass\nclass MLConfig:\n    # Basic types\n    model_name: str = cli_help(\"Model identifier\")\n    learning_rate: float = cli_help(\"Learning rate\", default=0.001)\n    epochs: int = cli_help(\"Training epochs\", default=100)\n\n    # Complex types\n    layer_sizes: List[int] = cli_help(\"Neural network layer sizes\", default_factory=lambda: [128, 64])\n    hyperparameters: Dict[str, Any] = cli_help(\"Model hyperparameters\")\n\n    # Optional types\n    checkpoint_path: Optional[Path] = cli_help(\"Path to model checkpoint\")\n\n    # File-loadable configurations\n    training_config: str = cli_file_loadable(cli_help(\"Training configuration\"))\n\n    def __post_init__(self):\n        # Custom validation\n        if self.learning_rate <= 0:\n            raise ValueError(\"Learning rate must be positive\")\n        if self.epochs <= 0:\n            raise ValueError(\"Epochs must be positive\")\n```\n\n## API Reference\n\n> **\ud83d\udcd6 Full API Documentation:** See [docs/API.md](docs/API.md) for complete API reference with detailed examples.\n\n### Quick API Reference\n\n### Main Functions\n\n#### `build_config(config_class, args=None)`\n\nGenerate CLI from dataclass and parse arguments.\n\n```python\nconfig = build_config(MyDataclass)  # Uses sys.argv automatically\n```\n\n#### `build_config_from_cli(config_class, args=None, **options)`\n\nGenerate CLI with additional options.\n\n```python\nconfig = build_config_from_cli(\n    MyDataclass,\n    args=['--name', 'test'],\n```\n\n### Annotations\n\n#### `cli_short(letter, **kwargs)`\n\nAdd a short option flag to a field.\n\n```python\nfield: str = cli_short('f', default=\"value\")\n\n# Or combine with other annotations\nfield: str = combine_annotations(\n    cli_short('f'),\n    cli_help(\"Help text\"),\n    default=\"value\"\n)\n```\n\n#### `cli_choices(choices_list, **kwargs)`\n\nRestrict field to a set of valid choices.\n\n```python\nenv: str = cli_choices(['dev', 'prod'], default='dev')\n\n# Or combine\nenv: str = combine_annotations(\n    cli_short('e'),\n    cli_choices(['dev', 'prod']),\n    cli_help(\"Environment\"),\n    default='dev'\n)\n```\n\n#### `cli_help(help_text, **kwargs)`\n\nAdd custom help text to CLI arguments.\n\n```python\nfield: str = cli_help(\"Custom help text\", default=\"default_value\")\n```\n\n\n\n#### `cli_positional(nargs=None, metavar=None, **kwargs)`\n\nMark a field as a positional CLI argument (no `--` prefix required).\n\n```python\n# Required positional\nsource: str = cli_positional(help=\"Source file\")\n\n# Optional positional\noutput: str = cli_positional(nargs='?', default='stdout')\n\n# Variable number (list)\nfiles: List[str] = cli_positional(nargs='+', help=\"Files\")\n\n# Exact count\ncoords: List[float] = cli_positional(nargs=2, metavar='X Y')\n\n# Combined with other annotations\ninput: str = combine_annotations(\n    cli_positional(),\n    cli_help(\"Input file path\")\n)\n```\n\n**Important:** At most one positional can use `nargs='*'` or `'+'`, and it must be the last positional.\n\n#### `cli_exclude(**kwargs)`\n\nExclude fields from CLI argument generation.\n\n```python\ninternal_field: str = cli_exclude(default=\"hidden\")\n```\n\n#### `cli_file_loadable(**kwargs)`\n\nMark string fields as file-loadable via '@filename' syntax.\n\n```python\ncontent: str = cli_file_loadable(default=\"default content\")\n```\n\n#### `combine_annotations(*annotations, **kwargs)`\n\nCombine multiple annotations on a single field.\n\n```python\nfield: str = combine_annotations(\n    cli_short('f'),\n    cli_choices(['a', 'b', 'c']),\n    cli_help(\"Description\"),\n    default='a'\n)\n```\n\n## Type Support\n\nDataclass CLI supports standard Python types:\n\n| Type | CLI Behavior | Example |\n|------|--------------|---------|\n| `str` | Direct string value | `--name \"hello\"` |\n| `int` | Parsed as integer | `--count 42` |\n| `float` | Parsed as float | `--rate 0.1` |\n| `bool` | Flag with negative | `--debug` or `--no-debug` |\n| `List[T]` | Multiple values | `--items a b c` |\n| `Dict[str, Any]` | Config file + overrides | `--config file.json --c key:value` |\n| `Optional[T]` | Optional parameter | `--timeout 30` (or omit) |\n| `Path` | Path object | `--output /path/to/file` |\n| Custom types | String representation | `--custom \"value\"` |\n\n## Configuration File Formats\n\nSupports multiple configuration file formats:\n\n### JSON\n```json\n{\n  \"name\": \"MyApp\",\n  \"count\": 42,\n  \"database\": {\n    \"host\": \"localhost\",\n    \"port\": 5432\n  }\n}\n```\n\n### YAML (requires `pip install \"dataclass-args[yaml]\"`)\n```yaml\nname: MyApp\ncount: 42\ndatabase:\n  host: localhost\n  port: 5432\n```\n\n### TOML (requires `pip install \"dataclass-args[toml]\"`)\n```toml\nname = \"MyApp\"\ncount = 42\n\n[database]\nhost = \"localhost\"\nport = 5432\n```\n\n## Examples\n\nCheck the [`examples/`](examples/) directory for complete working examples:\n\n- **`positional_example.py`** - Positional arguments and variable length args\n- **`boolean_flags_example.py`** - Boolean flags with `--flag` and `--no-flag`\n- **`cli_choices_example.py`** - Value validation with choices\n- **`cli_short_example.py`** - Short option flags\n- **`all_features_example.py`** - All features together\n- And more...\n\n### Web Server Configuration\n\n```python\nfrom dataclasses import dataclass\nfrom typing import List\nfrom dataclass_args import build_config, cli_short, cli_help, cli_exclude, cli_file_loadable, combine_annotations\n\n@dataclass\nclass ServerConfig:\n    # Basic server settings\n    host: str = combine_annotations(\n        cli_short('h'),\n        cli_help(\"Server bind address\"),\n        default=\"127.0.0.1\"\n    )\n\n    port: int = combine_annotations(\n        cli_short('p'),\n        cli_help(\"Server port number\"),\n        default=8000\n    )\n\n    workers: int = combine_annotations(\n        cli_short('w'),\n        cli_help(\"Number of worker processes\"),\n        default=1\n    )\n\n    # Security settings\n    ssl_cert: str = cli_file_loadable(cli_help(\"SSL certificate content\"))\n    ssl_key: str = cli_file_loadable(cli_help(\"SSL private key content\"))\n\n    # Application settings\n    debug: bool = combine_annotations(\n        cli_short('d'),\n        cli_help(\"Enable debug mode\"),\n        default=False\n    )\n\n    allowed_hosts: List[str] = cli_help(\"Allowed host headers\", default_factory=list)\n\n    # Internal fields (hidden from CLI)\n    _server_id: str = cli_exclude(default_factory=lambda: f\"server-{os.getpid()}\")\n\nif __name__ == \"__main__\":\n    config = build_config(ServerConfig)\n    print(f\"Starting server on {config.host}:{config.port}\")\n```\n\n```bash\n# Start server with short options\n$ python server.py -h 0.0.0.0 -p 9000 -w 4 -d\n\n# Load SSL certificates from files\n$ python server.py --ssl-cert \"@certs/server.crt\" --ssl-key \"@certs/server.key\"\n```\n\n## Contributing\n\nContributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n```bash\ngit clone https://github.com/bassmanitram/dataclass-args.git\ncd dataclass-args\npip install -e \".[dev,all]\"\n```\n\n### Development Setup\n\n```bash\ngit clone https://github.com/bassmanitram/dataclass-args.git\ncd dataclass-args\npip install -e \".[dev,all]\"\nmake setup  # Install dev dependencies and pre-commit hooks\n```\n\n### Running Tests\n\n```bash\n# Run all tests (coverage is automatic)\npytest\nmake test\n\n# Run tests with detailed coverage report\nmake coverage\n\n# Run tests with coverage and open HTML report\nmake coverage-html\n\n# Run specific test file\npytest tests/test_cli_short.py\n\n# Verbose output\npytest -v\n```\n\n### Code Coverage\n\nThis project maintains **94%+ code coverage**. Coverage reports are generated automatically when running tests.\n\n- **Quick check**: `make coverage`\n- **Detailed report**: See `htmlcov/index.html`\n- **Coverage docs**: [COVERAGE.md](COVERAGE.md)\n\nAll code changes should maintain or improve coverage. The minimum required coverage is 90%.\n\n### Code Formatting\n\n```bash\n# Format code\nmake format\nblack dataclass_args/ tests/ examples/\nisort dataclass_args/ tests/ examples/\n\n# Check formatting\nmake lint\nblack --check dataclass_args/ tests/\nflake8 dataclass_args/ tests/\nmypy dataclass_args/\n```\n\n### Full Check (like CI)\n\n```bash\n# Run all checks: linting, tests, and examples\nmake check\n```\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history and changes.\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/bassmanitram/dataclass-args/issues)\n- **Documentation**: This README and comprehensive docstrings\n- **Examples**: See the [examples/](examples/) directory\n\n## Quick Reference\n\n```python\nfrom dataclasses import dataclass\nfrom dataclass_args import (\n    build_config,                # Main function\n    cli_short,                   # Short options: -n\n    cli_positional,              # Positional args\n    cli_choices,                 # Value validation\n    cli_help,                    # Custom help text\n    cli_exclude,                 # Hide from CLI\n    cli_file_loadable,           # @file loading\n    combine_annotations,         # Combine features\n)\n\n@dataclass\nclass Config:\n    # Simple field\n    name: str\n\n    # Positional argument\n    input_file: str = cli_positional()\n\n    # With short option\n    port: int = cli_short('p', default=8000)\n\n    # With choices\n    env: str = cli_choices(['dev', 'prod'], default='dev')\n\n    # Boolean flag\n    debug: bool = False  # Creates --debug and --no-debug\n\n    # Combine everything\n    region: str = combine_annotations(\n        cli_short('r'),\n        cli_choices(['us-east-1', 'us-west-2']),\n        cli_help(\"AWS region\"),\n        default='us-east-1'\n    )\n\n    # Hidden from CLI\n    secret: str = cli_exclude(default=\"hidden\")\n\n    # File-loadable\n    config_text: str = cli_file_loadable(default=\"\")\n\n# Build and use\nconfig = build_config(Config)\n```\n\nDefine your dataclass, add annotations as needed, and call `build_config()` to parse command-line arguments.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Zero-boilerplate CLI generation from Python dataclasses with advanced type support and file loading",
    "version": "1.1.0",
    "project_urls": {
        "Documentation": "https://github.com/bassmanitram/dataclass-args#readme",
        "Homepage": "https://github.com/bassmanitram/dataclass-args",
        "Issues": "https://github.com/bassmanitram/dataclass-args/issues",
        "Repository": "https://github.com/bassmanitram/dataclass-args"
    },
    "split_keywords": [
        "cli",
        " dataclass",
        " argparse",
        " configuration",
        " command-line",
        " type-safe",
        " validation",
        " file-loading",
        " config-merging"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5f03ac2ff57ebca8fbebfc407eae10fb180988f6c266c33dea6cf25a9d48d7b3",
                "md5": "e31851cbd89410a06f95b4847d6087d4",
                "sha256": "3e5ed7888e14f429c827a416ce68f1fb3b635262a3a05fc714d35d7da531b6e1"
            },
            "downloads": -1,
            "filename": "dataclass_args-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e31851cbd89410a06f95b4847d6087d4",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 22921,
            "upload_time": "2025-11-03T18:25:57",
            "upload_time_iso_8601": "2025-11-03T18:25:57.001932Z",
            "url": "https://files.pythonhosted.org/packages/5f/03/ac2ff57ebca8fbebfc407eae10fb180988f6c266c33dea6cf25a9d48d7b3/dataclass_args-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7a80d29499a1952b5e393b9fe66cf9f07605c48547ce517af617c1d6a92ce9e6",
                "md5": "5ce9f1215cf339bd2a52224304f7e72e",
                "sha256": "9aa15a485c5b36efe15cda64b09d9a0144a79808f8163305a00ab517f7b66052"
            },
            "downloads": -1,
            "filename": "dataclass_args-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "5ce9f1215cf339bd2a52224304f7e72e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 47666,
            "upload_time": "2025-11-03T18:25:58",
            "upload_time_iso_8601": "2025-11-03T18:25:58.146345Z",
            "url": "https://files.pythonhosted.org/packages/7a/80/d29499a1952b5e393b9fe66cf9f07605c48547ce517af617c1d6a92ce9e6/dataclass_args-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-03 18:25:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "bassmanitram",
    "github_project": "dataclass-args#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "dataclass-args"
}
        
Elapsed time: 2.06452s