valid8r.integrations.typer

Typer integration for valid8r parsers.

This module provides TyperParser to use valid8r parsers as Typer parameter types. Since Typer uses Click internally, TyperParser wraps the Click ParamTypeAdapter.

Examples

>>> import typer
>>> from typing_extensions import Annotated
>>> from valid8r.core import parsers
>>> from valid8r.integrations.typer import TyperParser
>>>
>>> app = typer.Typer()
>>>
>>> # Basic usage with email parser
>>> @app.command()
... def create_user(
...     email: Annotated[str, typer.Option(parser=TyperParser(parsers.parse_email))]
... ) -> None:
...     print(f"Creating user: {email.local}@{email.domain}")
>>>
>>> # With chained validators for port validation
>>> from valid8r.core import validators
>>> def port_parser(text: str | None):
...     return parsers.parse_int(text).bind(
...         validators.minimum(1) & validators.maximum(65535)
...     )
>>> @app.command()
... def start_server(
...     port: Annotated[int, typer.Option(parser=TyperParser(port_parser))]
... ) -> None:
...     print(f"Starting server on port {port}")

Classes

TyperParser

Typer parameter type adapter for valid8r parsers.

ValidatedType

Create a custom Typer type with valid8r validation.

Functions

validator_callback(parser, *validators[, error_prefix])

Create a Typer callback function from a valid8r parser and optional validators.

validate_with(param_name, parser, *validators)

Add validation to a Typer command parameter.

validated_prompt(prompt_text, parser, *validators[, ...])

Prompt interactively with valid8r validation and retry logic.

Module Contents

class valid8r.integrations.typer.TyperParser(parser, name=None, error_prefix=None)[source]

Bases: valid8r.integrations.click.ParamTypeAdapter

Typer parameter type adapter for valid8r parsers.

This class wraps a valid8r parser function (returning Maybe[T]) into a Typer-compatible parameter type. Since Typer uses Click internally, this is a thin wrapper around ParamTypeAdapter that can be used with Typer’s Option() and Argument().

TyperParser can be used in two ways with Typer: 1. As a Click ParamType: typer.Option(click_type=TyperParser(…)) 2. As a callable parser: typer.Option(parser=TyperParser(…))

Parameters:

Examples

>>> from valid8r.core import parsers
>>> from valid8r.integrations.typer import TyperParser
>>>
>>> # Simple email validation
>>> email_type = TyperParser(parsers.parse_email)
>>> email_type.name
'parse_email'
>>>
>>> # With custom name
>>> port_type = TyperParser(parsers.parse_int, name='port')
>>> port_type.name
'port'
>>>
>>> # With custom error prefix
>>> email_type = TyperParser(
...     parsers.parse_email,
...     error_prefix='Email address'
... )
__name__[source]
__call__(value, param=None, ctx=None)[source]

Make TyperParser callable for use with Typer’s parser parameter.

When used as parser=TyperParser(…), Typer wraps this in a FuncParamType and calls it directly. We delegate to the convert method which handles the Maybe conversion and error handling.

Parameters:
  • value (str) – The input string to parse

  • param (click.Parameter | None) – Optional Click Parameter (can be named param or _param)

  • ctx (click.Context | None) – Optional Click Context (can be named ctx or _ctx)

Returns:

The successfully parsed and validated value

Raises:

click.exceptions.BadParameter – If validation fails

Return type:

object

valid8r.integrations.typer.validator_callback(parser, *validators, error_prefix=None)[source]

Create a Typer callback function from a valid8r parser and optional validators.

This factory function creates a callback that can be used with Typer’s Option() or Argument() callback parameter. The callback will parse and validate the input, returning the validated value or raising typer.BadParameter on failure.

Parameters:
Returns:

A callback function compatible with Typer’s callback parameter

Return type:

collections.abc.Callable[[str], object]

Examples

