Skip to main content

Simple class-based argument parsing for python scripts

Project description

argsclass

Simple class-based argument parsing for python scripts

Implementation Note

As of version 0.4.0, argsclass uses argparse as its backend parsing engine while maintaining the same public API. This migration provides:

  • Better error messages: More detailed and user-friendly error reporting
  • Standard help formatting: Uses argparse's proven help system
  • Improved maintainability: Reduced custom code by ~500 lines
  • Enhanced compatibility: Leverages argparse's battle-tested parsing logic

The migration is purely internal - all existing code continues to work unchanged.

Class Inspection

The inspect_class function allows you to convert a class definition into a list of ArgSpec objects. This enables you to define your command-line arguments using class attributes with type hints and descriptors.

Basic Usage

from argsclass import inspect_class, positional

class Args:
    flag: bool                    # Boolean attributes become flags
    option: str = "default"       # Attributes with defaults become options
    Name: str = positional(help_text="foo")  # Use descriptors for positional args

specs = inspect_class(Args)
# Returns: [FlagArgSpec("flag"), OptionArgSpec("option"), PositionalArgSpec("Name")]

Type Inference

The inspector automatically infers argument types from type hints:

  • boolFlagArgSpec (boolean flags)
  • str, int, floatOptionArgSpec or PositionalArgSpec (depending on descriptor)
  • Attributes with default values → OptionArgSpec
  • Attributes with positional() descriptor → PositionalArgSpec

Descriptors

Use descriptors to create specific argument types:

from argsclass import positional, option, flag

class Args:
    # Positional argument
    filename = positional(help_text="Input file", arg_type=str)
    
    # Option with choices
    format = option(help_text="Output format", choices=["json", "xml"], default="json")
    
    # Flag with aliases
    verbose = flag(help_text="Verbose output", aliases={"v"})

Complete Example

from argsclass import inspect_class, positional, option, flag

class MyArgs:
    # Boolean flag (inferred from type hint)
    verbose: bool
    
    # Option with default
    output: str = "output.txt"
    
    # Positional argument
    filename = positional(help_text="Input file", arg_type=str)
    
    # Option with choices and aliases
    format = option(help_text="Output format", choices=["json", "xml"], aliases={"f"})
    
    # Flag with aliases
    debug = flag(help_text="Enable debug mode", aliases={"d"})

# Convert to ArgSpec objects
specs = inspect_class(MyArgs)
for spec in specs:
    print(f"{spec.__class__.__name__}: {spec.name}")

## Argument Parsing

The `parse` function can parse command-line arguments using either a list of ArgSpec objects or a class definition.

### Parsing with Classes

