跳转至

配置 API

配置框架。叙述性指南见 配置系统

核心

Config

Config(**initial_values: Any)

Elegant configuration base class with declarative field definitions.

This base class provides a powerful framework for creating type-safe, validated configuration classes with IDE-friendly attribute access. It supports automatic type inference, chainable configuration loading, and immutability through freezing.

Features: - Declarative field definitions with explicit constraint validation - IDE-friendly attribute access with full autocomplete support - Chainable configuration loading from multiple sources - Immutability support through freezing - Dictionary-style access support - Comprehensive validation and error reporting

Attributes:

Name Type Description
_config_fields Dict[str, ConfigField]

Dictionary of field names to ConfigField descriptors.

_values Dict[str, Any]

Internal storage for field values.

_frozen

Boolean indicating whether the configuration is frozen.

Examples:

>>> class DatabaseConfig(Config):
...     host: str = ConfigField(default="localhost", doc="Database host")
...     port: int = ConfigField(default=5432, doc="Database port")
...     timeout: float = ConfigField(
...         default=30.0,
...         constraint=RangeConstraint(1.0, 300.0),
...         doc="Connection timeout in seconds"
...     )
>>> config = DatabaseConfig()
>>> config.from_file("db_config.yaml").from_env("DB_").freeze()
>>> print(f"Connecting to {config.host}:{config.port}")

Initializes a configuration instance with optional initial values.

Parameters:

Name Type Description Default
**initial_values Any

Initial field values to set. Keys must match defined configuration field names.

{}

Raises:

Type Description
KeyError

If any key in initial_values doesn't correspond to a defined configuration field.

from_file

from_file(config_file: str) -> Self

Loads configuration from a file (chainable).

Supports JSON, YAML, and TOML formats. Only updates fields that exist in both the file and the configuration class.

Parameters:

Name Type Description Default
config_file str

Path to the configuration file.

required

Returns:

Type Description
Self

Self for method chaining.

Raises:

Type Description
FileNotFoundError

If the configuration file doesn't exist.

ValueError

If the file format is unsupported.

Examples:

>>> config = MyConfig().from_file("app.yaml").from_file("override.json")

from_dict

from_dict(config_dict: Dict[str, Any]) -> Self

Loads configuration from a dictionary (chainable).

Only updates fields that exist in both the dictionary and the configuration class definition.

Parameters:

Name Type Description Default
config_dict Dict[str, Any]

Dictionary containing configuration values.

required

Returns:

Type Description
Self

Self for method chaining.

Examples:

>>> config_data = {"learning_rate": 0.001, "batch_size": 32}
>>> config = MyConfig().from_dict(config_data)
Note

Keys that do not match any field are ignored with a warning (likely typos — they would otherwise silently fall back to the default).

from_kwargs

from_kwargs(**kwargs: Any) -> Self

Loads configuration from keyword arguments (chainable).

Parameters:

Name Type Description Default
**kwargs Any

Configuration values as keyword arguments.

{}

Returns:

Type Description
Self

Self for method chaining.

Examples:

>>> config = MyConfig().from_kwargs(learning_rate=0.001, epochs=100)

from_args

from_args(args: Union[Namespace, ArgumentParser]) -> Self

Loads configuration from command line arguments (chainable).

Parameters:

Name Type Description Default
args Union[Namespace, ArgumentParser]

Either an ArgumentParser (will call parse_args()) or a Namespace object from parse_args().

required

Returns:

Type Description
Self

Self for method chaining.

Examples:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--learning-rate', type=float)
>>> config = MyConfig().from_args(parser)

from_env

from_env(prefix: str = '') -> Self

Loads configuration from environment variables (chainable).

Environment variable names are constructed by combining the prefix with field names, converted to uppercase.

Parameters:

Name Type Description Default
prefix str

Prefix to prepend to field names when looking up environment variables. Will be converted to uppercase.

''

Returns:

Type Description
Self

Self for method chaining.

Examples:

>>> # Looks for APP_LEARNING_RATE, APP_BATCH_SIZE, etc.
>>> config = MyConfig().from_env("APP_")

freeze

freeze() -> Self

Freezes the configuration, making it immutable (chainable).

After freezing, any attempt to modify field values will raise an AttributeError.

Returns:

Type Description
Self

Self for method chaining.

Examples:

>>> config = MyConfig().from_file("config.yaml").freeze()
>>> config.learning_rate = 0.1  # Raises AttributeError

unfreeze

unfreeze() -> Self

Unfreezes the configuration, allowing modifications (chainable).

After unfreezing, field values can be modified again.

Returns:

Type Description
Self

Self for method chaining.

copy

copy() -> Self

