Skip to content

Field Errors

field_errors

Base class for errors associated with a specific field.

Defines FieldErrors which represents validation or constraint errors
associated with a single field.

FieldErrors

Bases: Error[object]

Base class for errors associated with a specific field.

Example
class SomeError(Error[object]):
    pass


class FieldErrorAggregate(FieldErrors[SomeError]):
    pass


field_errors = FieldErrorAggregate(
    field=FieldReference("email"),
    errors=[
        SomeError.from_string("Format is invalid"),
        SomeError.from_string("Domain not allowed"),
    ],
)
assert field_errors.field.value == "email"
assert len(field_errors) == 2
for err in field_errors:
    assert "invalid" in str(err) or "not allowed" in str(err)
Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
class FieldErrors[ContainedErrorType: Error[object]](Error[object]):
    """Base class for errors associated with a specific field.

    Example:
        ```python
        class SomeError(Error[object]):
            pass


        class FieldErrorAggregate(FieldErrors[SomeError]):
            pass


        field_errors = FieldErrorAggregate(
            field=FieldReference("email"),
            errors=[
                SomeError.from_string("Format is invalid"),
                SomeError.from_string("Domain not allowed"),
            ],
        )
        assert field_errors.field.value == "email"
        assert len(field_errors) == 2
        for err in field_errors:
            assert "invalid" in str(err) or "not allowed" in str(err)
        ```

    """

    def __init__(self, field: FieldReference, errors: Iterable[ContainedErrorType]) -> None:
        """Initialise with a field reference and the errors associated with it.

        Args:
            field: Reference to the field these errors belong to.
            errors: The errors associated with *field*. Must be non-empty.

        Raises:
            RuleViolatedError: If *errors* is empty or *field* is falsy.
        """
        self._field = field
        self._errors: Sequence[ContainedErrorType] = tuple(errors)

        if not self._errors or not field or not field.value:
            raise RuleViolatedError(
                ErrorMessage("FieldErrors must contain at least one error and field defined.")
            )

        message = ErrorMessage(f"{len(self._errors)} error(s) for field '{field.value}'.")

        super().__init__(message=message)

    def __repr__(self) -> str:
        """Return a concise string representation of the field errors."""
        return (
            f"<{self._get_title_prefix()} field={self._field.value!r} errors={len(self._errors)}>"
        )

    def __str__(self) -> str:
        """Return a human-readable string representation of the field errors."""
        error_messages = "\n".join(f" - {str(error)}" for error in self._errors)
        return f"{self._get_title_prefix()} for field '{self._field.value}':\n{error_messages}"

    def __iter__(self) -> Iterator[ContainedErrorType]:
        """Iterate over the errors associated with the field."""
        return iter(self._errors)

    def __len__(self) -> int:
        """Return the number of errors associated with the field."""
        return len(self._errors)

    @property
    def field(self) -> FieldReference:
        """The field associated with these errors."""
        return self._field

    @property
    def errors(self) -> Sequence[ContainedErrorType]:
        """The collection of errors associated with the field."""
        return self._errors

    def as_debug_string(self) -> str:
        """Return detailed, multi-line string of this field error collection for debugging."""
        error_strings = [f"    {err.as_debug_string()}" for err in self._errors]
        return (
            f"{self._get_title_prefix()}(\n"
            f"  field={repr(self._field)},\n"
            f"  errors=[\n"
            + ("" if not error_strings else "\n".join(error_strings) + "\n")
            + "  ]\n"
            ")"
        )

    def _get_title_prefix(self) -> str:
        """Get the title prefix for this field error type."""
        return self.__class__.__name__

field: FieldReference property

The field associated with these errors.

errors: Sequence[ContainedErrorType] property

The collection of errors associated with the field.

__init__(field: FieldReference, errors: Iterable[ContainedErrorType]) -> None

Initialise with a field reference and the errors associated with it.

Parameters:

Name Type Description Default
field FieldReference

Reference to the field these errors belong to.

required
errors Iterable[ContainedErrorType]

The errors associated with field. Must be non-empty.

required

Raises:

Type Description
RuleViolatedError

If errors is empty or field is falsy.

Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
def __init__(self, field: FieldReference, errors: Iterable[ContainedErrorType]) -> None:
    """Initialise with a field reference and the errors associated with it.

    Args:
        field: Reference to the field these errors belong to.
        errors: The errors associated with *field*. Must be non-empty.

    Raises:
        RuleViolatedError: If *errors* is empty or *field* is falsy.
    """
    self._field = field
    self._errors: Sequence[ContainedErrorType] = tuple(errors)

    if not self._errors or not field or not field.value:
        raise RuleViolatedError(
            ErrorMessage("FieldErrors must contain at least one error and field defined.")
        )

    message = ErrorMessage(f"{len(self._errors)} error(s) for field '{field.value}'.")

    super().__init__(message=message)

__repr__() -> str

Return a concise string representation of the field errors.

Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
def __repr__(self) -> str:
    """Return a concise string representation of the field errors."""
    return (
        f"<{self._get_title_prefix()} field={self._field.value!r} errors={len(self._errors)}>"
    )

__str__() -> str

Return a human-readable string representation of the field errors.

Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
def __str__(self) -> str:
    """Return a human-readable string representation of the field errors."""
    error_messages = "\n".join(f" - {str(error)}" for error in self._errors)
    return f"{self._get_title_prefix()} for field '{self._field.value}':\n{error_messages}"

__iter__() -> Iterator[ContainedErrorType]

Iterate over the errors associated with the field.

Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
def __iter__(self) -> Iterator[ContainedErrorType]:
    """Iterate over the errors associated with the field."""
    return iter(self._errors)

__len__() -> int

Return the number of errors associated with the field.

Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
def __len__(self) -> int:
    """Return the number of errors associated with the field."""
    return len(self._errors)

as_debug_string() -> str

Return detailed, multi-line string of this field error collection for debugging.

Source code in src/forging_blocks/foundation/errors/combined/field_errors.py
def as_debug_string(self) -> str:
    """Return detailed, multi-line string of this field error collection for debugging."""
    error_strings = [f"    {err.as_debug_string()}" for err in self._errors]
    return (
        f"{self._get_title_prefix()}(\n"
        f"  field={repr(self._field)},\n"
        f"  errors=[\n"
        + ("" if not error_strings else "\n".join(error_strings) + "\n")
        + "  ]\n"
        ")"
    )