Source code for loom.core.use_case.field_ref

from __future__ import annotations

from dataclasses import dataclass
from enum import StrEnum
from typing import Any

from loom.core.command.base import Command
from loom.core.model.base import BaseModel

FieldRoot = type[Command] | type[BaseModel] | str


[docs] class PredicateOp(StrEnum): OR = "or" AND = "and"
[docs] @dataclass(frozen=True, slots=True) class FieldRef: """Declarative reference to a field path on a command (or loaded alias).""" root: FieldRoot path: tuple[str, ...] def __getattr__(self, item: str) -> FieldRef: if item.startswith("_"): raise AttributeError(item) return FieldRef(root=self.root, path=(*self.path, item)) def __or__(self, other: FieldRef | FieldExpr) -> FieldExpr: return FieldExpr(PredicateOp.OR, self, other) def __and__(self, other: FieldRef | FieldExpr) -> FieldExpr: return FieldExpr(PredicateOp.AND, self, other) @property def leaf(self) -> str: leaf = next(reversed(self.path), None) if leaf is None: raise ValueError("FieldRef.path cannot be empty.") return leaf
[docs] @dataclass(frozen=True, slots=True) class FieldExpr: """Boolean expression over field references used by DSL predicates.""" op: PredicateOp left: FieldRef | FieldExpr right: FieldRef | FieldExpr def __or__(self, other: FieldRef | FieldExpr) -> FieldExpr: return FieldExpr(PredicateOp.OR, self, other) def __and__(self, other: FieldRef | FieldExpr) -> FieldExpr: return FieldExpr(PredicateOp.AND, self, other)
class _FieldRefFactory: __slots__ = ("_root",) def __init__(self, root: FieldRoot) -> None: self._root = root def __getattr__(self, item: str) -> FieldRef: if item.startswith("_"): raise AttributeError(item) return FieldRef(root=self._root, path=(item,))
[docs] def field_ref( root: FieldRoot, ) -> Any: """Build a typed field-reference factory. Example: ``F(UpdateUserCommand).birthdate`` """ return _FieldRefFactory(root)
# Public shorthand kept for DSL ergonomics: F(Model).field F = field_ref