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.
- quantum/__init__.py +1 -0
- quantum/cli/__init__.py +2 -0
- quantum/cli/commands/__init__.py +15 -0
- quantum/cli/commands/build.py +417 -0
- quantum/cli/commands/dev.py +185 -0
- quantum/cli/commands/docs.py +329 -0
- quantum/cli/commands/lint.py +523 -0
- quantum/cli/commands/migrate.py +527 -0
- quantum/cli/commands/new.py +622 -0
- quantum/cli/commands/serve.py +190 -0
- quantum/cli/commands/test.py +193 -0
- quantum/cli/deploy.py +810 -0
- quantum/cli/hot_reload.py +951 -0
- quantum/cli/jobs.py +356 -0
- quantum/cli/mq.py +582 -0
- quantum/cli/pkg.py +390 -0
- quantum/cli/runner.py +547 -0
- quantum/cli/server_process.py +159 -0
- quantum/cli/utils.py +334 -0
- quantum/compiler/__init__.py +30 -0
- quantum/compiler/base_generator.py +367 -0
- quantum/compiler/cli.py +295 -0
- quantum/compiler/expression_transformer.py +444 -0
- quantum/compiler/javascript/__init__.py +10 -0
- quantum/compiler/javascript/generator.py +659 -0
- quantum/compiler/optimizer.py +270 -0
- quantum/compiler/python/__init__.py +10 -0
- quantum/compiler/python/generator.py +883 -0
- quantum/compiler/python/runtime.py +863 -0
- quantum/compiler/transpiler.py +330 -0
- quantum/core/__init__.py +3 -0
- quantum/core/ast_nodes.py +2611 -0
- quantum/core/expression_diagnostics.py +87 -0
- quantum/core/expression_stdlib.py +148 -0
- quantum/core/expressions.py +591 -0
- quantum/core/features/agents/src/__init__.py +30 -0
- quantum/core/features/agents/src/ast_node.py +540 -0
- quantum/core/features/conditionals/src/__init__.py +8 -0
- quantum/core/features/conditionals/src/ast_node.py +68 -0
- quantum/core/features/data_fetching/src/__init__.py +21 -0
- quantum/core/features/data_fetching/src/ast_node.py +312 -0
- quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
- quantum/core/features/data_fetching/src/html_adapter.py +474 -0
- quantum/core/features/data_fetching/src/parser.py +225 -0
- quantum/core/features/data_import/src/__init__.py +0 -0
- quantum/core/features/data_import/src/ast_node.py +291 -0
- quantum/core/features/data_import/src/runtime.py +538 -0
- quantum/core/features/dump/src/__init__.py +12 -0
- quantum/core/features/dump/src/ast_node.py +106 -0
- quantum/core/features/dump/src/parser.py +61 -0
- quantum/core/features/dump/src/runtime.py +246 -0
- quantum/core/features/functions/src/__init__.py +8 -0
- quantum/core/features/functions/src/ast_node.py +149 -0
- quantum/core/features/game_engine_2d/src/__init__.py +19 -0
- quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
- quantum/core/features/game_engine_2d/src/parser.py +983 -0
- quantum/core/features/invocation/src/__init__.py +0 -0
- quantum/core/features/invocation/src/ast_node.py +146 -0
- quantum/core/features/invocation/src/runtime.py +327 -0
- quantum/core/features/knowledge_base/src/__init__.py +6 -0
- quantum/core/features/knowledge_base/src/ast_node.py +113 -0
- quantum/core/features/knowledge_base/src/parser.py +82 -0
- quantum/core/features/logging/src/__init__.py +12 -0
- quantum/core/features/logging/src/ast_node.py +111 -0
- quantum/core/features/logging/src/parser.py +50 -0
- quantum/core/features/logging/src/runtime.py +190 -0
- quantum/core/features/loops/src/__init__.py +8 -0
- quantum/core/features/loops/src/ast_node.py +60 -0
- quantum/core/features/query/src/__init__.py +0 -0
- quantum/core/features/query/src/database_service.py +322 -0
- quantum/core/features/query/src/query_validators.py +20 -0
- quantum/core/features/state_management/src/__init__.py +11 -0
- quantum/core/features/state_management/src/ast_node.py +228 -0
- quantum/core/features/terminal_engine/src/__init__.py +21 -0
- quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
- quantum/core/features/terminal_engine/src/parser.py +361 -0
- quantum/core/features/testing_engine/src/__init__.py +41 -0
- quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
- quantum/core/features/testing_engine/src/parser.py +604 -0
- quantum/core/features/theming/src/__init__.py +48 -0
- quantum/core/features/theming/src/ast_node.py +137 -0
- quantum/core/features/theming/src/presets.py +405 -0
- quantum/core/features/ui_engine/src/__init__.py +20 -0
- quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
- quantum/core/features/ui_engine/src/parser.py +1106 -0
- quantum/core/features/websocket/src/__init__.py +24 -0
- quantum/core/features/websocket/src/ast_node.py +247 -0
- quantum/core/html_compat.py +299 -0
- quantum/core/parser.py +1235 -0
- quantum/core/parser_registry.py +213 -0
- quantum/core/parsers/__init__.py +76 -0
- quantum/core/parsers/ai/__init__.py +12 -0
- quantum/core/parsers/ai/agent_parser.py +106 -0
- quantum/core/parsers/ai/knowledge_parser.py +86 -0
- quantum/core/parsers/ai/llm_parser.py +78 -0
- quantum/core/parsers/ai/team_parser.py +88 -0
- quantum/core/parsers/base.py +322 -0
- quantum/core/parsers/composition/__init__.py +10 -0
- quantum/core/parsers/composition/import_parser.py +50 -0
- quantum/core/parsers/composition/slot_parser.py +48 -0
- quantum/core/parsers/control_flow/__init__.py +11 -0
- quantum/core/parsers/control_flow/if_parser.py +68 -0
- quantum/core/parsers/control_flow/loop_parser.py +105 -0
- quantum/core/parsers/control_flow/set_parser.py +89 -0
- quantum/core/parsers/data/__init__.py +12 -0
- quantum/core/parsers/data/data_parser.py +217 -0
- quantum/core/parsers/data/invoke_parser.py +116 -0
- quantum/core/parsers/data/query_parser.py +188 -0
- quantum/core/parsers/data/transaction_parser.py +77 -0
- quantum/core/parsers/events/__init__.py +9 -0
- quantum/core/parsers/events/dispatch_event_parser.py +44 -0
- quantum/core/parsers/forms/__init__.py +11 -0
- quantum/core/parsers/forms/action_parser.py +54 -0
- quantum/core/parsers/forms/flash_parser.py +34 -0
- quantum/core/parsers/forms/redirect_parser.py +33 -0
- quantum/core/parsers/functions/__init__.py +11 -0
- quantum/core/parsers/functions/function_parser.py +137 -0
- quantum/core/parsers/functions/param_parser.py +66 -0
- quantum/core/parsers/functions/return_parser.py +31 -0
- quantum/core/parsers/html/__init__.py +10 -0
- quantum/core/parsers/html/component_call_parser.py +130 -0
- quantum/core/parsers/html/html_parser.py +115 -0
- quantum/core/parsers/jobs/__init__.py +11 -0
- quantum/core/parsers/jobs/job_parser.py +71 -0
- quantum/core/parsers/jobs/schedule_parser.py +62 -0
- quantum/core/parsers/jobs/thread_parser.py +57 -0
- quantum/core/parsers/messaging/__init__.py +17 -0
- quantum/core/parsers/messaging/message_ack_parser.py +30 -0
- quantum/core/parsers/messaging/message_nack_parser.py +30 -0
- quantum/core/parsers/messaging/message_parser.py +114 -0
- quantum/core/parsers/messaging/queue_parser.py +61 -0
- quantum/core/parsers/messaging/websocket_parser.py +121 -0
- quantum/core/parsers/persistence/__init__.py +9 -0
- quantum/core/parsers/persistence/persist_parser.py +64 -0
- quantum/core/parsers/routing/__init__.py +9 -0
- quantum/core/parsers/routing/route_parser.py +41 -0
- quantum/core/parsers/scripting/__init__.py +12 -0
- quantum/core/parsers/scripting/pyclass_parser.py +62 -0
- quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
- quantum/core/parsers/scripting/pyimport_parser.py +52 -0
- quantum/core/parsers/scripting/python_parser.py +49 -0
- quantum/core/parsers/services/__init__.py +12 -0
- quantum/core/parsers/services/dump_parser.py +52 -0
- quantum/core/parsers/services/file_parser.py +48 -0
- quantum/core/parsers/services/log_parser.py +46 -0
- quantum/core/parsers/services/mail_parser.py +65 -0
- quantum/core/tiers.py +82 -0
- quantum/packages/__init__.py +28 -0
- quantum/packages/manager.py +413 -0
- quantum/packages/manifest.py +351 -0
- quantum/packages/registry.py +399 -0
- quantum/packages/resolver.py +336 -0
- quantum/plugins/__init__.py +33 -0
- quantum/plugins/hooks.py +329 -0
- quantum/plugins/loader.py +479 -0
- quantum/plugins/manifest.py +336 -0
- quantum/plugins/registry.py +371 -0
- quantum/runtime/__init__.py +28 -0
- quantum/runtime/action_handler.py +443 -0
- quantum/runtime/adapters/__init__.py +88 -0
- quantum/runtime/adapters/memory_adapter.py +690 -0
- quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
- quantum/runtime/adapters/redis_adapter.py +582 -0
- quantum/runtime/adapters/sqlite_adapter.py +414 -0
- quantum/runtime/agent_service.py +1133 -0
- quantum/runtime/api_server.py +86 -0
- quantum/runtime/ast_cache.py +506 -0
- quantum/runtime/auth_service.py +267 -0
- quantum/runtime/component.py +990 -0
- quantum/runtime/component_composer.py +319 -0
- quantum/runtime/component_resolver.py +174 -0
- quantum/runtime/database_service.py +598 -0
- quantum/runtime/email_service.py +162 -0
- quantum/runtime/error_handler.py +295 -0
- quantum/runtime/execution_context.py +286 -0
- quantum/runtime/executor_registry.py +171 -0
- quantum/runtime/executors/__init__.py +71 -0
- quantum/runtime/executors/ai/__init__.py +12 -0
- quantum/runtime/executors/ai/agent_executor.py +217 -0
- quantum/runtime/executors/ai/knowledge_executor.py +114 -0
- quantum/runtime/executors/ai/llm_executor.py +153 -0
- quantum/runtime/executors/ai/team_executor.py +171 -0
- quantum/runtime/executors/base.py +262 -0
- quantum/runtime/executors/control_flow/__init__.py +11 -0
- quantum/runtime/executors/control_flow/if_executor.py +93 -0
- quantum/runtime/executors/control_flow/loop_executor.py +307 -0
- quantum/runtime/executors/control_flow/set_executor.py +412 -0
- quantum/runtime/executors/data/__init__.py +12 -0
- quantum/runtime/executors/data/data_executor.py +145 -0
- quantum/runtime/executors/data/invoke_executor.py +176 -0
- quantum/runtime/executors/data/query_executor.py +256 -0
- quantum/runtime/executors/data/transaction_executor.py +91 -0
- quantum/runtime/executors/jobs/__init__.py +11 -0
- quantum/runtime/executors/jobs/job_executor.py +190 -0
- quantum/runtime/executors/jobs/schedule_executor.py +132 -0
- quantum/runtime/executors/jobs/thread_executor.py +127 -0
- quantum/runtime/executors/messaging/__init__.py +17 -0
- quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
- quantum/runtime/executors/messaging/message_executor.py +174 -0
- quantum/runtime/executors/messaging/queue_executor.py +103 -0
- quantum/runtime/executors/messaging/websocket_executor.py +197 -0
- quantum/runtime/executors/scripting/__init__.py +11 -0
- quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
- quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
- quantum/runtime/executors/scripting/python_executor.py +249 -0
- quantum/runtime/executors/services/__init__.py +12 -0
- quantum/runtime/executors/services/dump_executor.py +72 -0
- quantum/runtime/executors/services/file_executor.py +89 -0
- quantum/runtime/executors/services/log_executor.py +77 -0
- quantum/runtime/executors/services/mail_executor.py +81 -0
- quantum/runtime/expression_cache.py +498 -0
- quantum/runtime/file_upload_service.py +326 -0
- quantum/runtime/function_registry.py +118 -0
- quantum/runtime/game_builder.py +166 -0
- quantum/runtime/game_code_generator.py +2371 -0
- quantum/runtime/game_templates.py +2006 -0
- quantum/runtime/godot_code_generator.py +4681 -0
- quantum/runtime/godot_templates.py +1449 -0
- quantum/runtime/job_executor.py +1599 -0
- quantum/runtime/knowledge_service.py +500 -0
- quantum/runtime/llm_cache.py +100 -0
- quantum/runtime/llm_providers.py +704 -0
- quantum/runtime/llm_service.py +287 -0
- quantum/runtime/logging_setup.py +140 -0
- quantum/runtime/message_broker.py +364 -0
- quantum/runtime/message_queue_service.py +571 -0
- quantum/runtime/param_validation.py +184 -0
- quantum/runtime/pypy_compat.py +315 -0
- quantum/runtime/python_bridge.py +698 -0
- quantum/runtime/query_validators.py +304 -0
- quantum/runtime/renderer.py +733 -0
- quantum/runtime/service_container.py +444 -0
- quantum/runtime/terminal_builder.py +76 -0
- quantum/runtime/terminal_code_generator.py +607 -0
- quantum/runtime/terminal_templates.py +243 -0
- quantum/runtime/testing_builder.py +77 -0
- quantum/runtime/testing_code_generator.py +833 -0
- quantum/runtime/testing_templates.py +85 -0
- quantum/runtime/ui_builder.py +188 -0
- quantum/runtime/ui_desktop_adapter.py +1730 -0
- quantum/runtime/ui_desktop_templates.py +307 -0
- quantum/runtime/ui_html_adapter.py +2691 -0
- quantum/runtime/ui_html_templates.py +2297 -0
- quantum/runtime/ui_mobile_adapter.py +1832 -0
- quantum/runtime/ui_mobile_templates.py +1003 -0
- quantum/runtime/ui_textual_adapter.py +1866 -0
- quantum/runtime/ui_textual_templates.py +45 -0
- quantum/runtime/ui_tokens.py +465 -0
- quantum/runtime/ui_validator.py +365 -0
- quantum/runtime/validators.py +256 -0
- quantum/runtime/web_server.py +1766 -0
- quantum/runtime/websocket_adapter.py +501 -0
- quantum/runtime/websocket_service.py +585 -0
- quantum/runtime/websocket_transport.py +289 -0
- quantum/runtime/wsgi.py +101 -0
- quantum/utils/__init__.py +1 -0
- quantum_framework-0.9.0.dist-info/METADATA +244 -0
- quantum_framework-0.9.0.dist-info/RECORD +262 -0
- quantum_framework-0.9.0.dist-info/WHEEL +5 -0
- quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
- quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
- 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
|
+
]
|