quantum-framework 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/commands/__init__.py +15 -0
  4. quantum/cli/commands/build.py +417 -0
  5. quantum/cli/commands/dev.py +185 -0
  6. quantum/cli/commands/docs.py +329 -0
  7. quantum/cli/commands/lint.py +523 -0
  8. quantum/cli/commands/migrate.py +527 -0
  9. quantum/cli/commands/new.py +622 -0
  10. quantum/cli/commands/serve.py +190 -0
  11. quantum/cli/commands/test.py +193 -0
  12. quantum/cli/deploy.py +810 -0
  13. quantum/cli/hot_reload.py +951 -0
  14. quantum/cli/jobs.py +356 -0
  15. quantum/cli/mq.py +582 -0
  16. quantum/cli/pkg.py +390 -0
  17. quantum/cli/runner.py +547 -0
  18. quantum/cli/server_process.py +159 -0
  19. quantum/cli/utils.py +334 -0
  20. quantum/compiler/__init__.py +30 -0
  21. quantum/compiler/base_generator.py +367 -0
  22. quantum/compiler/cli.py +295 -0
  23. quantum/compiler/expression_transformer.py +444 -0
  24. quantum/compiler/javascript/__init__.py +10 -0
  25. quantum/compiler/javascript/generator.py +659 -0
  26. quantum/compiler/optimizer.py +270 -0
  27. quantum/compiler/python/__init__.py +10 -0
  28. quantum/compiler/python/generator.py +883 -0
  29. quantum/compiler/python/runtime.py +863 -0
  30. quantum/compiler/transpiler.py +330 -0
  31. quantum/core/__init__.py +3 -0
  32. quantum/core/ast_nodes.py +2611 -0
  33. quantum/core/expression_diagnostics.py +87 -0
  34. quantum/core/expression_stdlib.py +148 -0
  35. quantum/core/expressions.py +591 -0
  36. quantum/core/features/agents/src/__init__.py +30 -0
  37. quantum/core/features/agents/src/ast_node.py +540 -0
  38. quantum/core/features/conditionals/src/__init__.py +8 -0
  39. quantum/core/features/conditionals/src/ast_node.py +68 -0
  40. quantum/core/features/data_fetching/src/__init__.py +21 -0
  41. quantum/core/features/data_fetching/src/ast_node.py +312 -0
  42. quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
  43. quantum/core/features/data_fetching/src/html_adapter.py +474 -0
  44. quantum/core/features/data_fetching/src/parser.py +225 -0
  45. quantum/core/features/data_import/src/__init__.py +0 -0
  46. quantum/core/features/data_import/src/ast_node.py +291 -0
  47. quantum/core/features/data_import/src/runtime.py +538 -0
  48. quantum/core/features/dump/src/__init__.py +12 -0
  49. quantum/core/features/dump/src/ast_node.py +106 -0
  50. quantum/core/features/dump/src/parser.py +61 -0
  51. quantum/core/features/dump/src/runtime.py +246 -0
  52. quantum/core/features/functions/src/__init__.py +8 -0
  53. quantum/core/features/functions/src/ast_node.py +149 -0
  54. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  55. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  56. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  57. quantum/core/features/invocation/src/__init__.py +0 -0
  58. quantum/core/features/invocation/src/ast_node.py +146 -0
  59. quantum/core/features/invocation/src/runtime.py +327 -0
  60. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  61. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  62. quantum/core/features/knowledge_base/src/parser.py +82 -0
  63. quantum/core/features/logging/src/__init__.py +12 -0
  64. quantum/core/features/logging/src/ast_node.py +111 -0
  65. quantum/core/features/logging/src/parser.py +50 -0
  66. quantum/core/features/logging/src/runtime.py +190 -0
  67. quantum/core/features/loops/src/__init__.py +8 -0
  68. quantum/core/features/loops/src/ast_node.py +60 -0
  69. quantum/core/features/query/src/__init__.py +0 -0
  70. quantum/core/features/query/src/database_service.py +322 -0
  71. quantum/core/features/query/src/query_validators.py +20 -0
  72. quantum/core/features/state_management/src/__init__.py +11 -0
  73. quantum/core/features/state_management/src/ast_node.py +228 -0
  74. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  75. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  76. quantum/core/features/terminal_engine/src/parser.py +361 -0
  77. quantum/core/features/testing_engine/src/__init__.py +41 -0
  78. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  79. quantum/core/features/testing_engine/src/parser.py +604 -0
  80. quantum/core/features/theming/src/__init__.py +48 -0
  81. quantum/core/features/theming/src/ast_node.py +137 -0
  82. quantum/core/features/theming/src/presets.py +405 -0
  83. quantum/core/features/ui_engine/src/__init__.py +20 -0
  84. quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
  85. quantum/core/features/ui_engine/src/parser.py +1106 -0
  86. quantum/core/features/websocket/src/__init__.py +24 -0
  87. quantum/core/features/websocket/src/ast_node.py +247 -0
  88. quantum/core/html_compat.py +299 -0
  89. quantum/core/parser.py +1235 -0
  90. quantum/core/parser_registry.py +213 -0
  91. quantum/core/parsers/__init__.py +76 -0
  92. quantum/core/parsers/ai/__init__.py +12 -0
  93. quantum/core/parsers/ai/agent_parser.py +106 -0
  94. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  95. quantum/core/parsers/ai/llm_parser.py +78 -0
  96. quantum/core/parsers/ai/team_parser.py +88 -0
  97. quantum/core/parsers/base.py +322 -0
  98. quantum/core/parsers/composition/__init__.py +10 -0
  99. quantum/core/parsers/composition/import_parser.py +50 -0
  100. quantum/core/parsers/composition/slot_parser.py +48 -0
  101. quantum/core/parsers/control_flow/__init__.py +11 -0
  102. quantum/core/parsers/control_flow/if_parser.py +68 -0
  103. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  104. quantum/core/parsers/control_flow/set_parser.py +89 -0
  105. quantum/core/parsers/data/__init__.py +12 -0
  106. quantum/core/parsers/data/data_parser.py +217 -0
  107. quantum/core/parsers/data/invoke_parser.py +116 -0
  108. quantum/core/parsers/data/query_parser.py +188 -0
  109. quantum/core/parsers/data/transaction_parser.py +77 -0
  110. quantum/core/parsers/events/__init__.py +9 -0
  111. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  112. quantum/core/parsers/forms/__init__.py +11 -0
  113. quantum/core/parsers/forms/action_parser.py +54 -0
  114. quantum/core/parsers/forms/flash_parser.py +34 -0
  115. quantum/core/parsers/forms/redirect_parser.py +33 -0
  116. quantum/core/parsers/functions/__init__.py +11 -0
  117. quantum/core/parsers/functions/function_parser.py +137 -0
  118. quantum/core/parsers/functions/param_parser.py +66 -0
  119. quantum/core/parsers/functions/return_parser.py +31 -0
  120. quantum/core/parsers/html/__init__.py +10 -0
  121. quantum/core/parsers/html/component_call_parser.py +130 -0
  122. quantum/core/parsers/html/html_parser.py +115 -0
  123. quantum/core/parsers/jobs/__init__.py +11 -0
  124. quantum/core/parsers/jobs/job_parser.py +71 -0
  125. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  126. quantum/core/parsers/jobs/thread_parser.py +57 -0
  127. quantum/core/parsers/messaging/__init__.py +17 -0
  128. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  130. quantum/core/parsers/messaging/message_parser.py +114 -0
  131. quantum/core/parsers/messaging/queue_parser.py +61 -0
  132. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  133. quantum/core/parsers/persistence/__init__.py +9 -0
  134. quantum/core/parsers/persistence/persist_parser.py +64 -0
  135. quantum/core/parsers/routing/__init__.py +9 -0
  136. quantum/core/parsers/routing/route_parser.py +41 -0
  137. quantum/core/parsers/scripting/__init__.py +12 -0
  138. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  139. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  140. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  141. quantum/core/parsers/scripting/python_parser.py +49 -0
  142. quantum/core/parsers/services/__init__.py +12 -0
  143. quantum/core/parsers/services/dump_parser.py +52 -0
  144. quantum/core/parsers/services/file_parser.py +48 -0
  145. quantum/core/parsers/services/log_parser.py +46 -0
  146. quantum/core/parsers/services/mail_parser.py +65 -0
  147. quantum/core/tiers.py +82 -0
  148. quantum/packages/__init__.py +28 -0
  149. quantum/packages/manager.py +413 -0
  150. quantum/packages/manifest.py +351 -0
  151. quantum/packages/registry.py +399 -0
  152. quantum/packages/resolver.py +336 -0
  153. quantum/plugins/__init__.py +33 -0
  154. quantum/plugins/hooks.py +329 -0
  155. quantum/plugins/loader.py +479 -0
  156. quantum/plugins/manifest.py +336 -0
  157. quantum/plugins/registry.py +371 -0
  158. quantum/runtime/__init__.py +28 -0
  159. quantum/runtime/action_handler.py +443 -0
  160. quantum/runtime/adapters/__init__.py +88 -0
  161. quantum/runtime/adapters/memory_adapter.py +690 -0
  162. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  163. quantum/runtime/adapters/redis_adapter.py +582 -0
  164. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  165. quantum/runtime/agent_service.py +1133 -0
  166. quantum/runtime/api_server.py +86 -0
  167. quantum/runtime/ast_cache.py +506 -0
  168. quantum/runtime/auth_service.py +267 -0
  169. quantum/runtime/component.py +990 -0
  170. quantum/runtime/component_composer.py +319 -0
  171. quantum/runtime/component_resolver.py +174 -0
  172. quantum/runtime/database_service.py +598 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +286 -0
  176. quantum/runtime/executor_registry.py +171 -0
  177. quantum/runtime/executors/__init__.py +71 -0
  178. quantum/runtime/executors/ai/__init__.py +12 -0
  179. quantum/runtime/executors/ai/agent_executor.py +217 -0
  180. quantum/runtime/executors/ai/knowledge_executor.py +114 -0
  181. quantum/runtime/executors/ai/llm_executor.py +153 -0
  182. quantum/runtime/executors/ai/team_executor.py +171 -0
  183. quantum/runtime/executors/base.py +262 -0
  184. quantum/runtime/executors/control_flow/__init__.py +11 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +93 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +307 -0
  187. quantum/runtime/executors/control_flow/set_executor.py +412 -0
  188. quantum/runtime/executors/data/__init__.py +12 -0
  189. quantum/runtime/executors/data/data_executor.py +145 -0
  190. quantum/runtime/executors/data/invoke_executor.py +176 -0
  191. quantum/runtime/executors/data/query_executor.py +256 -0
  192. quantum/runtime/executors/data/transaction_executor.py +91 -0
  193. quantum/runtime/executors/jobs/__init__.py +11 -0
  194. quantum/runtime/executors/jobs/job_executor.py +190 -0
  195. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  196. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  197. quantum/runtime/executors/messaging/__init__.py +17 -0
  198. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  199. quantum/runtime/executors/messaging/message_executor.py +174 -0
  200. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  201. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  202. quantum/runtime/executors/scripting/__init__.py +11 -0
  203. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  204. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  205. quantum/runtime/executors/scripting/python_executor.py +249 -0
  206. quantum/runtime/executors/services/__init__.py +12 -0
  207. quantum/runtime/executors/services/dump_executor.py +72 -0
  208. quantum/runtime/executors/services/file_executor.py +89 -0
  209. quantum/runtime/executors/services/log_executor.py +77 -0
  210. quantum/runtime/executors/services/mail_executor.py +81 -0
  211. quantum/runtime/expression_cache.py +498 -0
  212. quantum/runtime/file_upload_service.py +326 -0
  213. quantum/runtime/function_registry.py +118 -0
  214. quantum/runtime/game_builder.py +166 -0
  215. quantum/runtime/game_code_generator.py +2371 -0
  216. quantum/runtime/game_templates.py +2006 -0
  217. quantum/runtime/godot_code_generator.py +4681 -0
  218. quantum/runtime/godot_templates.py +1449 -0
  219. quantum/runtime/job_executor.py +1599 -0
  220. quantum/runtime/knowledge_service.py +500 -0
  221. quantum/runtime/llm_cache.py +100 -0
  222. quantum/runtime/llm_providers.py +704 -0
  223. quantum/runtime/llm_service.py +287 -0
  224. quantum/runtime/logging_setup.py +140 -0
  225. quantum/runtime/message_broker.py +364 -0
  226. quantum/runtime/message_queue_service.py +571 -0
  227. quantum/runtime/param_validation.py +184 -0
  228. quantum/runtime/pypy_compat.py +315 -0
  229. quantum/runtime/python_bridge.py +698 -0
  230. quantum/runtime/query_validators.py +304 -0
  231. quantum/runtime/renderer.py +733 -0
  232. quantum/runtime/service_container.py +444 -0
  233. quantum/runtime/terminal_builder.py +76 -0
  234. quantum/runtime/terminal_code_generator.py +607 -0
  235. quantum/runtime/terminal_templates.py +243 -0
  236. quantum/runtime/testing_builder.py +77 -0
  237. quantum/runtime/testing_code_generator.py +833 -0
  238. quantum/runtime/testing_templates.py +85 -0
  239. quantum/runtime/ui_builder.py +188 -0
  240. quantum/runtime/ui_desktop_adapter.py +1730 -0
  241. quantum/runtime/ui_desktop_templates.py +307 -0
  242. quantum/runtime/ui_html_adapter.py +2691 -0
  243. quantum/runtime/ui_html_templates.py +2297 -0
  244. quantum/runtime/ui_mobile_adapter.py +1832 -0
  245. quantum/runtime/ui_mobile_templates.py +1003 -0
  246. quantum/runtime/ui_textual_adapter.py +1866 -0
  247. quantum/runtime/ui_textual_templates.py +45 -0
  248. quantum/runtime/ui_tokens.py +465 -0
  249. quantum/runtime/ui_validator.py +365 -0
  250. quantum/runtime/validators.py +256 -0
  251. quantum/runtime/web_server.py +1766 -0
  252. quantum/runtime/websocket_adapter.py +501 -0
  253. quantum/runtime/websocket_service.py +585 -0
  254. quantum/runtime/websocket_transport.py +289 -0
  255. quantum/runtime/wsgi.py +101 -0
  256. quantum/utils/__init__.py +1 -0
  257. quantum_framework-0.9.0.dist-info/METADATA +244 -0
  258. quantum_framework-0.9.0.dist-info/RECORD +262 -0
  259. quantum_framework-0.9.0.dist-info/WHEEL +5 -0
  260. quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
  261. quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
  262. quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,361 @@
