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,61 @@
1
+ """
2
+ Parser for q:dump - Variable Inspection
3
+ """
4
+
5
+ import xml.etree.ElementTree as ET
6
+ from .ast_node import DumpNode
7
+
8
+
9
+ def parse_dump(dump_element: ET.Element) -> DumpNode:
10
+ """
11
+ Parse a <q:dump> element into a DumpNode
12
+
13
+ Args:
14
+ dump_element: The XML element representing the dump statement
15
+
16
+ Returns:
17
+ DumpNode instance
18
+
19
+ Raises:
20
+ ValueError: If required attributes are missing or invalid
21
+ """
22
+ # Get required attribute
23
+ var = dump_element.get('var')
24
+
25
+ # Get optional attributes
26
+ label = dump_element.get('label')
27
+ format_str = dump_element.get('format', 'html')
28
+ depth_str = dump_element.get('depth', '10')
29
+ when = dump_element.get('when')
30
+ expand_str = dump_element.get('expand', '2')
31
+ show_types_str = dump_element.get('show_types', 'true')
32
+
33
+ # Parse depth
34
+ try:
35
+ depth = int(depth_str) if depth_str else 10
36
+ except ValueError:
37
+ depth = 10
38
+
39
+ # Parse expand
40
+ try:
41
+ expand = int(expand_str) if expand_str else 2
42
+ except ValueError:
43
+ expand = 2
44
+
45
+ # Parse show_types
46
+ show_types = show_types_str.lower() == 'true' if show_types_str else True
47
+
48
+ # Validate no child elements (q:dump should be self-closing)
49
+ if len(dump_element) > 0:
50
+ raise ValueError("Dump tag must be self-closing")
51
+
52
+ # Create and return DumpNode (validation happens in __init__)
53
+ return DumpNode(
54
+ var=var,
55
+ label=label,
56
+ format=format_str,
57
+ depth=depth,
58
+ when=when,
59
+ expand=expand,
60
+ show_types=show_types
61
+ )
@@ -0,0 +1,246 @@
1
+ """
2
+ Runtime service for q:dump - Variable Inspection
3
+ """
4
+
5
+ import json
6
+ from typing import Any, Dict, Set
7
+ from html import escape
8
+
9
+
10
+ class DumpService:
11
+ """
12
+ Service to handle variable inspection and formatted output
13
+
14
+ Phase 1 Features:
15
+ - HTML, JSON, and text output formats
16
+ - Depth limiting
17
+ - Type information
18
+ - Circular reference detection
19
+
20
+ Phase 2 Features (TODO):
21
+ - Rich library integration for beautiful output
22
+ - Expandable/collapsible trees
23
+ - Search within dumps
24
+ - Side-by-side comparison
25
+ - Custom themes
26
+ """
27
+
28
+ def __init__(self):
29
+ """Initialize the dump service"""
30
+ self._seen_objects: Set[int] = set()
31
+
32
+ def dump(
33
+ self,
34
+ var: Any,
35
+ label: str,
36
+ format: str = 'html',
37
+ depth: int = 10,
38
+ current_depth: int = 0
39
+ ) -> str:
40
+ """
41
+ Generate formatted dump output for a variable
42
+
43
+ Args:
44
+ var: Variable to inspect
45
+ label: Label for the dump
46
+ format: Output format (html, json, text)
47
+ depth: Maximum nesting depth
48
+ current_depth: Current recursion depth
49
+
50
+ Returns:
51
+ Formatted string output
52
+ """
53
+ # Reset seen objects for new dump
54
+ if current_depth == 0:
55
+ self._seen_objects = set()
56
+
57
+ if format == 'json':
58
+ return self._dump_json(var, label)
59
+ elif format == 'text':
60
+ return self._dump_text(var, label, depth, current_depth)
61
+ else: # html (default)
62
+ return self._dump_html(var, label, depth, current_depth)
63
+
64
+ def _dump_json(self, var: Any, label: str) -> str:
65
+ """Dump as pretty-printed JSON"""
66
+ output = [f"=== {label} ==="]
67
+ try:
68
+ json_str = json.dumps(var, indent=2, default=str)
69
+ output.append(json_str)
70
+ except Exception as e:
71
+ output.append(f"Error dumping as JSON: {e}")
72
+ output.append(f"Type: {type(var).__name__}")
73
+ output.append(f"Value: {str(var)}")
74
+ return '\n'.join(output)
75
+
76
+ def _dump_text(
77
+ self,
78
+ var: Any,
79
+ label: str,
80
+ max_depth: int,
81
+ current_depth: int,
82
+ prefix: str = ''
83
+ ) -> str:
84
+ """Dump as plain text tree structure"""
85
+ if current_depth == 0:
86
+ output = [f"=== {label} ==="]
87
+ else:
88
+ output = []
89
+
90
+ # Check depth limit
91
+ if current_depth >= max_depth:
92
+ output.append(f"{prefix}... (max depth reached)")
93
+ return '\n'.join(output)
94
+
95
+ # Get type name
96
+ type_name = type(var).__name__
97
+
98
+ # Handle None/null
99
+ if var is None:
100
+ output.append(f"{prefix}{label} => null")
101
+ return '\n'.join(output)
102
+
103
+ # Handle primitives
104
+ if isinstance(var, (str, int, float, bool)):
105
+ if isinstance(var, str):
106
+ value_repr = f'"{var}"'
107
+ else:
108
+ value_repr = str(var).lower() if isinstance(var, bool) else str(var)
109
+ output.append(f"{prefix}{label} => {value_repr} ({type_name})")
110
+ return '\n'.join(output)
111
+
112
+ # Handle dictionaries/objects
113
+ if isinstance(var, dict):
114
+ output.append(f"{prefix}{label} (dict, {len(var)} items):")
115
+ for key, value in var.items():
116
+ sub_output = self._dump_text(
117
+ value,
118
+ str(key),
119
+ max_depth,
120
+ current_depth + 1,
121
+ prefix + ' '
122
+ )
123
+ # Skip the header line for nested items
124
+ sub_lines = sub_output.split('\n')
125
+ if current_depth > 0 and sub_lines:
126
+ output.extend(sub_lines)
127
+ else:
128
+ output.append(sub_output)
129
+ return '\n'.join(output)
130
+
131
+ # Handle lists/arrays
132
+ if isinstance(var, (list, tuple)):
133
+ output.append(f"{prefix}{label} ({type_name}, {len(var)} items):")
134
+ for i, item in enumerate(var):
135
+ sub_output = self._dump_text(
136
+ item,
137
+ f"[{i}]",
138
+ max_depth,
139
+ current_depth + 1,
140
+ prefix + ' '
141
+ )
142
+ sub_lines = sub_output.split('\n')
143
+ if current_depth > 0 and sub_lines:
144
+ output.extend(sub_lines)
145
+ else:
146
+ output.append(sub_output)
147
+ return '\n'.join(output)
148
+
149
+ # Handle other types
150
+ output.append(f"{prefix}{label} => {str(var)} ({type_name})")
151
+ return '\n'.join(output)
152
+
153
+ def _dump_html(
154
+ self,
155
+ var: Any,
156
+ label: str,
157
+ max_depth: int,
158
+ current_depth: int
159
+ ) -> str:
160
+ """Dump as HTML with styling"""
161
+ if current_depth == 0:
162
+ output = [
163
+ '<div class="quantum-dump" style="font-family: monospace; background: #f5f5f5; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px;">',
164
+ f'<h4 style="margin: 0 0 10px 0; color: #333;">{escape(label)}</h4>'
165
+ ]
166
+ else:
167
+ output = []
168
+
169
+ # Check depth limit
170
+ if current_depth >= max_depth:
171
+ output.append(f'<span style="color: #999;">... (max depth reached)</span>')
172
+ if current_depth == 0:
173
+ output.append('</div>')
174
+ return ''.join(output)
175
+
176
+ # Get type name
177
+ type_name = type(var).__name__
178
+
179
+ # Handle None/null
180
+ if var is None:
181
+ output.append('<span style="color: #999; font-style: italic;">null</span>')
182
+ if current_depth == 0:
183
+ output.append('</div>')
184
+ return ''.join(output)
185
+
186
+ # Handle primitives
187
+ if isinstance(var, bool):
188
+ color = '#008800' if var else '#cc0000'
189
+ output.append(f'<span style="color: {color}; font-weight: bold;">{str(var).lower()}</span>')
190
+ output.append(f' <span style="color: #999; font-size: 0.9em;">(boolean)</span>')
191
+ elif isinstance(var, (int, float)):
192
+ output.append(f'<span style="color: #0066cc; font-weight: bold;">{var}</span>')
193
+ output.append(f' <span style="color: #999; font-size: 0.9em;">({type_name})</span>')
194
+ elif isinstance(var, str):
195
+ output.append(f'<span style="color: #cc6600;">"{escape(var)}"</span>')
196
+ output.append(f' <span style="color: #999; font-size: 0.9em;">(string)</span>')
197
+ # Handle dictionaries/objects
198
+ elif isinstance(var, dict):
199
+ output.append(f'<span style="color: #999;">(dict, {len(var)} items)</span>')
200
+ output.append('<ul style="margin: 5px 0; padding-left: 20px; list-style: none;">')
201
+ for key, value in var.items():
202
+ output.append('<li style="margin: 2px 0;">')
203
+ output.append(f'<span style="color: #660066; font-weight: bold;">{escape(str(key))}</span>: ')
204
+ output.append(self._dump_html(value, '', max_depth, current_depth + 1))
205
+ output.append('</li>')
206
+ output.append('</ul>')
207
+ # Handle lists/arrays
208
+ elif isinstance(var, (list, tuple)):
209
+ output.append(f'<span style="color: #999;">({type_name}, {len(var)} items)</span>')
210
+ output.append('<ul style="margin: 5px 0; padding-left: 20px; list-style: none;">')
211
+ for i, item in enumerate(var):
212
+ output.append('<li style="margin: 2px 0;">')
213
+ output.append(f'<span style="color: #660066; font-weight: bold;">[{i}]</span>: ')
214
+ output.append(self._dump_html(item, '', max_depth, current_depth + 1))
215
+ output.append('</li>')
216
+ output.append('</ul>')
217
+ # Handle other types
218
+ else:
219
+ output.append(f'<span style="color: #666;">{escape(str(var))}</span>')
220
+ output.append(f' <span style="color: #999; font-size: 0.9em;">({type_name})</span>')
221
+
222
+ if current_depth == 0:
223
+ output.append('</div>')
224
+
225
+ return ''.join(output)
226
+
227
+ def should_dump(self, condition: Any) -> bool:
228
+ """
229
+ Evaluate if dumping should occur based on 'when' condition
230
+
231
+ Args:
232
+ condition: Evaluated condition value
233
+
234
+ Returns:
235
+ True if should dump, False otherwise
236
+ """
237
+ # If no condition, always dump
238
+ if condition is None:
239
+ return True
240
+
241
+ # Evaluate boolean condition
242
+ if isinstance(condition, bool):
243
+ return condition
244
+
245
+ # Truthy evaluation for other types
246
+ return bool(condition)
@@ -0,0 +1,8 @@
1
+ """
2
+ Functions Feature (q:function)
3
+ """
4
+
5
+ from .ast_node import FunctionNode, RestConfig
6
+
7
+ __all__ = ['FunctionNode', 'RestConfig']
8
+ __version__ = '1.0.0'
@@ -0,0 +1,149 @@
1
+ """
2
+ AST Node for Functions (q:function)
3
+ """
4
+
5
+ from typing import Dict, Any, List, Optional
6
+ from dataclasses import dataclass
7
+
8
+ # Import base class
9
+ import sys
10
+ from pathlib import Path
11
+ from quantum.core.ast_nodes import QuantumNode, QuantumParam
12
+
13
+
14
+ @dataclass
15
+ class RestConfig:
16
+ """REST configuration for a function - OPTIONAL"""
17
+ # Required (if REST enabled)
18
+ endpoint: str
19
+ method: str = "GET"
20
+
21
+ # Optional (with sensible defaults)
22
+ produces: str = "application/json"
23
+ consumes: str = "application/json"
24
+ auth: Optional[str] = None # None = no auth, or: bearer, basic, apikey
25
+ roles: List[str] = None # None = no role check
26
+ rate_limit: Optional[str] = None # "100/minute"
27
+ cors: bool = False
28
+ status: int = 200 # Default status code
29
+
30
+ def __post_init__(self):
31
+ if self.roles is None:
32
+ self.roles = []
33
+
34
+
35
+ class FunctionNode(QuantumNode):
36
+ """Represents a <q:function>"""
37
+
38
+ def __init__(self, name: str):
39
+ # ========== CORE (required) ==========
40
+ self.name = name
41
+ self.return_type = "any"
42
+ self.scope = "component" # component, global, api
43
+ self.access = "public" # public, private, protected
44
+ self.params: List[QuantumParam] = []
45
+ self.body: List[QuantumNode] = []
46
+
47
+ # ========== OPTIONAL LAYERS ==========
48
+
49
+ # Layer 1: Documentation
50
+ self.description = None
51
+ self.hint = None
52
+
53
+ # Layer 2: Validation
54
+ self.validate_params = False # Auto-validate params
55
+
56
+ # Layer 3: Performance
57
+ self.cache = False
58
+ self.cache_ttl = None # seconds
59
+ self.memoize = False
60
+ self.pure = False
61
+
62
+ # Layer 4: Behavior
63
+ self.async_func = False
64
+ self.retry = 0
65
+ self.timeout = None # seconds
66
+
67
+ # Layer 5: REST API (completely optional)
68
+ self.rest_config: Optional[RestConfig] = None
69
+
70
+ # Back-reference to container
71
+ self.container: Optional['ComponentNode'] = None
72
+
73
+ def is_rest_enabled(self) -> bool:
74
+ """Check if function has REST configuration"""
75
+ return self.rest_config is not None
76
+
77
+ def enable_rest(self, endpoint: str, method: str = "GET"):
78
+ """Enable REST for this function"""
79
+ self.rest_config = RestConfig(
80
+ endpoint=endpoint,
81
+ method=method
82
+ )
83
+
84
+ def is_private(self) -> bool:
85
+ """Check if function is private (starts with _ or access=private)"""
86
+ return self.access == "private" or self.name.startswith('_')
87
+
88
+ def add_param(self, param: QuantumParam):
89
+ """Add parameter to function"""
90
+ self.params.append(param)
91
+
92
+ def add_statement(self, statement: QuantumNode):
93
+ """Add statement to function body"""
94
+ self.body.append(statement)
95
+
96
+ def to_dict(self) -> Dict[str, Any]:
97
+ result = {
98
+ "type": "function",
99
+ "name": self.name,
100
+ "return_type": self.return_type,
101
+ "scope": self.scope,
102
+ "access": self.access,
103
+ "params_count": len(self.params),
104
+ "body_statements": len(self.body),
105
+ "description": self.description,
106
+ "validate_params": self.validate_params,
107
+ "cache": self.cache,
108
+ "memoize": self.memoize,
109
+ "pure": self.pure,
110
+ "async": self.async_func,
111
+ "retry": self.retry,
112
+ "timeout": self.timeout
113
+ }
114
+
115
+ if self.rest_config:
116
+ result["rest"] = {
117
+ "endpoint": self.rest_config.endpoint,
118
+ "method": self.rest_config.method,
119
+ "produces": self.rest_config.produces,
120
+ "consumes": self.rest_config.consumes,
121
+ "auth": self.rest_config.auth,
122
+ "roles": self.rest_config.roles,
123
+ "status": self.rest_config.status
124
+ }
125
+
126
+ return result
127
+
128
+ def validate(self) -> List[str]:
129
+ errors = []
130
+
131
+ if not self.name:
132
+ errors.append("Function name is required")
133
+
134
+ # Validate params
135
+ for param in self.params:
136
+ errors.extend(param.validate())
137
+
138
+ # Validate body
139
+ for statement in self.body:
140
+ errors.extend(statement.validate())
141
+
142
+ # Validate REST config if present
143
+ if self.rest_config:
144
+ if not self.rest_config.endpoint:
145
+ errors.append("REST endpoint is required when REST is enabled")
146
+ if self.rest_config.method not in ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']:
147
+ errors.append(f"Invalid HTTP method: {self.rest_config.method}")
148
+
149
+ return errors
@@ -0,0 +1,19 @@
1
+ """
2
+ Game Engine 2D - AST nodes and parser for the qg: namespace.
3
+ """
4
+
5
+ from .ast_nodes import (
6
+ SceneNode, SpriteNode, PhysicsNode, ColliderNode, AnimationNode,
7
+ OnCollisionNode, CameraNode, InputNode, SoundNode, ParticleNode, TimerNode,
8
+ SpawnNode, HudNode, TweenNode, TilemapNode, TilemapLayerNode,
9
+ BehaviorNode, UseNode, PrefabNode, InstanceNode, GroupNode,
10
+ StateMachineNode, StateNode, TransitionNode,
11
+ )
12
+
13
+ __all__ = [
14
+ 'SceneNode', 'SpriteNode', 'PhysicsNode', 'ColliderNode', 'AnimationNode',
15
+ 'OnCollisionNode', 'CameraNode', 'InputNode', 'SoundNode', 'ParticleNode', 'TimerNode',
16
+ 'SpawnNode', 'HudNode', 'TweenNode', 'TilemapNode', 'TilemapLayerNode',
17
+ 'BehaviorNode', 'UseNode', 'PrefabNode', 'InstanceNode', 'GroupNode',
18
+ 'StateMachineNode', 'StateNode', 'TransitionNode',
19
+ ]