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

1"""Data transformation utilities for the admin layer.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING, Any 

6 

7if TYPE_CHECKING: 

8 from collections.abc import Callable 

9 

10 

11class DataTransformer: 

12 """Handles data preparation between storage and UI layers. 

13 

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 """ 

17 

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] = {} 

22 

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 

27 

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 

35 

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 

43 

44 

45# Standard Transformers 

46 

47 

48def json_transformer() -> Any: 

49 """Transformer for JSON string <-> Object.""" 

50 from lexigram.serialization import dumps_str, loads_str 

51 

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 ) 

56 

57 

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 ) 

64 

65 

66__all__ = ["DataTransformer", "comma_separated_list", "json_transformer"]