1
+ """
2
+ Terminal Engine Parser - Parse qt: namespace elements into Terminal AST nodes.
3
+
4
+ This module provides parse functions for all terminal-specific tags.
5
+ It is called from the main QuantumParser when a qt: prefixed tag is encountered.
6
+ """
7
+
8
+ from xml.etree import ElementTree as ET
9
+ from typing import Optional, List
10
+
11
+ from .ast_nodes import (
12
+ ScreenNode, PanelNode, LayoutNode, TableNode, ColumnNode,
13
+ TerminalInputNode, ButtonNode, MenuNode, OptionNode,
14
+ TextNode_Terminal, ProgressNode, TreeNode, TabsNode, TabNode,
15
+ LogNode_Terminal, HeaderNode_Terminal, FooterNode, StatusNode,
16
+ KeybindingNode, TimerNode_Terminal, ServiceNode, CssNode,
17
+ OnEventNode_Terminal, RawCodeNode_Terminal,
18
+ )
19
+
20
+
21
+ class TerminalParseError(Exception):
22
+ """Terminal-specific parse error."""
23
+ pass
24
+
25
+
26
+ class TerminalParser:
27
+ """Parser for qt: namespace terminal elements."""
28
+
29
+ def __init__(self, parent_parser):
30
+ """
31
+ Args:
32
+ parent_parser: The main QuantumParser instance, used to parse
33
+ q: namespace children (q:set, q:function, q:if, etc.)
34
+ """
35
+ self.parent = parent_parser
36
+
37
+ # ------------------------------------------------------------------
38
+ # Dispatch
39
+ # ------------------------------------------------------------------
40
+
41
+ TERMINAL_TAG_MAP = {
42
+ 'screen': '_parse_terminal_screen',
43
+ 'panel': '_parse_terminal_panel',
44
+ 'layout': '_parse_terminal_layout',
45
+ 'table': '_parse_terminal_table',
46
+ 'column': '_parse_terminal_column',
47
+ 'input': '_parse_terminal_input',
48
+ 'button': '_parse_terminal_button',
49
+ 'menu': '_parse_terminal_menu',
50
+ 'option': '_parse_terminal_option',
51
+ 'text': '_parse_terminal_text',
52
+ 'progress': '_parse_terminal_progress',
53
+ 'tree': '_parse_terminal_tree',
54
+ 'tabs': '_parse_terminal_tabs',
55
+ 'tab': '_parse_terminal_tab',
56
+ 'log': '_parse_terminal_log',
57
+ 'header': '_parse_terminal_header',
58
+ 'footer': '_parse_terminal_footer',
59
+ 'status': '_parse_terminal_status',
60
+ 'keybinding': '_parse_terminal_keybinding',
61
+ 'timer': '_parse_terminal_timer',
62
+ 'service': '_parse_terminal_service',
63
+ 'css': '_parse_terminal_css',
64
+ 'on': '_parse_terminal_on',
65
+ }
66
+
67
+ def parse_terminal_element(self, local_name: str, element: ET.Element):
68
+ """Dispatch a qt: element to the correct parse method."""
69
+ method_name = self.TERMINAL_TAG_MAP.get(local_name)
70
+ if method_name is None:
71
+ raise TerminalParseError(f"Unknown terminal tag: qt:{local_name}")
72
+ method = getattr(self, method_name)
73
+ return method(element)
74
+
75
+ # ------------------------------------------------------------------
76
+ # Helper: get local name from element
77
+ # ------------------------------------------------------------------
78
+
79
+ def _get_local_name(self, element: ET.Element) -> str:
80
+ tag = element.tag
81
+ if '}' in tag:
82
+ return tag.split('}')[-1]
83
+ if ':' in tag:
84
+ return tag.split(':')[-1]
85
+ return tag
86
+
87
+ def _get_namespace(self, element: ET.Element) -> Optional[str]:
88
+ tag = element.tag
89
+ if '{https://quantum.lang/terminal}' in tag:
90
+ return 'terminal'
91
+ if '{https://quantum.lang/ns}' in tag:
92
+ return 'quantum'
93
+ if tag.startswith('qt:'):
94
+ return 'terminal'
95
+ if tag.startswith('q:'):
96
+ return 'quantum'
97
+ return None
98
+
99
+ def _parse_float(self, value: Optional[str], default: float = 0) -> float:
100
+ if value is None:
101
+ return default
102
+ try:
103
+ return float(value)
104
+ except ValueError:
105
+ return default
106
+
107
+ def _parse_int(self, value: Optional[str], default: int = 0) -> int:
108
+ if value is None:
109
+ return default
110
+ try:
111
+ return int(value)
112
+ except ValueError:
113
+ return default
114
+
115
+ def _parse_bool(self, value: Optional[str], default: bool = False) -> bool:
116
+ if value is None:
117
+ return default
118
+ return value.lower() in ('true', '1', 'yes')
119
+
120
+ # ------------------------------------------------------------------
121
+ # Parse children - dispatches both qt: and q: tags
122
+ # ------------------------------------------------------------------
123
+
124
+ def _parse_child(self, child: ET.Element):
125
+ """Parse a child element that can be either qt: or q: namespace."""
126
+ ns = self._get_namespace(child)
127
+ local = self._get_local_name(child)
128
+
129
+ if ns == 'terminal':
130
+ return self.parse_terminal_element(local, child)
131
+ elif ns == 'quantum':
132
+ if local == 'function':
133
+ return self._parse_terminal_function(child)
134
+ return self.parent._parse_statement(child)
135
+ return None
136
+
137
+ def _parse_terminal_function(self, element: ET.Element):
138
+ """Parse q:function with mixed raw Python code and XML statement children.
139
+
140
+ Captures element.text and child.tail as RawCodeNode_Terminal, alongside
141
+ regular q:set / q:if / etc children parsed normally.
142
+ """
143
+ func_node = self.parent._parse_function(element)
144
+
145
+ mixed_body = []
146
+
147
+ # Leading text before first child
148
+ if element.text and element.text.strip():
149
+ for line in element.text.strip().splitlines():
150
+ line = line.strip()
151
+ if line:
152
+ mixed_body.append(RawCodeNode_Terminal(line))
153
+
154
+ # Process children: XML elements + their tail text
155
+ for child in element:
156
+ parsed = self._parse_child(child)
157
+ if parsed:
158
+ mixed_body.append(parsed)
159
+ if child.tail and child.tail.strip():
160
+ for line in child.tail.strip().splitlines():
161
+ line = line.strip()
162
+ if line:
163
+ mixed_body.append(RawCodeNode_Terminal(line))
164
+
165
+ # Only replace body if we found raw code nodes
166
+ has_raw = any(isinstance(n, RawCodeNode_Terminal) for n in mixed_body)
167
+ if has_raw:
168
+ func_node.body = mixed_body
169
+
170
+ return func_node
171
+
172
+ # ------------------------------------------------------------------
173
+ # Core terminal nodes
174
+ # ------------------------------------------------------------------
175
+
176
+ def _parse_terminal_screen(self, element: ET.Element) -> ScreenNode:
177
+ name = element.get('name', 'main')
178
+ node = ScreenNode(name)
179
+ node.title = element.get('title')
180
+
181
+ for child in element:
182
+ parsed = self._parse_child(child)
183
+ if parsed:
184
+ node.add_child(parsed)
185
+ return node
186
+
187
+ def _parse_terminal_panel(self, element: ET.Element) -> PanelNode:
188
+ node = PanelNode()
189
+ node.panel_id = element.get('id')
190
+ node.title = element.get('title')
191
+
192
+ for child in element:
193
+ parsed = self._parse_child(child)
194
+ if parsed:
195
+ node.add_child(parsed)
196
+ return node
197
+
198
+ def _parse_terminal_layout(self, element: ET.Element) -> LayoutNode:
199
+ node = LayoutNode()
200
+ node.layout_id = element.get('id')
201
+ node.direction = element.get('direction', 'vertical')
202
+
203
+ for child in element:
204
+ parsed = self._parse_child(child)
205
+ if parsed:
206
+ node.add_child(parsed)
207
+ return node
208
+
209
+ def _parse_terminal_table(self, element: ET.Element) -> TableNode:
210
+ node = TableNode()
211
+ node.table_id = element.get('id')
212
+ node.data_source = element.get('data-source')
213
+ node.zebra = self._parse_bool(element.get('zebra'))
214
+
215
+ for child in element:
216
+ local = self._get_local_name(child)
217
+ ns = self._get_namespace(child)
218
+ if ns == 'terminal' and local == 'column':
219
+ col = self._parse_terminal_column(child)
220
+ node.add_column(col)
221
+ return node
222
+
223
+ def _parse_terminal_column(self, element: ET.Element) -> ColumnNode:
224
+ node = ColumnNode()
225
+ node.name = element.get('name', '')
226
+ node.key = element.get('key', '')
227
+ node.width = self._parse_int(element.get('width')) if element.get('width') else None
228
+ node.align = element.get('align', 'left')
229
+ return node
230
+
231
+ def _parse_terminal_input(self, element: ET.Element) -> TerminalInputNode:
232
+ node = TerminalInputNode()
233
+ node.input_id = element.get('id')
234
+ node.placeholder = element.get('placeholder')
235
+ node.on_submit = element.get('on-submit')
236
+ node.password = self._parse_bool(element.get('password'))
237
+ return node
238
+
239
+ def _parse_terminal_button(self, element: ET.Element) -> ButtonNode:
240
+ node = ButtonNode()
241
+ node.button_id = element.get('id')
242
+ node.label = element.get('label', '')
243
+ node.variant = element.get('variant', 'default')
244
+ node.on_click = element.get('on-click')
245
+ return node
246
+
247
+ def _parse_terminal_menu(self, element: ET.Element) -> MenuNode:
248
+ node = MenuNode()
249
+ node.menu_id = element.get('id')
250
+ node.on_select = element.get('on-select')
251
+
252
+ for child in element:
253
+ local = self._get_local_name(child)
254
+ ns = self._get_namespace(child)
255
+ if ns == 'terminal' and local == 'option':
256
+ opt = self._parse_terminal_option(child)
257
+ node.add_option(opt)
258
+ return node
259
+
260
+ def _parse_terminal_option(self, element: ET.Element) -> OptionNode:
261
+ node = OptionNode()
262
+ node.value = element.get('value', '')
263
+ node.label = element.get('label', '') or (element.text or '').strip()
264
+ return node
265
+
266
+ def _parse_terminal_text(self, element: ET.Element) -> TextNode_Terminal:
267
+ node = TextNode_Terminal()
268
+ node.text_id = element.get('id')
269
+ node.content = (element.text or '').strip()
270
+ return node
271
+
272
+ def _parse_terminal_progress(self, element: ET.Element) -> ProgressNode:
273
+ node = ProgressNode()
274
+ node.progress_id = element.get('id')
275
+ node.total = self._parse_float(element.get('total'), 100)
276
+ node.value_var = element.get('value-var')
277
+ return node
278
+
279
+ def _parse_terminal_tree(self, element: ET.Element) -> TreeNode:
280
+ node = TreeNode()
281
+ node.tree_id = element.get('id')
282
+ node.label = element.get('label', '')
283
+ node.on_select = element.get('on-select')
284
+ return node
285
+
286
+ def _parse_terminal_tabs(self, element: ET.Element) -> TabsNode:
287
+ node = TabsNode()
288
+ node.tabs_id = element.get('id')
289
+
290
+ for child in element:
291
+ local = self._get_local_name(child)
292
+ ns = self._get_namespace(child)
293
+ if ns == 'terminal' and local == 'tab':
294
+ tab = self._parse_terminal_tab(child)
295
+ node.add_tab(tab)
296
+ return node
297
+
298
+ def _parse_terminal_tab(self, element: ET.Element) -> TabNode:
299
+ node = TabNode()
300
+ node.tab_id = element.get('id')
301
+ node.title = element.get('title', '')
302
+
303
+ for child in element:
304
+ parsed = self._parse_child(child)
305
+ if parsed:
306
+ node.add_child(parsed)
307
+ return node
308
+
309
+ def _parse_terminal_log(self, element: ET.Element) -> LogNode_Terminal:
310
+ node = LogNode_Terminal()
311
+ node.log_id = element.get('id')
312
+ node.auto_scroll = self._parse_bool(element.get('auto-scroll'), True)
313
+ node.markup = self._parse_bool(element.get('markup'), True)
314
+ node.max_lines = self._parse_int(element.get('max-lines')) if element.get('max-lines') else None
315
+ return node
316
+
317
+ def _parse_terminal_header(self, element: ET.Element) -> HeaderNode_Terminal:
318
+ node = HeaderNode_Terminal()
319
+ node.title = element.get('title')
320
+ node.show_clock = self._parse_bool(element.get('show-clock'))
321
+ return node
322
+
323
+ def _parse_terminal_footer(self, element: ET.Element) -> FooterNode:
324
+ return FooterNode()
325
+
326
+ def _parse_terminal_status(self, element: ET.Element) -> StatusNode:
327
+ node = StatusNode()
328
+ node.status_id = element.get('id')
329
+ node.content = (element.text or '').strip()
330
+ return node
331
+
332
+ def _parse_terminal_keybinding(self, element: ET.Element) -> KeybindingNode:
333
+ node = KeybindingNode()
334
+ node.key = element.get('key', '')
335
+ node.action = element.get('action', '')
336
+ node.description = element.get('description')
337
+ return node
338
+
339
+ def _parse_terminal_timer(self, element: ET.Element) -> TimerNode_Terminal:
340
+ node = TimerNode_Terminal()
341
+ node.timer_id = element.get('id')
342
+ node.interval = self._parse_float(element.get('interval'), 1.0)
343
+ node.action = element.get('action', '')
344
+ return node
345
+
346
+ def _parse_terminal_service(self, element: ET.Element) -> ServiceNode:
347
+ node = ServiceNode()
348
+ node.service_id = element.get('id')
349
+ node.handler = element.get('handler', '')
350
+ return node
351
+
352
+ def _parse_terminal_css(self, element: ET.Element) -> CssNode:
353
+ node = CssNode()
354
+ node.content = (element.text or '').strip()
355
+ return node
356
+
357
+ def _parse_terminal_on(self, element: ET.Element) -> OnEventNode_Terminal:
358
+ node = OnEventNode_Terminal()
359
+ node.event = element.get('event', '')
360
+ node.action = element.get('action', '')
361
+ return node
@@ -0,0 +1,41 @@
1
+ """
2
+ Testing Engine - AST nodes and parser for the qtest: namespace.
3
+ """
4
+
5
+ from .ast_nodes import (
6
+ # Core testing nodes
7
+ QTestSuiteNode, QTestCaseNode, ExpectNode, MockNode_Testing,
8
+ FixtureNode_Testing, SetupNode_Testing, TeardownNode_Testing,
9
+ BeforeEachNode, AfterEachNode, GenerateNode,
10
+ ScenarioNode, GivenNode, WhenNode, ThenNode,
11
+ # Browser testing nodes
12
+ BrowserConfigNode, NavigateNode, ClickNode, DblClickNode,
13
+ RightClickNode, HoverNode, FillNode, TypeNode_Testing,
14
+ SelectNode_Testing, CheckNode, UncheckNode, KeyboardNode,
15
+ DragNode, ScrollNode_Testing, UploadNode, DownloadNode,
16
+ WaitForNode, ScreenshotNode, InterceptNode, InterceptRespondNode,
17
+ FrameNode_Testing, PopupNode, AuthNode, SaveStateNode, PauseNode,
18
+ # Advanced testing nodes
19
+ SnapshotNode, FuzzNode, PropertyNode, FuzzFieldNode,
20
+ PerfNode, PerfMetricNode, A11yNode, ChaosNode, ChaosFailNode,
21
+ GeolocationNode,
22
+ )
23
+
24
+ __all__ = [
25
+ # Core testing nodes
26
+ 'QTestSuiteNode', 'QTestCaseNode', 'ExpectNode', 'MockNode_Testing',
27
+ 'FixtureNode_Testing', 'SetupNode_Testing', 'TeardownNode_Testing',
28
+ 'BeforeEachNode', 'AfterEachNode', 'GenerateNode',
29
+ 'ScenarioNode', 'GivenNode', 'WhenNode', 'ThenNode',
30
+ # Browser testing nodes
31
+ 'BrowserConfigNode', 'NavigateNode', 'ClickNode', 'DblClickNode',
32
+ 'RightClickNode', 'HoverNode', 'FillNode', 'TypeNode_Testing',
33
+ 'SelectNode_Testing', 'CheckNode', 'UncheckNode', 'KeyboardNode',
34
+ 'DragNode', 'ScrollNode_Testing', 'UploadNode', 'DownloadNode',
35
+ 'WaitForNode', 'ScreenshotNode', 'InterceptNode', 'InterceptRespondNode',
36
+ 'FrameNode_Testing', 'PopupNode', 'AuthNode', 'SaveStateNode', 'PauseNode',
37
+ # Advanced testing nodes
38
+ 'SnapshotNode', 'FuzzNode', 'PropertyNode', 'FuzzFieldNode',
39
+ 'PerfNode', 'PerfMetricNode', 'A11yNode', 'ChaosNode', 'ChaosFailNode',
40
+ 'GeolocationNode',
41
+ ]