Coverage for formkit_ninja / parser / node_registry.py: 86.36%

40 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-03-03 09:21 +0000

1""" 

2Registry for FormKit node classes. 

3 

4This module provides a registry that maps node identifiers (e.g., "$formkit" values) 

5to their corresponding Pydantic model classes. This enables centralized node type 

6resolution and makes it easier to extend the system with new node types. 

7""" 

8 

9from __future__ import annotations 

10 

11from typing import TYPE_CHECKING, Type 

12 

13if TYPE_CHECKING: 13 ↛ 14line 13 didn't jump to line 14 because the condition on line 13 was never true

14 from formkit_ninja.formkit_schema import FormKitType 

15 

16 

17class NodeRegistry: 

18 """ 

19 Registry for FormKit node classes. 

20 

21 Maps node type identifiers (e.g., "text", "group", "repeater") to their 

22 corresponding Pydantic model classes. This enables centralized node type 

23 resolution and makes it easier to extend the system with new node types. 

24 

25 Example: 

26 registry = NodeRegistry() 

27 registry.register_formkit_node("text", TextNode) 

28 node_class = registry.get_formkit_node_class("text") 

29 """ 

30 

31 def __init__(self) -> None: 

32 """Initialize an empty registry.""" 

33 self._formkit_nodes: dict[str, Type[FormKitType]] = {} 

34 

35 def register_formkit_node(self, node_type: str, node_class: Type[FormKitType]) -> None: 

36 """ 

37 Register a FormKit node class. 

38 

39 Args: 

40 node_type: The node type identifier (e.g., "text", "group", "repeater") 

41 node_class: The Pydantic model class for this node type 

42 

43 Raises: 

44 ValueError: If the node_type is already registered 

45 """ 

46 if node_type in self._formkit_nodes: 46 ↛ 47line 46 didn't jump to line 47 because the condition on line 46 was never true

47 raise ValueError(f"Node type '{node_type}' is already registered") 

48 self._formkit_nodes[node_type] = node_class 

49 

50 def get_formkit_node_class(self, node_type: str) -> Type[FormKitType] | None: 

51 """ 

52 Get the registered class for a FormKit node type. 

53 

54 Args: 

55 node_type: The node type identifier (e.g., "text", "group") 

56 

57 Returns: 

58 The registered Pydantic model class, or None if not found 

59 """ 

60 return self._formkit_nodes.get(node_type) 

61 

62 def list_formkit_nodes(self) -> list[str]: 

63 """ 

64 List all registered FormKit node types. 

65 

66 Returns: 

67 List of registered node type identifiers 

68 """ 

69 return list(self._formkit_nodes.keys()) 

70 

71 def is_registered(self, node_type: str) -> bool: 

72 """ 

73 Check if a node type is registered. 

74 

75 Args: 

76 node_type: The node type identifier to check 

77 

78 Returns: 

79 True if the node type is registered, False otherwise 

80 """ 

81 return node_type in self._formkit_nodes 

82 

83 

84def _create_default_registry() -> NodeRegistry: 

85 """ 

86 Create and populate the default registry with common FormKit node types. 

87 

88 This function is called once to initialize the default_registry singleton. 

89 It imports node classes lazily to avoid circular dependencies. 

90 

91 Returns: 

92 A NodeRegistry instance with common nodes pre-registered 

93 """ 

94 # Lazy import to avoid circular dependencies 

95 from formkit_ninja.formkit_schema import ( 

96 AutocompleteNode, 

97 CheckBoxNode, 

98 CurrencyNode, 

99 DateNode, 

100 DatePickerNode, 

101 DropDownNode, 

102 EmailNode, 

103 GroupNode, 

104 HiddenNode, 

105 NumberNode, 

106 PasswordNode, 

107 RadioNode, 

108 RepeaterNode, 

109 SelectNode, 

110 TelNode, 

111 TextAreaNode, 

112 TextNode, 

113 UuidNode, 

114 ) 

115 

116 registry = NodeRegistry() 

117 

118 # Register all common FormKit node types 

119 registry.register_formkit_node("text", TextNode) 

120 registry.register_formkit_node("textarea", TextAreaNode) 

121 registry.register_formkit_node("checkbox", CheckBoxNode) 

122 registry.register_formkit_node("password", PasswordNode) 

123 registry.register_formkit_node("select", SelectNode) 

124 registry.register_formkit_node("autocomplete", AutocompleteNode) 

125 registry.register_formkit_node("email", EmailNode) 

126 registry.register_formkit_node("number", NumberNode) 

127 registry.register_formkit_node("radio", RadioNode) 

128 registry.register_formkit_node("group", GroupNode) 

129 registry.register_formkit_node("date", DateNode) 

130 registry.register_formkit_node("datepicker", DatePickerNode) 

131 registry.register_formkit_node("dropdown", DropDownNode) 

132 registry.register_formkit_node("repeater", RepeaterNode) 

133 registry.register_formkit_node("tel", TelNode) 

134 registry.register_formkit_node("currency", CurrencyNode) 

135 registry.register_formkit_node("hidden", HiddenNode) 

136 registry.register_formkit_node("uuid", UuidNode) 

137 

138 return registry 

139 

140 

141# Singleton default registry instance 

142default_registry: NodeRegistry = _create_default_registry()