Creates a copy of the configuration (never frozen, even if the original was).

Mutable field values (list/dict/set) are deep-copied so the copy is independent of the original. Fields that are None on the original are left at the new instance's default — this skip is deliberate: setting a required field to None would trip required-validation, so copying a config with unset required fields must not do that.

Returns:

Type Description
Self

A new configuration instance with the same field values.

Examples:

>>> original = MyConfig().from_file("config.yaml").freeze()
>>> editable_copy = original.copy()
>>> editable_copy.learning_rate = 0.1  # Works fine

to_dict

to_dict() -> Dict[str, Any]

Converts the configuration to a dictionary.

Returns:

Type Description
Dict[str, Any]

Dictionary containing all configuration field names and their

Dict[str, Any]

current values.

Examples:

>>> config = MyConfig(learning_rate=0.001, epochs=100)
>>> config_dict = config.to_dict()
>>> print(config_dict)
{'learning_rate': 0.001, 'epochs': 100, ...}

to_file

to_file(save_file: str)

Saves the configuration to a file.

The file format is determined by the file extension. Supports JSON, YAML, and TOML.

Parameters:

Name Type Description Default
save_file str

Path where the configuration should be saved.

required

Examples:

>>> config.to_file("saved_config.yaml")
>>> config.to_file("backup_config.json")

validate

validate() -> Self

Validates all configuration fields against their constraints.

Performs comprehensive validation of all fields, checking both required field constraints and custom field constraints. Then runs cross-field constraints if all field constraints pass.

Returns:

Type Description
Self

Self for method chaining.

Raises:

Type Description
ValueError

If any required field is None.

ConstraintError

If any field value fails its constraint validation or if a cross-field constraint is violated.

Examples:

>>> config = MyConfig()
>>> config.learning_rate = -0.1  # Invalid if constraint requires positive
>>> config.validate()  # Raises ConstraintError

get_field_info

get_field_info(field_name: str) -> Dict[str, Any]

Retrieves comprehensive information about a configuration field.

Parameters:

Name Type Description Default
field_name str

Name of the field to get information about.

required

Returns:

Type Description
Dict[str, Any]

Dictionary containing field metadata including name, default value,

Dict[str, Any]

current value, constraints, documentation, and requirements.

Raises:

Type Description
ValueError

If the field name is not found in the configuration.

Examples:

>>> info = config.get_field_info("learning_rate")
>>> print(info["doc"])
Learning rate for model training
>>> print(info["constraint"])
RangeConstraint

get_schema classmethod

get_schema() -> Dict[str, Any]

Retrieves the schema information for all fields in the configuration class.

Returns:

Type Description
Dict[str, Any]

Dictionary mapping field names to their metadata, including defaults,

Dict[str, Any]

constraints, documentation, and requirement status.

Examples:

>>> schema = MyConfig.get_schema()
>>> for field_name, field_info in schema.items():
...     print(f"{field_name}: {field_info['doc']}")

ConfigField

ConfigField(default: Any = None, constraint: Constraint = NoConstraint(), preprocessor: Callable[[Any], Any] = lambda x: x, doc: str = '', required: bool = False)

Descriptor for configuration fields with validation and preprocessing.

This descriptor provides declarative field definitions with explicit constraint validation, preprocessing, and documentation support.

Attributes:

Name Type Description
default Any

The default value for the field.

constraint Constraint

Constraint object for validation, or None for no validation.

preprocessor Callable[[Any], Any]

Optional callable to transform values before validation.

doc str

Documentation string describing the field's purpose.

required bool

Whether the field must have a non-None value.

name str

The attribute name (set automatically by set_name).

Initializes a ConfigField with validation and processing options.

Parameters:

Name Type Description Default
default Any

The default value for this field. Used when the field is not explicitly set.

None
constraint Constraint

Constraint for validation. Defaults to NoConstraint() (no validation); pass an explicit constraint to validate this field.

NoConstraint()
preprocessor Callable[[Any], Any]

Optional callable that transforms the value before validation. Useful for path normalization, string conversion, etc.

lambda x: x
doc str

Documentation string describing the field's purpose and usage.

''
required bool

If True, the field must be set to a non-None value. Required fields will raise ValueError if left as None.

False

ConfigContainer

ConfigContainer(configs: Optional[Dict[str, Union[Config, ConfigContainer]]] = None)

Bases: MutableMapping

Advanced configuration container supporting nesting, composition, and type safety.

This container provides hierarchical organization of configuration objects with support for arbitrary nesting levels, type-safe access, and dynamic composition. It implements the MutableMapping protocol for dictionary-like operations while providing additional features for configuration management.