```python
from argsclass import parse, positional, option, flag

class MyArgs:
    verbose: bool
    output: str = "output.txt"
    filename = positional(help_text="Input file")

# Parse directly from class
result = parse(MyArgs, ["script.py", "--verbose", "input.txt"])
print(result)  # {'verbose': True, 'output': 'output.txt', 'filename': 'input.txt'}

Parsing with ArgSpec Lists

from argsclass import parse, PositionalArgSpec, OptionArgSpec, FlagArgSpec

specs = [
    PositionalArgSpec(name="filename"),
    OptionArgSpec(name="output", aliases={"o"}),
    FlagArgSpec(name="verbose", aliases={"v"})
]

result = parse(specs, ["script.py", "input.txt", "-o", "output.txt", "-v"])
print(result)  # {'filename': 'input.txt', 'output': 'output.txt', 'verbose': True}

Ambiguity Protection

The parser includes built-in protection against ambiguous argument configurations that could lead to unpredictable parsing behavior.

Ambiguous Configurations

The following configurations are considered ambiguous and will raise an AmbiguityError:

  1. Multiple positional arguments with non-specific cardinality:

    class AmbiguousArgs:
        files1 = positional(cardinality=Cardinality.one_or_more())
        files2 = positional(cardinality=Cardinality.zero_or_more())
    
  2. Multiple option arguments with non-specific cardinality:

    class AmbiguousArgs:
        files1 = option(cardinality=Cardinality.one_or_more())
        files2 = option(cardinality=Cardinality.zero_or_more())
    

Note: Mixed positional and option arguments with non-specific cardinality are NOT ambiguous because they are parsed differently:

  • Options are parsed by name (e.g., --option value)
  • Positionals are parsed by position

This configuration is valid:

class ValidArgs:
    files = positional(cardinality=Cardinality.one_or_more())  # Parsed by position
    tags = option(cardinality=Cardinality.zero_or_more())      # Parsed by name

Note: The parsing order matters! Arguments are processed in the order they appear in the class definition. For mixed positional and option arguments, it's recommended to define options first, then positionals:

class RecommendedOrder:
    tags = option(cardinality=Cardinality.zero_or_more())      # Processed first
    files = positional(cardinality=Cardinality.one_or_more())  # Processed second

Resolving Ambiguities

To resolve ambiguities, consider these approaches:

  1. Use specific cardinalities:

    class ValidArgs:
        input_file = positional()  # Single value
        output_file = positional()  # Single value
        files = positional(cardinality=Cardinality.one_or_more())  # Only one with non-specific
    
  2. Reorder arguments (put non-specific cardinality last):

    class ValidArgs:
        input_file = positional()  # Specific first
        output_file = positional()  # Specific second
        extra_files = positional(cardinality=Cardinality.zero_or_more())  # Non-specific last
    
  3. Use different argument types (this is actually always valid):

    class ValidArgs:
        input_file = positional()  # Positional for required
        extra_files = option(cardinality=Cardinality.zero_or_more())  # Option for optional
    

Disabling Ambiguity Validation

If you need to disable ambiguity validation (not recommended), you can set validate_ambiguities=False:

result = parse(MyArgs, argv, validate_ambiguities=False)

Ambiguity Detection Functions

You can also manually check for ambiguities:

from argsclass import detect_ambiguities, is_ambiguous, get_ambiguity_resolution_suggestions

# Check if configuration is ambiguous
if is_ambiguous(MyArgs):
    warnings = detect_ambiguities(MyArgs)
    suggestions = get_ambiguity_resolution_suggestions(MyArgs)
    print("Ambiguities found:", warnings)
    print("Suggestions:", suggestions)

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

argsclass-0.4.0.tar.gz (39.0 kB view details)

Uploaded Source

Built Distribution

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

argsclass-0.4.0-py3-none-any.whl (25.3 kB view details)

Uploaded Python 3

File details

Details for the file argsclass-0.4.0.tar.gz.

File metadata

  • Download URL: argsclass-0.4.0.tar.gz
  • Upload date:
  • Size: 39.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for argsclass-0.4.0.tar.gz
Algorithm Hash digest
SHA256 dc8299b5b17a915c582e97a10a048edea0a197fab7ebea96323c4e1a2d766de0
MD5 0a09b32438aaadadafabb1e07e1a0443
BLAKE2b-256 d2237adac3bdd9ff587b546672eaf8cce2b680252581ae4311d4ba3e9eca6dea

See more details on using hashes here.

Provenance

The following attestation bundles were made for argsclass-0.4.0.tar.gz:

Publisher: pypi-publish.yml on dotle-git/argsclass

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file argsclass-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: argsclass-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 25.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for argsclass-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c89612d33fd2fbe32af9dd4ab2f2bf6f644af8dd76725187b0ffbdad18845676
MD5 f6946ac75b953ee3c2a62bbd3b0c1068
BLAKE2b-256 2426fd78a268fc98de462a0c6972eee428f9907fcdabf9aebddb3eed75ab30b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for argsclass-0.4.0-py3-none-any.whl:

Publisher: pypi-publish.yml on dotle-git/argsclass

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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