examples.29_records_validation

Validate a list of small records (dicts) where each field is checked using constrained value types such as RangeValue and EnumValue.

This example shows:
  • How to iterate over a list of input records and validate each field.
  • How to collect normalized/typed outputs for valid rows.
  • How to collect structured error information for invalid rows.
Run directly:

python examples/29_records_validation.py

Expected output:

OK: [{'id': 1, 'role': 'user'}, {'id': 2, 'role': 'admin'}] ERRS: [(1, "Value must be one of 'int', got 'str'", "Value must be one of ('user', 'admin'), got owner")]

  1"""Validate a list of small records (dicts) where each field is checked using
  2constrained value types such as :class:`RangeValue` and :class:`EnumValue`.
  3
  4This example shows:
  5  * How to iterate over a list of input records and validate each field.
  6  * How to collect normalized/typed outputs for valid rows.
  7  * How to collect structured error information for invalid rows.
  8
  9Run directly:
 10
 11    python examples/29_records_validation.py
 12
 13Expected output:
 14
 15    OK: [{'id': 1, 'role': 'user'}, {'id': 2, 'role': 'admin'}]
 16    ERRS: [(1, "Value must be one of 'int', got 'str'", "Value must be one of ('user', 'admin'), got owner")]
 17"""
 18
 19import sys
 20import pathlib
 21from enum import Enum
 22from typing import List, Dict, Any, Tuple
 23
 24# ---------------------------------------------------------------------------
 25# Make repo root importable when running this file directly
 26# ---------------------------------------------------------------------------
 27sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
 28
 29from constrained_values import RangeValue, EnumValue, Status
 30
 31
 32class Role(Enum):
 33    """Valid roles for records."""
 34    USER = "user"
 35    ADMIN = "admin"
 36
 37
 38def validate_records(rows: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Tuple[int, Any, Any]]]:
 39    """Validate a list of record dicts.
 40
 41    Each row is expected to contain:
 42      * ``id`` — an integer in the inclusive range ``[1, 10**9]``.
 43      * ``role`` — one of :class:`Role` (``"user"`` or ``"admin"``), accepted
 44        either as the enum member or its underlying string value.
 45
 46    For each row:
 47      * If both fields validate, a normalized dict ``{"id": int, "role": Role}``
 48        is appended to the OK list.
 49      * Otherwise, an error tuple ``(index, id_error, role_error)`` is appended
 50        to the error list. Missing errors are reported as ``None``.
 51
 52    Args:
 53        rows: Input records to validate.
 54
 55    Returns:
 56        Tuple[List[Dict[str, Any]], List[Tuple[int, Any, Any]]]:
 57            * First item — list of normalized, valid rows.
 58            * Second item — list of error tuples with the original row index and
 59              per-field error messages (or ``None`` if that field was OK).
 60    """
 61    out: List[Dict[str, Any]] = []
 62    errs: List[Tuple[int, Any, Any]] = []
 63
 64    for i, row in enumerate(rows):
 65        uid = RangeValue(row.get("id"), 1, 10 ** 9)
 66        role = EnumValue(row.get("role"), Role)
 67
 68        if uid.status == Status.OK and role.status == Status.OK:
 69            out.append({"id": uid.value, "role": role.value})
 70        else:
 71            errs.append(
 72                (
 73                    i,
 74                    uid.details if uid.status != Status.OK else None,
 75                    role.details if role.status != Status.OK else None,
 76                )
 77            )
 78
 79    return out, errs
 80
 81
 82def main() -> None:
 83    """Run the record list validation demonstration.
 84
 85    Creates a list with two valid rows and one invalid row, validates them,
 86    then prints the OK results and the collected error details.
 87
 88    Prints:
 89        * ``OK: [...]`` — normalized rows.
 90        * ``ERRS: [...]`` — list of (index, id_error, role_error).
 91    """
 92    rows = [
 93        {"id": 1, "role": "user"},
 94        {"id": "x", "role": "owner"},
 95        {"id": 2, "role": Role.ADMIN},
 96    ]
 97
 98    ok, bad = validate_records(rows)
 99    print("OK:", ok)