Features: - Support for arbitrary levels of configuration nesting - Type-safe configuration access with generic type hints - Chainable operations for fluent API design - Dynamic configuration composition and merging - Namespace isolation for large applications - Nested path access with dot notation - Comprehensive validation across all contained configurations - Type-annotated field declarations with IDE auto-completion - Auto-instantiation of Config fields from type annotations

Attributes:

Name Type Description
_configs Dict[str, Union[Config, ConfigContainer]]

Internal dictionary storing configuration objects.

_frozen bool

Boolean indicating whether the container is frozen.

_namespace str

Optional namespace string for organization.

_container_fields Dict[str, Dict[str, Any]]

Metadata about type-annotated fields (class attribute).

Examples:

>>> # Traditional dict-based initialization (backward compatible)
>>> container = ConfigContainer({
...     "database": DatabaseConfig(),
...     "api": ApiConfig()
... })
>>> # New type-annotated subclass (IDE auto-completion)
>>> class MyAppContainer(ConfigContainer):
...     database: DatabaseConfig
...     api: ApiConfig = lambda: ApiConfig(port=8080)
...
>>> container = MyAppContainer()
>>> container.database  # ← IDE knows type and provides auto-completion
>>> # Load from file and access nested configurations
>>> container.from_file("config.yaml")
>>> db_config = container.get_config("database", DatabaseConfig)
>>> learning_rate = container.get_nested("ml.training.learning_rate")

Initializes a configuration container with optional initial configurations.

Supports both dict-based initialization (backward compatible) and auto-instantiation of type-annotated fields from the class definition.

Parameters:

Name Type Description Default
configs Optional[Dict[str, Union[Config, ConfigContainer]]]

Optional dictionary mapping names to Config or ConfigContainer objects. If None, auto-instantiates fields from type annotations.

None

Examples:

>>> # Dict-based (backward compatible)
>>> container = ConfigContainer({"db": DatabaseConfig()})
>>> # Auto-instantiation from annotations
>>> class MyContainer(ConfigContainer):
...     database: DatabaseConfig
>>> container = MyContainer()  # database auto-created

add_cross_constraint

add_cross_constraint(constraint: CrossConstraint) -> None

Add a cross-constraint to this container instance.

Parameters:

Name Type Description Default
constraint CrossConstraint

CrossConstraint to add.

required

remove_cross_constraint

remove_cross_constraint(name: str) -> bool

Remove the first cross-constraint matching name.

Parameters:

Name Type Description Default
name str

Name of the constraint to remove.

required

Returns:

Type Description
bool

True if a constraint was found and removed, False otherwise.

add_config

add_config(name: str, config: Union[Config, ConfigContainer]) -> Self

Adds a configuration to the container (chainable).

Parameters:

Name Type Description Default
name str

Name to associate with the configuration.

required
config Union[Config, ConfigContainer]

Configuration object to add.

required

Returns:

Type Description
Self

Self for method chaining.

Examples:

>>> container.add_config("database", DatabaseConfig())
>>>          .add_config("api", ApiConfig())

add_configs

add_configs(**configs: Union[Config, ConfigContainer]) -> Self

Adds multiple configurations at once (chainable).

Parameters:

Name Type Description Default
**configs Union[Config, ConfigContainer]

Configuration objects as keyword arguments.

{}

Returns:

Type Description
Self

Self for method chaining.

remove_config

remove_config(name: str) -> Self

Removes a configuration from the container (chainable).

Parameters:

Name Type Description Default
name str

Name of the configuration to remove.

required

Returns:

Type Description
Self

Self for method chaining.

Raises:

Type Description
KeyError

If the configuration name is not found.

get_config

get_config(name: str, config_type: Type[T] = None) -> T

Retrieves a configuration with optional type checking.

Provides type-safe access to configurations with runtime type validation.

Parameters:

Name Type Description Default
name str

Name of the configuration to retrieve.

required
config_type Type[T]

Expected type of the configuration for type safety.

None

Returns:

Type Description
T

The configuration object, cast to the specified type if provided.

Raises:

Type Description
KeyError

If the configuration name is not found.

TypeError

If config_type is specified and the configuration doesn't match.

has_config

has_config(name: str, config_type: Type[T] = None) -> bool

Checks if a configuration exists and optionally matches a type.

Parameters:

Name Type Description Default
name str

Name of the configuration to check.

required
config_type Type[T]

Optional type to check against.

None

Returns:

Type Description
bool

True if the configuration exists (and matches the type if specified).

get_nested

get_nested(path: str, separator: str = '.') -> Union[Config, ConfigContainer, Any]

Retrieves a value from nested configurations using dot notation. Supports accessing deeply nested configuration values using a simple path string with configurable separator.

Parameters:

Name Type Description Default
path str

Dot-separated path to the desired value (e.g., "ml.model.hidden_size").

required
separator str

String used to separate path components.

'.'

Returns:

Type Description
Union[Config, ConfigContainer, Any]

The value at the specified path, which could be a Config, ConfigContainer,

Union[Config, ConfigContainer, Any]

or any configuration field value.

Raises:

Type Description
ValueError

If the path contains invalid segments.

KeyError

If any segment in the path is not found.

AttributeError

If trying to access a field that doesn't exist.

set_nested

set_nested(path: str, value: Any, separator: str = '.') -> ConfigContainer

Sets a value in nested configurations using dot notation (chainable).

Parameters:

Name Type Description Default
path str

Dot-separated path to the value to set.

required
value Any

Value to assign at the specified path.

required
separator str

String used to separate path components.

'.'

Returns:

Type Description
ConfigContainer

Self for method chaining.

Raises:

Type Description
ValueError

If the path contains invalid segments.

KeyError

If any segment in the path is not found.

has_nested

has_nested(path: str, separator: str = '.') -> bool

Checks if a nested path exists in the configuration hierarchy.

Parameters:

Name Type Description Default
path str

Dot-separated path to check.

required
separator str

String used to separate path components.

'.'

Returns:

Type Description
bool

True if the path exists, False otherwise.

from_file

from_file(config_file: str, namespace: str = '') -> Self

Loads configurations from a file with optional namespace support (chainable).

Parameters:

Name Type Description Default
config_file str

Path to the configuration file.

required
namespace str

Optional namespace prefix for configuration keys.

''

Returns:

Type Description
Self

Self for method chaining.

from_dict

from_dict(config_dict: Dict[str, Any]) -> Self

Loads configurations from a dictionary (chainable).

Parameters:

Name Type Description Default
config_dict Dict[str, Any]

Dictionary containing configuration data.

required

Returns:

Type Description
Self

Self for method chaining.

from_args

from_args(args: Union[Namespace, ArgumentParser], prefix: str = '') -> Self

Loads configurations from command line arguments (chainable).

Uses prefixed argument names to route values to the appropriate configurations.

Parameters:

Name Type Description Default
args Union[Namespace, ArgumentParser]

ArgumentParser or Namespace containing command line arguments.

required
prefix str

Prefix for filtering relevant arguments.

''

Returns:

Type Description
Self

Self for method chaining.

from_env

from_env(prefix: str = '') -> ConfigContainer

Loads configurations from environment variables (chainable).

Parameters:

Name Type Description Default
prefix str

Prefix for environment variable names.

''

Returns:

Type Description
ConfigContainer

Self for method chaining.

Examples:

>>> # Environment: APP_DB_HOST=localhost, APP_API_PORT=8080
>>> container.from_env("APP_")

merge

merge(other: ConfigContainer, strategy: str = 'override') -> ConfigContainer

Merges another configuration container with conflict resolution strategies.

Parameters:

Name Type Description Default
other ConfigContainer

Another ConfigContainer to merge.

required
strategy str

Merge strategy - "override", "skip", or "error". - "override": Replace duplicate configurations - "skip": Keep existing configurations, ignore duplicates - "error": Raise error on duplicate configuration names

'override'

Returns:

Type Description
ConfigContainer

New ConfigContainer containing merged configurations.

Raises:

Type Description
TypeError

If other is not a ConfigContainer.

ValueError

If strategy is "error" and duplicate names are found, or if strategy is not recognized.

Examples:

>>> base_config = ConfigContainer({"db": DatabaseConfig()})
>>> override_config = ConfigContainer({"api": ApiConfig()})
>>> merged = base_config.merge(override_config, strategy="override")

subset

subset(*config_names: str) -> ConfigContainer

Creates a new container with only the specified configurations.

Parameters:

Name Type Description Default
*config_names str

Names of configurations to include in the subset.

()

Returns:

Type Description
ConfigContainer

New ConfigContainer containing only the specified configurations.

Raises:

Type Description
KeyError

If any specified configuration name is not found.

Examples:

>>> subset = container.subset("database", "api")
>>> # Contains only database and api configurations

filter_by_type

filter_by_type(config_type: Type) -> ConfigContainer

Creates a new container containing only configurations of the specified type.

Parameters:

Name Type Description Default
config_type Type

Type to filter by.

required

Returns:

Type Description
ConfigContainer

New ConfigContainer containing only configurations of the specified type.

Examples:

>>> model_configs = container.filter_by_type(ModelConfig)
>>> # Contains only ModelConfig instances

freeze

freeze() -> ConfigContainer

Freezes the container and all contained configurations (chainable).

Returns:

