Source code for valid8r.integrations.argparse

"""argparse integration for valid8r parsers.

This module provides type_from_parser to convert valid8r parsers into argparse-compatible
type functions that can be used with ArgumentParser.add_argument().

argparse's type parameter expects a callable that takes a string and either returns
a converted value (on success) or raises TypeError or ValueError (on failure).

Examples:
    Basic usage with email parser::

        import argparse
        from valid8r.core import parsers
        from valid8r.integrations.argparse import type_from_parser

        parser = argparse.ArgumentParser()
        parser.add_argument(
            '--email',
            type=type_from_parser(parsers.parse_email),
            help='Email address'
        )

    With chained validators for port validation::

        from valid8r.core import parsers, validators
        from valid8r.integrations.argparse import type_from_parser

        def port_parser(text):
            return parsers.parse_int(text).bind(
                validators.minimum(1) & validators.maximum(65535)
            )
        parser = argparse.ArgumentParser()
        parser.add_argument(
            '--port',
            type=type_from_parser(port_parser),
            help='Port number (1-65535)'
        )

"""

from __future__ import annotations

from typing import (
    TYPE_CHECKING,
    TypeVar,
    cast,
)

if TYPE_CHECKING:
    from collections.abc import Callable

    from valid8r.core.maybe import Maybe

from valid8r.core.maybe import (
    Failure,
    Success,
)

T = TypeVar('T')


[docs] def type_from_parser(parser: Callable[[str | None], Maybe[T]]) -> Callable[[str], T]: """Convert a valid8r parser into an argparse-compatible type function. Creates a callable that can be used as the 'type' parameter in ArgumentParser.add_argument(). The returned function takes a string, parses it using the provided valid8r parser, and either returns the successfully parsed value or raises ValueError with the error message. Args: parser: A valid8r parser function that takes a string and returns Maybe[T] Returns: A callable suitable for use with argparse's 'type' parameter Raises: ValueError: When the parser returns a Failure (invalid input) Examples: >>> from valid8r.core import parsers >>> from valid8r.integrations.argparse import type_from_parser >>> >>> # Create an argparse type for email validation >>> email_type = type_from_parser(parsers.parse_email) >>> email = email_type('alice@example.com') >>> email.local 'alice' >>> >>> # Invalid input raises ValueError >>> try: ... email_type('not-an-email') ... except ValueError as e: ... print('Error:', e) Error: ... """ def argparse_type(value: str) -> T: """Argparse type function that uses valid8r parser. Args: value: The string value to parse Returns: The successfully parsed and validated value Raises: ValueError: If validation fails """ # Parse the value using the valid8r parser result = parser(value) # Handle the Maybe result match result: case Success(parsed_value): # Cast to T to satisfy mypy's return type checking return cast('T', parsed_value) case Failure(error_msg): # argparse expects TypeError or ValueError on failure # ValueError is more appropriate for validation failures raise ValueError(error_msg) from None # This should never be reached due to exhaustive pattern matching # but mypy doesn't know that msg = 'Unexpected Maybe state' # pragma: no cover raise RuntimeError(msg) # pragma: no cover return argparse_type
__all__ = ['type_from_parser']