Source code for r2x_core.utils.parser
"""Parser utils."""
from typing import Any, TypeVar
from infrasys import Component
from pydantic import ValidationError as PydanticValidationError
from rust_ok import Err, Ok, Result
T = TypeVar("T", bound=Component)
[docs]
def create_component(
component_class: type[T],
*,
skip_none: bool = True,
skip_validation: bool = False,
**field_values: Any,
) -> Result[T, PydanticValidationError]:
"""Create and validate a component instance with optional validation skipping.
This utility function returns a Result to allow recovery from validation errors
(e.g., skipping invalid components, logging warnings, etc.).
Parameters
----------
component_class : type[T]
The component class to instantiate.
skip_none : bool, default True
Whether to skip fields with None values when creating the component.
skip_validation : bool, default False
Skip Pydantic validation when creating components (faster but less safe).
**field_values : Any
Field values to pass to the component constructor.
Returns
-------
Result[T, PydanticValidationError]
``Ok(component)`` if validation succeeds, or ``Err(validation_error)``
if validation fails. Returns the specific component type T.
Examples
--------
>>> from infrasys import Generator
>>> result = create_component(Generator, name="Gen1", capacity=100.0)
>>> if result.is_ok():
... gen = result.value
... print(gen.name)
>>> else:
... print(f"Error: {result.error}")
"""
valid_fields = {
k: v
for k, v in field_values.items()
if k in component_class.model_fields and (v is not None or not skip_none)
}
try:
# Both paths return the same type T - either via model_construct or model_validate
# model_construct bypasses __init__ and all validators for 2-3x speedup
# on large batch component creation.
if skip_validation:
component = component_class.model_construct(**valid_fields)
else:
component = component_class.model_validate(valid_fields)
return Ok(component)
except PydanticValidationError as e:
return Err(e)