Type Description
ConfigContainer

Self for method chaining.

Examples:

>>> container.from_file("config.yaml").freeze()
>>> # Container and all configs are now immutable

copy

copy(deep: bool = True) -> ConfigContainer

Creates a copy of the configuration container.

Parameters:

Name Type Description Default
deep bool

If True, performs deep copying of all contained configurations. If False, performs shallow copying (references to same config objects).

True

Returns:

Type Description
ConfigContainer

New ConfigContainer with copied configurations.

Examples:

>>> # Deep copy for independent modifications
>>> independent_copy = container.copy(deep=True)
>>>
>>> # Shallow copy for shared configurations
>>> shared_copy = container.copy(deep=False)

validate

validate() -> ConfigContainer

Validates all configurations in the container (chainable).

Recursively validates child configs first. If all pass, runs container-level cross-constraints (class + instance).

Returns:

Type Description
ConfigContainer

Self for method chaining.

Raises:

Type Description
ValueError

If any child configuration fails validation.

ConstraintError

If a container-level cross-constraint is violated.

Examples:

>>> container.from_file("config.yaml").validate().freeze()

to_dict

to_dict(flatten: bool = False, separator: str = '.') -> Dict[str, Any]

Converts the container to a dictionary representation.

Parameters:

Name Type Description Default
flatten bool

If True, flattens nested structures using dot notation.

False
separator str

Separator to use for flattened keys.

'.'

Returns:

Type Description
Dict[str, Any]

Dictionary representation of all configurations.

Examples:

>>> # Nested structure
>>> nested_dict = container.to_dict(flatten=False)
>>> print(nested_dict["ml"]["model"]["hidden_size"])
>>> # Flattened structure
>>> flat_dict = container.to_dict(flatten=True)
>>> print(flat_dict["ml.model.hidden_size"])

get_summary

get_summary() -> Dict[str, Any]

Generates a comprehensive summary of the container contents.

Returns:

Type Description
Dict[str, Any]

Dictionary containing statistics about configurations, types,

Dict[str, Any]

nesting levels, and total field counts.

Examples:

>>> summary = container.get_summary()
>>> print(f"Total configs: {summary['total_configs']}")
>>> print(f"Config types: {summary['config_types']}")

to_file

to_file(save_file: str)

Saves all configurations to a file.

Parameters:

Name Type Description Default
save_file str

Path where the configuration file should be saved.

required

Examples:

>>> container.to_file("full_config.yaml")

keys

keys()

Returns an iterator over configuration names.

values

values()

Returns an iterator over configuration objects.

items

items()

Returns an iterator over (name, config) pairs.

约束

A comprehensive constraint validation module for data validation and type checking.

This module provides a flexible framework for defining and applying validation constraints to data fields. It includes various built-in constraint types such as type checking, range validation, choice validation, and custom lambda constraints. Constraints can be combined using logical operations (AND, OR) and can be made optional or inverted.

Typical usage example:

# Create individual constraints
int_constraint = TypeConstraint(int)
range_constraint = RangeConstraint(0, 100)

# Combine constraints
combined = int_constraint & range_constraint

# Validate values
try:
    combined.check("score", 85)  # Valid
    combined.check("score", 150)  # Raises ConstraintError
except ConstraintError as e:
    print(e.message)

BaseConstraint

Bases: ABC

Marker ABC shared by Constraint and CrossConstraint.

NOT a polymorphic interface — callers must know which branch they hold. Provides: (1) structural guarantee via @abstractmethod, (2) isinstance type marker, (3) shared repr fallback.

Constraint

Bases: BaseConstraint

Abstract base class for single-field constraint types.

This class defines the interface that all single-field constraints must implement, including validation logic and error message generation. It also provides operator overloading for combining constraints using logical AND (&) and OR (|).

Examples:

>>> class CustomConstraint(Constraint):
...     def validate(self, value):
...         return isinstance(value, str) and len(value) > 0
...     def get_error_message(self, field_name, value):
...         return f"Field '{field_name}' must be a non-empty string"

validate abstractmethod

validate(value: Any) -> bool

Validates whether a value satisfies this constraint.

Parameters:

Name Type Description Default
value Any

The value to validate against this constraint.

required

Returns:

Type Description
bool

True if the value satisfies the constraint, False otherwise.

get_error_message abstractmethod

get_error_message(field_name: str, value: Any) -> str

Generates an error message for constraint validation failures.

Parameters:

Name Type Description Default
field_name str

The name of the field being validated.

required
value Any

The value that failed validation.

required

Returns:

Type Description
str

A descriptive error message explaining why validation failed.

check

check(field_name: str, value: Any) -> None

