valid8r.integrations

Integrations with popular Python frameworks and libraries.

This module provides integrations with popular Python frameworks:

  • argparse: Standard library CLI integration via type_from_parser

  • Click: CLI framework integration via ParamTypeAdapter

  • Typer: Modern CLI framework integration via TyperParser

  • Pydantic: Field validator integration via validator_from_parser

  • Environment Variables: Schema-based configuration loading via load_env_config

Examples

argparse integration:

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

parser = argparse.ArgumentParser()
parser.add_argument('--email', type=type_from_parser(parsers.parse_email))
args = parser.parse_args(['--email', 'alice@example.com'])
print(f"Hello {args.email.local}@{args.email.domain}!")

Click integration:

from valid8r.integrations.click import ParamTypeAdapter
from valid8r.core import parsers
import click

@click.command()
@click.option('--email', type=ParamTypeAdapter(parsers.parse_email))
def greet(email):
    click.echo(f"Hello {email.local}@{email.domain}!")

Typer integration:

from valid8r.integrations.typer import TyperParser
import typer
from typing_extensions import Annotated

app = typer.Typer()
@app.command()
def greet(
    email: Annotated[str, typer.Option(parser=TyperParser(parsers.parse_email))]
) -> None:
    print(f"Hello {email.local}@{email.domain}!")

Pydantic integration:

from valid8r.integrations.pydantic import validator_from_parser
from pydantic import BaseModel

class User(BaseModel):
    email: str
    _validate_email = validator_from_parser(parsers.parse_email)

Environment variable integration:

from valid8r.integrations.env import load_env_config, EnvSchema, EnvField
from valid8r.core import parsers

schema = EnvSchema(fields={
    'port': EnvField(parser=parsers.parse_int, default=8080),
    'debug': EnvField(parser=parsers.parse_bool, default=False),
})
result = load_env_config(schema, prefix='APP_')

Submodules

Classes

EnvField

Represents a field in an environment variable schema.

EnvSchema

Represents a schema for environment variable configuration.

Functions

load_env_config(schema, *[, prefix, delimiter, environ])

Load and validate configuration from environment variables.

make_after_validator(parser)

Create a Pydantic AfterValidator from a valid8r parser.

make_wrap_validator(parser)

Create a Pydantic WrapValidator from a valid8r parser.

validator_from_parser(parser, *[, error_prefix])

Convert a valid8r parser into a Pydantic field validator.

Package Contents

class valid8r.integrations.EnvField[source]

Represents a field in an environment variable schema.

Parameters:
  • parser – A function that parses a string into a Maybe[T]

  • default – Optional default value if environment variable is not set

  • required – Whether this field must be present in the environment

  • nested – Optional nested schema for hierarchical configuration

parser: collections.abc.Callable[[str | None], valid8r.core.maybe.Maybe[Any]] | None
default: Any = None
required: bool = False
nested: EnvSchema | None = None
class valid8r.integrations.EnvSchema[source]

Represents a schema for environment variable configuration.

Parameters:

fields – Dictionary mapping field names to EnvField objects

fields: dict[str, EnvField]
valid8r.integrations.load_env_config(schema, *, prefix='', delimiter='_', environ=None)[source]

Load and validate configuration from environment variables.

Parameters:
  • schema (EnvSchema) – The EnvSchema defining expected fields and their parsers

  • prefix (str) – Optional prefix for environment variable names (e.g., ‘APP_’)

  • delimiter (str) – Delimiter for nested configuration (default: ‘_’)

  • environ (dict[str, str] | None) – Optional dict of environment variables (defaults to os.environ)

Returns:

Success with parsed config dict, or Failure with error message

Return type:

Maybe[dict]

Example

>>> from valid8r.integrations.env import load_env_config, EnvSchema, EnvField
>>> from valid8r.core.parsers import parse_int
>>> schema = EnvSchema(fields={'port': EnvField(parser=parse_int, default=8080)})
>>> env = {'APP_PORT': '3000'}
>>> result = load_env_config(schema, prefix='APP_', environ=env)
>>> result.value_or({})
{'port': 3000}
valid8r.integrations.make_after_validator(parser)[source]