>>> from valid8r.core import parsers, validators
>>> from valid8r.integrations.typer import validator_callback
>>> import typer
>>>
>>> # Simple email validation
>>> email_callback = validator_callback(parsers.parse_email)
>>>
>>> # Port validation with range checking
>>> def port_parser(text: str | None):
...     return parsers.parse_int(text).bind(
...         validators.minimum(1) & validators.maximum(65535)
...     )
>>> port_callback = validator_callback(port_parser)
>>>
>>> # Use in Typer command
>>> app = typer.Typer()
>>> @app.command()
... def serve(
...     port: int = typer.Option(8000, callback=port_callback)
... ) -> None:
...     print(f"Serving on port {port}")
valid8r.integrations.typer.validate_with(param_name, parser, *validators)[source]

Add validation to a Typer command parameter.

This decorator modifies a Typer command to use a validator callback for a specific parameter. The validated/converted value replaces the original string parameter before the command executes.

Note: This decorator should be applied BEFORE @app.command() so that Typer sees the modified default values with callbacks attached.

Parameters:
Returns:

A decorator function that modifies the Typer command

Return type:

collections.abc.Callable[[collections.abc.Callable[Ellipsis, Any]], collections.abc.Callable[Ellipsis, Any]]

Examples

>>> from valid8r.core import parsers, validators
>>> from valid8r.integrations.typer import validate_with
>>> import typer
>>>
>>> app = typer.Typer()
>>>
>>> @app.command()
... @validate_with('email', parsers.parse_email)
... def send(email: str = typer.Option(...)) -> None:
...     # email is now an EmailAddress object
...     print(f"Sending to {email.local}@{email.domain}")
>>>
>>> @app.command()
... @validate_with('email', parsers.parse_email)
... @validate_with('age', parsers.parse_int, validators.minimum(0))
... def register(
...     email: str = typer.Option(...),
...     age: str = typer.Option(...)
... ) -> None:
...     # Both parameters are validated
...     print(f"Registered {email.local}, age {age}")
class valid8r.integrations.typer.ValidatedType[source]

Create a custom Typer type with valid8r validation.

This class wraps a valid8r parser into a Click ParamType that can be used with Typer’s type annotations. It provides a cleaner alternative to using TyperParser directly in type hints.

Parameters:
  • parser – A valid8r parser function that returns Maybe[T]

  • name – Optional custom name for the type

  • help_text – Optional help text describing validation constraints (reserved for future use)

Examples

>>> from valid8r.core import parsers
>>> from valid8r.integrations.typer import ValidatedType
>>> import typer
>>>
>>> # Create custom types
>>> Email = ValidatedType(parsers.parse_email)
>>> Phone = ValidatedType(parsers.parse_phone)
>>>
>>> app = typer.Typer()
>>>
>>> @app.command()
... def contact(
...     email: Email = typer.Option(...),  # type: ignore[valid-type]
...     phone: Phone = typer.Option(None)   # type: ignore[valid-type]
... ) -> None:
...     # email is EmailAddress, phone is Optional[PhoneNumber]
...     print(f"Contact: {email.local}@{email.domain}")
valid8r.integrations.typer.validated_prompt(prompt_text, parser, *validators, max_retries=10, typer_style=False)[source]

Prompt interactively with valid8r validation and retry logic.

This function prompts the user for input, validates it using a valid8r parser and optional validators, and re-prompts on validation failure up to max_retries. After max_retries, it raises a Typer exception to exit the CLI.

Parameters:
Returns:

The validated and parsed value

Raises:

typer.Exit – If max_retries is exceeded without valid input

Return type:

object

Examples

>>> from valid8r.core import parsers
>>> from valid8r.integrations.typer import validated_prompt
>>> import typer
>>>
>>> app = typer.Typer()
>>>
>>> @app.command()
... def interactive() -> None:
...     email = validated_prompt(
...         "Enter email",
...         parser=parsers.parse_email,
...         typer_style=True
...     )
...     print(f"Got email: {email.local}@{email.domain}")