Validates a value and raises ConstraintError if validation fails.

This method performs validation and handles any exceptions that occur during the validation process, ensuring consistent error reporting.

Parameters:

Name Type Description Default
field_name str

The name of the field being validated.

required
value Any

The value to validate.

required

Raises:

Type Description
ConstraintError

If the value fails validation or if an unexpected error occurs during validation.

Examples:

>>> constraint = TypeConstraint(int)
>>> constraint.check("age", 25)  # No exception
>>> constraint.check("age", "25")  # Raises ConstraintError

TypeConstraint

TypeConstraint(expected_type: Type)

Bases: Constraint

Constraint that validates values against a specific type.

This constraint ensures that values are instances of the specified type. It uses isinstance() for type checking, which supports inheritance.

Attributes:

Name Type Description
expected_type

The type that values must be instances of.

Initializes a TypeConstraint with the expected type.

Parameters:

Name Type Description Default
expected_type Type

The type that values must be instances of.

required

validate

validate(value: Any) -> bool

Validates that the value is an instance of the expected type.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value is an instance of expected_type, False otherwise.

RangeConstraint

RangeConstraint(min_val: Union[int, float, None], max_val: Union[int, float, None])

Bases: Constraint

Constraint that validates numeric values within a specified range.

This constraint ensures that numeric values fall within the specified closed interval [min_val, max_val]. Either boundary can be None to create open-ended ranges.

Attributes:

Name Type Description
min_val

The minimum allowed value (inclusive), or None for no lower bound.

max_val

The maximum allowed value (inclusive), or None for no upper bound.

Initializes a RangeConstraint with the specified bounds.

Parameters:

Name Type Description Default
min_val Union[int, float, None]

The minimum allowed value (inclusive), or None for no lower bound.

required
max_val Union[int, float, None]

The maximum allowed value (inclusive), or None for no upper bound.

required

validate

validate(value: Any) -> bool

Validates that the value falls within the specified range.

Parameters:

Name Type Description Default
value Any

The numeric value to validate.

required

Returns:

Type Description
bool

True if the value is within the range, False otherwise.

bool

Returns False if both min_val and max_val are None.

ChoiceConstraint

ChoiceConstraint(choices: List[Any])

Bases: Constraint

Constraint that validates values against a list of allowed choices.

This constraint ensures that values are members of a predefined set of allowed values. It uses the 'in' operator for membership testing.

Attributes:

Name Type Description
choices

A list of allowed values.

Initializes a ChoiceConstraint with the allowed choices.

Parameters:

Name Type Description Default
choices List[Any]

A list of values that are considered valid.

required

validate

validate(value: Any) -> bool

Validates that the value is one of the allowed choices.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value is in the choices list, False otherwise.

ChoicesConstraint

ChoicesConstraint(choices: List[Any])

Bases: Constraint

Constraint that validates every element of a list/tuple against allowed choices.

The list-analogue of ChoiceConstraint: membership is tested element-wise. Empty sequences are accepted (no element violates the constraint).

Attributes:

Name Type Description
choices

A list of values that every element must be drawn from.

EqualityConstraint

EqualityConstraint(expected_value: Any)

Bases: Constraint

Constraint that validates values for equality with a specific value.

This constraint ensures that values are exactly equal to a predetermined expected value using the == operator.

Attributes:

Name Type Description
expected_value

The exact value that inputs must equal.

Initializes an EqualityConstraint with the expected value.

Parameters:

Name Type Description Default
expected_value Any

The exact value that inputs must equal.

required

validate

validate(value: Any) -> bool

Validates that the value equals the expected value.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value equals the expected value, False otherwise.

LengthConstraint

LengthConstraint(min_length: Optional[int], max_length: Optional[int])

Bases: Constraint

Constraint that validates the length of sequences or collections.

Validates that len(value) falls within the closed interval [min_length, max_length]. Either bound can be None for an open-ended range. Signature mirrors RangeConstraint so both follow the same min/max convention — use LengthConstraint(N, N) for an exact-length check.

Attributes:

Name Type Description
min_length

Minimum allowed length (inclusive), or None for no lower bound.

max_length

Maximum allowed length (inclusive), or None for no upper bound.

Initializes a LengthConstraint with the specified length bounds.

Parameters:

Name Type Description Default
min_length Optional[int]

Minimum allowed length (inclusive), or None for no lower bound.

required
max_length Optional[int]

Maximum allowed length (inclusive), or None for no upper bound.

required

validate

validate(value: Any) -> bool

Validates that len(value) falls within the configured bounds.

Parameters:

Name Type Description Default
value Any

The object to validate (must support len()).

required

Returns:

Type Description
bool

True if the length is within the range, False otherwise.