100    print("ERRS:", bad)
101
102
103if __name__ == "__main__":
104    main()
class Role(enum.Enum):
33class Role(Enum):
34    """Valid roles for records."""
35    USER = "user"
36    ADMIN = "admin"

Valid roles for records.

USER = <Role.USER: 'user'>
ADMIN = <Role.ADMIN: 'admin'>
Inherited Members
enum.Enum
name
value
def validate_records( rows: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Tuple[int, Any, Any]]]:
39def validate_records(rows: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Tuple[int, Any, Any]]]:
40    """Validate a list of record dicts.
41
42    Each row is expected to contain:
43      * ``id`` — an integer in the inclusive range ``[1, 10**9]``.
44      * ``role`` — one of :class:`Role` (``"user"`` or ``"admin"``), accepted
45        either as the enum member or its underlying string value.
46
47    For each row:
48      * If both fields validate, a normalized dict ``{"id": int, "role": Role}``
49        is appended to the OK list.
50      * Otherwise, an error tuple ``(index, id_error, role_error)`` is appended
51        to the error list. Missing errors are reported as ``None``.
52
53    Args:
54        rows: Input records to validate.
55
56    Returns:
57        Tuple[List[Dict[str, Any]], List[Tuple[int, Any, Any]]]:
58            * First item — list of normalized, valid rows.
59            * Second item — list of error tuples with the original row index and
60              per-field error messages (or ``None`` if that field was OK).
61    """
62    out: List[Dict[str, Any]] = []
63    errs: List[Tuple[int, Any, Any]] = []
64
65    for i, row in enumerate(rows):
66        uid = RangeValue(row.get("id"), 1, 10 ** 9)
67        role = EnumValue(row.get("role"), Role)
68
69        if uid.status == Status.OK and role.status == Status.OK:
70            out.append({"id": uid.value, "role": role.value})
71        else:
72            errs.append(
73                (
74                    i,
75                    uid.details if uid.status != Status.OK else None,
76                    role.details if role.status != Status.OK else None,
77                )
78            )
79
80    return out, errs

Validate a list of record dicts.

Each row is expected to contain:
  • id — an integer in the inclusive range [1, 10**9].
  • role — one of Role ("user" or "admin"), accepted either as the enum member or its underlying string value.
For each row:
  • If both fields validate, a normalized dict {"id": int, "role": Role} is appended to the OK list.
  • Otherwise, an error tuple (index, id_error, role_error) is appended to the error list. Missing errors are reported as None.
Arguments:
  • rows: Input records to validate.
Returns:

Tuple[List[Dict[str, Any]], List[Tuple[int, Any, Any]]]: * First item — list of normalized, valid rows. * Second item — list of error tuples with the original row index and per-field error messages (or None if that field was OK).

def main() -> None:
 83def main() -> None:
 84    """Run the record list validation demonstration.
 85
 86    Creates a list with two valid rows and one invalid row, validates them,
 87    then prints the OK results and the collected error details.
 88
 89    Prints:
 90        * ``OK: [...]`` — normalized rows.
 91        * ``ERRS: [...]`` — list of (index, id_error, role_error).
 92    """
 93    rows = [
 94        {"id": 1, "role": "user"},
 95        {"id": "x", "role": "owner"},
 96        {"id": 2, "role": Role.ADMIN},
 97    ]
 98
 99    ok, bad = validate_records(rows)
100    print("OK:", ok)
101    print("ERRS:", bad)

Run the record list validation demonstration.

Creates a list with two valid rows and one invalid row, validates them, then prints the OK results and the collected error details.

Prints:
  • OK: [...] — normalized rows.
  • ERRS: [...] — list of (index, id_error, role_error).