Create a Pydantic AfterValidator from a valid8r parser.

AfterValidator runs after Pydantic’s type conversion, allowing you to use valid8r parsers with Pydantic’s Annotated type system for cleaner model definitions.

This function wraps a valid8r parser (which returns Maybe[T]) into a function suitable for use with Pydantic’s AfterValidator. For optional fields (e.g., str | None), None values are passed through without validation.

Parameters:

parser (collections.abc.Callable[[Any], valid8r.core.maybe.Maybe[T]]) – A valid8r parser function that returns Maybe[T].

Returns:

A validator function that returns T on success, None for None inputs, or raises ValueError on failure.

Raises:

ValueError – When the parser returns a Failure with the error message.

Return type:

collections.abc.Callable[[Any], T | None]

Example

>>> from pydantic import BaseModel, AfterValidator
>>> from typing_extensions import Annotated
>>> from valid8r.core import parsers
>>>
>>> email_validator = make_after_validator(parsers.parse_email)
>>>
>>> class User(BaseModel):
...     email: Annotated[str, AfterValidator(email_validator)]
>>>
>>> user = User(email='alice@example.com')
>>> # Optional field example
>>> class Contact(BaseModel):
...     email: Annotated[str | None, AfterValidator(email_validator)] = None
>>>
>>> contact = Contact(email=None)
>>> contact.email is None
True
valid8r.integrations.make_wrap_validator(parser)[source]

Create a Pydantic WrapValidator from a valid8r parser.

WrapValidator runs before Pydantic’s type conversion, receiving raw input values. This allows full control over validation and pre-processing.

This function wraps a valid8r parser (which returns Maybe[T]) into a function suitable for use with Pydantic’s WrapValidator.

Parameters:

parser (collections.abc.Callable[[Any], valid8r.core.maybe.Maybe[T]]) – A valid8r parser function that returns Maybe[T].

Returns:

A wrap validator function that returns T on success or raises ValueError on failure. The function signature is (value, handler) -> T, though handler is not used since the parser handles all validation.

Raises:

ValueError – When the parser returns a Failure with the error message.

Return type:

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

Example

>>> from pydantic import BaseModel, WrapValidator
>>> from typing_extensions import Annotated
>>> from valid8r.core import parsers
>>>
>>> int_validator = make_wrap_validator(parsers.parse_int)
>>>
>>> class Data(BaseModel):
...     value: Annotated[int, WrapValidator(int_validator)]
>>>
>>> data = Data(value='42')
valid8r.integrations.validator_from_parser(parser, *, error_prefix=None)[source]

Convert a valid8r parser into a Pydantic field validator.

This function takes a valid8r parser (any callable that returns Maybe[T]) and converts it into a function suitable for use with Pydantic’s field_validator decorator.

Works seamlessly with: - Simple fields (str, int, custom types) - Nested models (User -> Address -> phone) - Lists of models (Order with list[LineItem]) - Dicts with validated values (Config with dict[str, int]) - Optional fields (field: Model | None)

Pydantic automatically handles field path reporting for nested structures, so validation errors will include the full path (e.g., ‘address.phone’ or ‘items[1].quantity’).

Parameters:
Returns:

A validator function that returns T on success or raises ValueError on failure.

Raises:

ValueError – When the parser returns a Failure with the error message.

Return type:

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

Example

>>> from valid8r.core import parsers
>>> validator = validator_from_parser(parsers.parse_int)
>>> validator('42')
42
>>> validator('invalid')
Traceback (most recent call last):
    ...
ValueError: ...
>>> # With custom error prefix
>>> validator = validator_from_parser(parsers.parse_int, error_prefix='User ID')
>>> validator('invalid')
Traceback (most recent call last):
    ...
ValueError: User ID: ...
>>> # Nested model validation
>>> from pydantic import BaseModel, field_validator
>>> from valid8r.core.parsers import EmailAddress
>>>
>>> class Contact(BaseModel):
...     email: EmailAddress
...
...     @field_validator('email', mode='before')
...     @classmethod
...     def validate_email(cls, v):
...         return validator_from_parser(parsers.parse_email)(v)
>>>
>>> contact = Contact(email='user@example.com')