bool

Returns False if both bounds are None.

Raises:

Type Description
TypeError

If the value doesn't support len() (handled by check()).

LambdaConstraint

LambdaConstraint(func: Callable[[Any], bool], error_message: Union[str, Callable[[str, Any], str], None] = None)

Bases: Constraint

Constraint that uses a custom function for validation logic.

This constraint allows for arbitrary validation logic by accepting a callable that takes a value and returns a boolean. It also supports custom error message generation.

Attributes:

Name Type Description
func

A callable that takes a value and returns True if valid.

error_message

Either a static string or a callable that generates error messages.

Initializes a LambdaConstraint with validation function and error message.

Parameters:

Name Type Description Default
func Callable[[Any], bool]

A callable that takes a value and returns True if the value is valid, False otherwise.

required
error_message Union[str, Callable[[str, Any], str], None]

Either a static error message string, a callable that takes (field_name, value) and returns a string, or None to use a default message.

None

validate

validate(value: Any) -> bool

Validates the value using the provided function.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

The result of calling self.func(value).

get_error_message

get_error_message(field_name: str, value: Any) -> str

Generates an error message for validation failures.

Parameters:

Name Type Description Default
field_name str

The name of the field being validated.

required
value Any

The value that failed validation.

required

Returns:

Type Description
str

An error message based on the configured error_message attribute.

NoneConstraint

Bases: Constraint

Constraint that validates values to ensure they are None.

This constraint only accepts None values and rejects all other values. It's useful for fields that must be explicitly unset or null.

validate

validate(value: Any) -> bool

Validates that the value is None.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value is None, False otherwise.

NoConstraint

Bases: Constraint

Constraint that accepts any value without validation.

This constraint always returns True for any input value. It's useful as a placeholder or default constraint when no validation is needed.

validate

validate(value: Any) -> bool

Accepts any value without validation.

Parameters:

Name Type Description Default
value Any

The value to validate (ignored).

required

Returns:

Type Description
bool

Always returns True.

OptionalConstraint

OptionalConstraint(constraint: Constraint)

Bases: Constraint

Constraint wrapper that makes another constraint optional.

This constraint accepts None values or values that satisfy the wrapped constraint. It's useful for making fields optional while still applying validation when values are provided.

Attributes:

Name Type Description
constraint

The wrapped constraint to apply to non-None values.

Examples:

>>> # Optional integer constraint
>>> optional_int = OptionalConstraint(TypeConstraint(int))
>>> optional_int.validate(None)  # True
>>> optional_int.validate(42)  # True
>>> optional_int.validate("42")  # False
>>> # Optional range constraint
>>> optional_range = OptionalConstraint(RangeConstraint(0, 100))
>>> optional_range.validate(None)  # True
>>> optional_range.validate(50)  # True
>>> optional_range.validate(150)  # False

Initializes an OptionalConstraint with a wrapped constraint.

Parameters:

Name Type Description Default
constraint Constraint

The constraint to apply to non-None values.

required

validate

validate(value: Any) -> bool

Validates that the value is None or satisfies the wrapped constraint.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value is None or satisfies the wrapped constraint,

bool

False otherwise.

InverseConstraint

InverseConstraint(constraint: Constraint)

Bases: Constraint

Constraint wrapper that inverts another constraint's validation logic.

This constraint accepts values that do NOT satisfy the wrapped constraint. It's useful for excluding certain values or types.

Attributes:

Name Type Description
constraint

The wrapped constraint whose logic will be inverted.

Examples:

>>> # Not a string constraint
>>> not_string = InverseConstraint(TypeConstraint(str))
>>> not_string.validate(42)  # True
>>> not_string.validate("hello")  # False
>>> # Not in range constraint
>>> not_in_range = InverseConstraint(RangeConstraint(0, 10))
>>> not_in_range.validate(15)  # True
>>> not_in_range.validate(5)  # False

Initializes an InverseConstraint with a wrapped constraint.

Parameters:

Name Type Description Default
constraint Constraint

The constraint whose validation logic will be inverted.

required

validate

validate(value: Any) -> bool

Validates that the value does NOT satisfy the wrapped constraint.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value does NOT satisfy the wrapped constraint,

bool

False otherwise.

IntersectionConstraints

IntersectionConstraints(*constraints: Constraint)

Bases: Constraint

Constraint that requires ALL of multiple constraints to be satisfied.

This constraint implements logical AND operation across multiple constraints. A value is valid only if it satisfies every single constraint in the collection.

Attributes:

Name Type Description
constraints

A tuple of constraints that must all be satisfied.

Examples:

>>> # Must be int AND in range [0, 100]
>>> int_and_range = IntersectionConstraints(
...     TypeConstraint(int),
...     RangeConstraint(0, 100)
... )
>>> int_and_range.validate(50)  # True
>>> int_and_range.validate(150)  # False (out of range)
>>> int_and_range.validate("50")  # False (wrong type)
>>> # Can also be created using & operator
>>> same_constraint = TypeConstraint(int) & RangeConstraint(0, 100)

Initializes an IntersectionConstraints with multiple constraints.

Parameters:

Name Type Description Default
*constraints Constraint

Variable number of constraints that must all be satisfied.

()

validate

validate(value: Any) -> bool

Validates that the value satisfies ALL constraints.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value satisfies all constraints, False if any

bool

constraint is not satisfied.

UnionConstraints

UnionConstraints(*constraints: Constraint)

Bases: Constraint

Constraint that requires ANY of multiple constraints to be satisfied.

This constraint implements logical OR operation across multiple constraints. A value is valid if it satisfies at least one constraint in the collection.

Attributes:

Name Type Description
constraints

A tuple of constraints where at least one must be satisfied.

Examples:

>>> # Must be string OR int
>>> string_or_int = UnionConstraints(
...     TypeConstraint(str),
...     TypeConstraint(int)
... )
>>> string_or_int.validate("hello")  # True
>>> string_or_int.validate(42)  # True
>>> string_or_int.validate([1, 2, 3])  # False
>>> # Can also be created using | operator
>>> same_constraint = TypeConstraint(str) | TypeConstraint(int)

Initializes a UnionConstraints with multiple constraints.

Parameters:

Name Type Description Default
*constraints Constraint

Variable number of constraints where at least one must be satisfied.

()

validate

validate(value: Any) -> bool

Validates that the value satisfies at least one constraint.

Parameters:

Name Type Description Default
value Any

The value to validate.

required

Returns:

Type Description
bool

True if the value satisfies at least one constraint,

bool

False if no constraints are satisfied.

CrossConstraint

Bases: BaseConstraint

Abstract base class for cross-field constraint types.

Validates invariants that span multiple fields on a Config or ConfigContainer instance. Sibling of Constraint — NOT a subclass.

Subclasses must implement validate(), get_error_message(), and provide a name property used in error messages and for dynamic removal.

name abstractmethod property

name: str

Unique name for this cross-constraint (used in error messages).

validate abstractmethod

validate(config) -> bool

Return True if the cross-field invariant holds on config.

get_error_message abstractmethod

get_error_message(config) -> str

Return a human-readable error message when validation fails.

check

check(config) -> None

Validate and raise ConstraintError on failure.

Mirrors the error-handling pattern of Constraint.check(): - validate() returning False → ConstraintError with error message - unexpected exception → ConstraintError wrapping the original

LambdaCrossConstraint

LambdaCrossConstraint(func: Callable, error: str, name: str = '')

Bases: CrossConstraint

General-purpose cross-constraint using a callable predicate.

MutualExclusionConstraint

MutualExclusionConstraint(*fields: str, name: str = '')

Bases: CrossConstraint

Asserts that at most one of the named fields is non-None.

MethodCrossConstraint

MethodCrossConstraint(func: Callable, error: str, name: str)

Bases: CrossConstraint

Wraps an unbound function from a class body (produced by @cross_validate).

Structurally similar to LambdaCrossConstraint, but kept as a separate class to distinguish decorator-originated constraints from user-defined lambdas in isinstance checks, repr output, and debugging.

CrossIntersectionConstraints

CrossIntersectionConstraints(*constraints: CrossConstraint)

Bases: CrossConstraint

All wrapped CrossConstraints must pass (logical AND).

check

check(config) -> None

Single-pass check: evaluate each sub-constraint once.

CrossUnionConstraints

CrossUnionConstraints(*constraints: CrossConstraint)

Bases: CrossConstraint

At least one wrapped CrossConstraint must pass (logical OR).

ConstraintError

ConstraintError(message: str)

Bases: Exception

Exception raised when constraint validation fails.

This exception is raised by constraints when validation fails or when unexpected errors occur during the validation process.

Attributes:

Name Type Description
message

A descriptive error message explaining the validation failure.

Examples:

>>> try:
...     constraint.check("field", invalid_value)
... except ConstraintError as e:
...     print(f"Validation failed: {e.message}")

Initializes a ConstraintError with the given message.

Parameters:

Name Type Description Default
message str

A descriptive error message explaining the validation failure.

required

cross_validate

cross_validate(error=None, name=None)

Mark a method as a cross-field validator.

The method should accept self (the Config/ConfigContainer) and return True when the invariant holds. The metaclass wraps it into a MethodCrossConstraint at class-creation time.