Coverage for src/lexigram/admin/resources/layouts.py: 0%

40 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-24 23:31 +0800

1"""Layout configurators for Admin Resources. 

2 

3Registry-style dispatch that applies a resource's layout configuration to a 

4:class:`~lexigram.admin.layout.layout_manager.LayoutManager`. One configurator 

5per :class:`~lexigram.admin.layout.LayoutType`; the registry selects by 

6``config.type`` and raises on unknown types so misconfiguration is explicit. 

7""" 

8 

9from __future__ import annotations 

10 

11from typing import TYPE_CHECKING, Any, Protocol 

12 

13if TYPE_CHECKING: 

14 from lexigram.admin.layout.layout_manager import LayoutManager 

15 

16 

17class LayoutConfiguratorProtocol(Protocol): 

18 """Protocol for layout configurators.""" 

19 

20 def can_configure(self, layout_type: Any) -> bool: ... 

21 

22 def configure_layout(self, manager: LayoutManager, config: Any) -> None: ... 

23 

24 

25class GridLayoutConfigurator: 

26 def can_configure(self, layout_type: Any) -> bool: 

27 from lexigram.admin.layout import LayoutType 

28 

29 return bool(layout_type == LayoutType.GRID) 

30 

31 def configure_layout(self, manager: LayoutManager, config: Any) -> None: 

32 manager.add_grid_layout( # type: ignore[attr-defined] 

33 columns=config.columns, 

34 card_template=config.card_template, 

35 enabled=config.enabled, 

36 ) 

37 

38 

39class CalendarLayoutConfigurator: 

40 def can_configure(self, layout_type: Any) -> bool: 

41 from lexigram.admin.layout import LayoutType 

42 

43 return bool(layout_type == LayoutType.CALENDAR) 

44 

45 def configure_layout(self, manager: LayoutManager, config: Any) -> None: 

46 manager.add_calendar_layout( # type: ignore[attr-defined] 

47 date_field=config.date_field, 

48 title_field=config.title_field, 

49 enabled=config.enabled, 

50 ) 

51 

52 

53class MapLayoutConfigurator: 

54 def can_configure(self, layout_type: Any) -> bool: 

55 from lexigram.admin.layout import LayoutType 

56 

57 return bool(layout_type == LayoutType.MAP) 

58 

59 def configure_layout(self, manager: LayoutManager, config: Any) -> None: 

60 manager.add_map_layout( # type: ignore[attr-defined] 

61 latitude_field=config.latitude_field, 

62 longitude_field=config.longitude_field, 

63 marker_template=config.marker_template, 

64 enabled=config.enabled, 

65 ) 

66 

67 

68class ListLayoutConfigurator: 

69 def can_configure(self, layout_type: Any) -> bool: 

70 from lexigram.admin.layout import LayoutType 

71 

72 return bool(layout_type == LayoutType.LIST) 

73 

74 def configure_layout(self, manager: LayoutManager, config: Any) -> None: 

75 manager.add_list_layout(enabled=config.enabled) # type: ignore[attr-defined] 

76 

77 

78class LayoutConfiguratorRegistry: 

79 """Registry that selects a configurator for a given layout type.""" 

80 

81 def __init__(self) -> None: 

82 self._configurators: list[LayoutConfiguratorProtocol] = [ 

83 GridLayoutConfigurator(), 

84 CalendarLayoutConfigurator(), 

85 MapLayoutConfigurator(), 

86 ListLayoutConfigurator(), 

87 ] 

88 

89 def configure(self, manager: LayoutManager, config: Any) -> None: 

90 for c in self._configurators: 

91 if c.can_configure(config.type): 

92 c.configure_layout(manager, config) 

93 return 

94 # Fallback: raise to make misconfiguration explicit 

95 raise ValueError(f"No configurator for layout type: {config.type}") 

96 

97 

98_layout_configurator_registry = LayoutConfiguratorRegistry() 

99 

100 

101def apply_layout_config(manager: LayoutManager, config: Any) -> None: 

102 """Apply layout configuration to *manager* using the configurator registry. 

103 

104 Args: 

105 manager: Layout manager receiving the configured layout. 

106 config: Layout configuration object with a ``type`` attribute. 

107 """ 

108 _layout_configurator_registry.configure(manager, config) 

109 

110 

111__all__ = [ 

112 "CalendarLayoutConfigurator", 

113 "GridLayoutConfigurator", 

114 "LayoutConfiguratorProtocol", 

115 "LayoutConfiguratorRegistry", 

116 "ListLayoutConfigurator", 

117 "MapLayoutConfigurator", 

118 "apply_layout_config", 

119]