Coverage for src / lexigram / admin / lib / transformation.py: 37%
27 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
1"""Data transformation utilities for the admin layer."""
3from __future__ import annotations
5from typing import TYPE_CHECKING, Any
7if TYPE_CHECKING:
8 from collections.abc import Callable
11class DataTransformer:
12 """Handles data preparation between storage and UI layers.
14 This is used to format raw database/API data for form display
15 and to process form submissions back into a serializable format.
16 """
18 def __init__(self) -> None:
19 """Initialize with empty transform maps."""
20 self._to_form: dict[str, Callable] = {}
21 self._from_form: dict[str, Callable] = {}
23 def register(self, field_name: str, to_form: Callable, from_form: Callable) -> None:
24 """Register transform functions for a specific field."""
25 self._to_form[field_name] = to_form
26 self._from_form[field_name] = from_form
28 def transform_to_form(self, data: dict[str, Any]) -> dict[str, Any]:
29 """Apply all 'to_form' transformations to a data dictionary."""
30 result = dict(data)
31 for field, transformer in self._to_form.items():
32 if field in result:
33 result[field] = transformer(result[field])
34 return result
36 def transform_from_form(self, data: dict[str, Any]) -> dict[str, Any]:
37 """Apply all 'from_form' transformations to a data dictionary."""
38 result = dict(data)
39 for field, transformer in self._from_form.items():
40 if field in result:
41 result[field] = transformer(result[field])
42 return result
45# Standard Transformers
48def json_transformer() -> Any:
49 """Transformer for JSON string <-> Object."""
50 from lexigram.serialization import dumps_str, loads_str
52 return (
53 lambda x: loads_str(x) if isinstance(x, str) else x,
54 lambda x: dumps_str(x) if not isinstance(x, str) else x,
55 )
58def comma_separated_list() -> Any:
59 """Transformer for CSV String <-> List."""
60 return (
61 lambda x: [s.strip() for s in x.split(",")] if isinstance(x, str) else x,
62 lambda x: ", ".join(x) if isinstance(x, list) else x,
63 )
66__all__ = ["DataTransformer", "comma_separated_list", "json_transformer"]