quantum-framework 0.18.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 (333) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/admin.py +131 -0
  4. quantum/cli/check.py +223 -0
  5. quantum/cli/commands/__init__.py +15 -0
  6. quantum/cli/commands/build.py +414 -0
  7. quantum/cli/commands/dev.py +185 -0
  8. quantum/cli/commands/docs.py +329 -0
  9. quantum/cli/commands/lint.py +523 -0
  10. quantum/cli/commands/migrate.py +548 -0
  11. quantum/cli/commands/new.py +622 -0
  12. quantum/cli/commands/serve.py +190 -0
  13. quantum/cli/commands/test.py +193 -0
  14. quantum/cli/deploy.py +810 -0
  15. quantum/cli/hot_reload.py +951 -0
  16. quantum/cli/jobs.py +356 -0
  17. quantum/cli/mq.py +582 -0
  18. quantum/cli/pkg.py +390 -0
  19. quantum/cli/runner.py +565 -0
  20. quantum/cli/server_process.py +159 -0
  21. quantum/cli/utils.py +334 -0
  22. quantum/compiler/__init__.py +30 -0
  23. quantum/compiler/base_generator.py +367 -0
  24. quantum/compiler/cli.py +295 -0
  25. quantum/compiler/expression_transformer.py +444 -0
  26. quantum/compiler/javascript/__init__.py +10 -0
  27. quantum/compiler/javascript/generator.py +659 -0
  28. quantum/compiler/optimizer.py +270 -0
  29. quantum/compiler/python/__init__.py +10 -0
  30. quantum/compiler/python/generator.py +883 -0
  31. quantum/compiler/python/runtime.py +863 -0
  32. quantum/compiler/transpiler.py +330 -0
  33. quantum/core/__init__.py +3 -0
  34. quantum/core/ast_nodes.py +2619 -0
  35. quantum/core/config_env.py +54 -0
  36. quantum/core/docs_links.py +8 -0
  37. quantum/core/expression_diagnostics.py +87 -0
  38. quantum/core/expression_stdlib.py +208 -0
  39. quantum/core/expressions.py +677 -0
  40. quantum/core/features/agents/src/__init__.py +30 -0
  41. quantum/core/features/agents/src/ast_node.py +540 -0
  42. quantum/core/features/conditionals/src/__init__.py +8 -0
  43. quantum/core/features/conditionals/src/ast_node.py +68 -0
  44. quantum/core/features/data_import/src/__init__.py +0 -0
  45. quantum/core/features/data_import/src/ast_node.py +292 -0
  46. quantum/core/features/data_import/src/runtime.py +533 -0
  47. quantum/core/features/dump/src/__init__.py +12 -0
  48. quantum/core/features/dump/src/ast_node.py +106 -0
  49. quantum/core/features/dump/src/parser.py +61 -0
  50. quantum/core/features/dump/src/runtime.py +246 -0
  51. quantum/core/features/functions/src/__init__.py +8 -0
  52. quantum/core/features/functions/src/ast_node.py +149 -0
  53. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  54. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  55. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  56. quantum/core/features/invocation/src/__init__.py +0 -0
  57. quantum/core/features/invocation/src/ast_node.py +147 -0
  58. quantum/core/features/invocation/src/runtime.py +332 -0
  59. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  60. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  61. quantum/core/features/knowledge_base/src/parser.py +82 -0
  62. quantum/core/features/logging/src/__init__.py +12 -0
  63. quantum/core/features/logging/src/ast_node.py +111 -0
  64. quantum/core/features/logging/src/parser.py +50 -0
  65. quantum/core/features/logging/src/runtime.py +190 -0
  66. quantum/core/features/loops/src/__init__.py +8 -0
  67. quantum/core/features/loops/src/ast_node.py +60 -0
  68. quantum/core/features/query/src/__init__.py +0 -0
  69. quantum/core/features/query/src/query_validators.py +20 -0
  70. quantum/core/features/state_management/src/__init__.py +11 -0
  71. quantum/core/features/state_management/src/ast_node.py +121 -0
  72. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  73. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  74. quantum/core/features/terminal_engine/src/parser.py +361 -0
  75. quantum/core/features/testing_engine/src/__init__.py +41 -0
  76. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  77. quantum/core/features/testing_engine/src/parser.py +604 -0
  78. quantum/core/features/theming/src/__init__.py +48 -0
  79. quantum/core/features/theming/src/ast_node.py +137 -0
  80. quantum/core/features/theming/src/presets.py +405 -0
  81. quantum/core/features/ui_engine/src/__init__.py +20 -0
  82. quantum/core/features/ui_engine/src/ast_nodes.py +1913 -0
  83. quantum/core/features/ui_engine/src/parser.py +1192 -0
  84. quantum/core/features/websocket/src/__init__.py +24 -0
  85. quantum/core/features/websocket/src/ast_node.py +247 -0
  86. quantum/core/guards.py +53 -0
  87. quantum/core/html_compat.py +299 -0
  88. quantum/core/parser.py +1551 -0
  89. quantum/core/parser_registry.py +213 -0
  90. quantum/core/parsers/__init__.py +76 -0
  91. quantum/core/parsers/ai/__init__.py +12 -0
  92. quantum/core/parsers/ai/agent_parser.py +106 -0
  93. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  94. quantum/core/parsers/ai/llm_parser.py +78 -0
  95. quantum/core/parsers/ai/team_parser.py +88 -0
  96. quantum/core/parsers/base.py +322 -0
  97. quantum/core/parsers/composition/__init__.py +10 -0
  98. quantum/core/parsers/composition/import_parser.py +50 -0
  99. quantum/core/parsers/composition/slot_parser.py +48 -0
  100. quantum/core/parsers/control_flow/__init__.py +11 -0
  101. quantum/core/parsers/control_flow/if_parser.py +71 -0
  102. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  103. quantum/core/parsers/control_flow/set_parser.py +93 -0
  104. quantum/core/parsers/data/__init__.py +12 -0
  105. quantum/core/parsers/data/data_parser.py +229 -0
  106. quantum/core/parsers/data/invoke_parser.py +133 -0
  107. quantum/core/parsers/data/query_parser.py +213 -0
  108. quantum/core/parsers/data/transaction_parser.py +86 -0
  109. quantum/core/parsers/events/__init__.py +9 -0
  110. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  111. quantum/core/parsers/forms/__init__.py +11 -0
  112. quantum/core/parsers/forms/action_parser.py +79 -0
  113. quantum/core/parsers/forms/flash_parser.py +34 -0
  114. quantum/core/parsers/forms/redirect_parser.py +33 -0
  115. quantum/core/parsers/functions/__init__.py +11 -0
  116. quantum/core/parsers/functions/function_parser.py +98 -0
  117. quantum/core/parsers/functions/param_parser.py +73 -0
  118. quantum/core/parsers/functions/return_parser.py +31 -0
  119. quantum/core/parsers/html/__init__.py +10 -0
  120. quantum/core/parsers/html/component_call_parser.py +130 -0
  121. quantum/core/parsers/html/html_parser.py +115 -0
  122. quantum/core/parsers/jobs/__init__.py +11 -0
  123. quantum/core/parsers/jobs/job_parser.py +71 -0
  124. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  125. quantum/core/parsers/jobs/thread_parser.py +57 -0
  126. quantum/core/parsers/messaging/__init__.py +17 -0
  127. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  128. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_parser.py +114 -0
  130. quantum/core/parsers/messaging/queue_parser.py +61 -0
  131. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  132. quantum/core/parsers/routing/__init__.py +9 -0
  133. quantum/core/parsers/routing/route_parser.py +41 -0
  134. quantum/core/parsers/scripting/__init__.py +12 -0
  135. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  136. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  137. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  138. quantum/core/parsers/scripting/python_parser.py +49 -0
  139. quantum/core/parsers/services/__init__.py +12 -0
  140. quantum/core/parsers/services/dump_parser.py +52 -0
  141. quantum/core/parsers/services/file_parser.py +48 -0
  142. quantum/core/parsers/services/log_parser.py +46 -0
  143. quantum/core/parsers/services/mail_parser.py +65 -0
  144. quantum/core/tiers.py +164 -0
  145. quantum/core/xml_lines.py +81 -0
  146. quantum/packages/__init__.py +28 -0
  147. quantum/packages/manager.py +413 -0
  148. quantum/packages/manifest.py +351 -0
  149. quantum/packages/registry.py +399 -0
  150. quantum/packages/resolver.py +336 -0
  151. quantum/plugins/__init__.py +33 -0
  152. quantum/plugins/hooks.py +329 -0
  153. quantum/plugins/loader.py +479 -0
  154. quantum/plugins/manifest.py +336 -0
  155. quantum/plugins/registry.py +371 -0
  156. quantum/runtime/__init__.py +25 -0
  157. quantum/runtime/action_handler.py +532 -0
  158. quantum/runtime/adapters/__init__.py +88 -0
  159. quantum/runtime/adapters/memory_adapter.py +690 -0
  160. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  161. quantum/runtime/adapters/redis_adapter.py +582 -0
  162. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  163. quantum/runtime/agent_service.py +1133 -0
  164. quantum/runtime/ast_cache.py +506 -0
  165. quantum/runtime/auth_service.py +267 -0
  166. quantum/runtime/component.py +1048 -0
  167. quantum/runtime/component_composer.py +133 -0
  168. quantum/runtime/component_resolver.py +174 -0
  169. quantum/runtime/conditions.py +54 -0
  170. quantum/runtime/database_service.py +595 -0
  171. quantum/runtime/db_schema.py +100 -0
  172. quantum/runtime/dev_panel.py +178 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +283 -0
  176. quantum/runtime/executor_registry.py +178 -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 +264 -0
  184. quantum/runtime/executors/control_flow/__init__.py +12 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +98 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +308 -0
  187. quantum/runtime/executors/control_flow/redirect_executor.py +43 -0
  188. quantum/runtime/executors/control_flow/set_executor.py +464 -0
  189. quantum/runtime/executors/data/__init__.py +12 -0
  190. quantum/runtime/executors/data/data_executor.py +156 -0
  191. quantum/runtime/executors/data/invoke_executor.py +228 -0
  192. quantum/runtime/executors/data/query_executor.py +290 -0
  193. quantum/runtime/executors/data/transaction_executor.py +91 -0
  194. quantum/runtime/executors/jobs/__init__.py +11 -0
  195. quantum/runtime/executors/jobs/job_executor.py +190 -0
  196. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  197. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  198. quantum/runtime/executors/messaging/__init__.py +17 -0
  199. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  200. quantum/runtime/executors/messaging/message_executor.py +174 -0
  201. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  202. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  203. quantum/runtime/executors/scripting/__init__.py +11 -0
  204. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  205. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  206. quantum/runtime/executors/scripting/python_executor.py +249 -0
  207. quantum/runtime/executors/services/__init__.py +12 -0
  208. quantum/runtime/executors/services/dump_executor.py +72 -0
  209. quantum/runtime/executors/services/file_executor.py +89 -0
  210. quantum/runtime/executors/services/log_executor.py +77 -0
  211. quantum/runtime/executors/services/mail_executor.py +81 -0
  212. quantum/runtime/expression_cache.py +498 -0
  213. quantum/runtime/file_upload_service.py +326 -0
  214. quantum/runtime/function_registry.py +118 -0
  215. quantum/runtime/game_builder.py +166 -0
  216. quantum/runtime/game_code_generator.py +2371 -0
  217. quantum/runtime/game_templates.py +2006 -0
  218. quantum/runtime/godot_code_generator.py +4681 -0
  219. quantum/runtime/godot_templates.py +1449 -0
  220. quantum/runtime/job_executor.py +1599 -0
  221. quantum/runtime/knowledge_service.py +546 -0
  222. quantum/runtime/llm_cache.py +100 -0
  223. quantum/runtime/llm_providers.py +704 -0
  224. quantum/runtime/llm_service.py +287 -0
  225. quantum/runtime/local_server.py +28 -0
  226. quantum/runtime/logging_setup.py +141 -0
  227. quantum/runtime/message_broker.py +364 -0
  228. quantum/runtime/message_queue_service.py +571 -0
  229. quantum/runtime/param_validation.py +218 -0
  230. quantum/runtime/pypy_compat.py +317 -0
  231. quantum/runtime/python_bridge.py +698 -0
  232. quantum/runtime/query_validators.py +304 -0
  233. quantum/runtime/renderer.py +734 -0
  234. quantum/runtime/service_container.py +470 -0
  235. quantum/runtime/table_params.py +163 -0
  236. quantum/runtime/terminal_builder.py +76 -0
  237. quantum/runtime/terminal_code_generator.py +607 -0
  238. quantum/runtime/terminal_templates.py +243 -0
  239. quantum/runtime/testing_builder.py +77 -0
  240. quantum/runtime/testing_code_generator.py +833 -0
  241. quantum/runtime/testing_templates.py +85 -0
  242. quantum/runtime/ui_builder.py +222 -0
  243. quantum/runtime/ui_console.py +405 -0
  244. quantum/runtime/ui_desktop.py +56 -0
  245. quantum/runtime/ui_form_rules.py +193 -0
  246. quantum/runtime/ui_html_adapter.py +2567 -0
  247. quantum/runtime/ui_html_templates.py +2106 -0
  248. quantum/runtime/ui_mobile_adapter.py +1832 -0
  249. quantum/runtime/ui_mobile_templates.py +1003 -0
  250. quantum/runtime/ui_page_renderer.py +392 -0
  251. quantum/runtime/ui_pager.py +73 -0
  252. quantum/runtime/ui_table_edit.py +139 -0
  253. quantum/runtime/ui_textual_adapter.py +1866 -0
  254. quantum/runtime/ui_textual_templates.py +45 -0
  255. quantum/runtime/ui_tokens.py +465 -0
  256. quantum/runtime/ui_validator.py +365 -0
  257. quantum/runtime/ui_view.py +221 -0
  258. quantum/runtime/validators.py +256 -0
  259. quantum/runtime/web_server.py +2131 -0
  260. quantum/runtime/websocket_adapter.py +501 -0
  261. quantum/runtime/websocket_service.py +585 -0
  262. quantum/runtime/websocket_transport.py +289 -0
  263. quantum/runtime/wsgi.py +101 -0
  264. quantum/services.py +109 -0
  265. quantum/utils/__init__.py +1 -0
  266. quantum_admin/__init__.py +4 -0
  267. quantum_admin/assets/quantum-admin-connectors.js +123 -0
  268. quantum_admin/assets/quantum-admin.css +2058 -0
  269. quantum_admin/assets/quantum-source-highlight.js +106 -0
  270. quantum_admin/backend/__init__.py +4 -0
  271. quantum_admin/backend/audit_service.py +346 -0
  272. quantum_admin/backend/auth_service.py +394 -0
  273. quantum_admin/backend/component_discovery.py +766 -0
  274. quantum_admin/backend/config_generator.py +586 -0
  275. quantum_admin/backend/connector_service.py +1016 -0
  276. quantum_admin/backend/crud.py +557 -0
  277. quantum_admin/backend/database.py +226 -0
  278. quantum_admin/backend/db_setup_service.py +193 -0
  279. quantum_admin/backend/deploy_service.py +698 -0
  280. quantum_admin/backend/docker_service.py +422 -0
  281. quantum_admin/backend/environment_service.py +418 -0
  282. quantum_admin/backend/git_service.py +370 -0
  283. quantum_admin/backend/health_service.py +390 -0
  284. quantum_admin/backend/job_service.py +347 -0
  285. quantum_admin/backend/log_service.py +331 -0
  286. quantum_admin/backend/main.py +14426 -0
  287. quantum_admin/backend/models.py +986 -0
  288. quantum_admin/backend/pipeline_service.py +812 -0
  289. quantum_admin/backend/resource_manager.py +1118 -0
  290. quantum_admin/backend/schemas.py +419 -0
  291. quantum_admin/backend/secret_manager.py +277 -0
  292. quantum_admin/backend/settings_service.py +488 -0
  293. quantum_admin/backend/template_service.py +710 -0
  294. quantum_admin/backend/test_execution_service.py +364 -0
  295. quantum_admin/backend/test_generator.py +782 -0
  296. quantum_admin/backend/webhook_service.py +454 -0
  297. quantum_admin/backend/websocket_manager.py +360 -0
  298. quantum_admin/components/admin/_layout/AdminShell.q +121 -0
  299. quantum_admin/components/admin/agents.q +107 -0
  300. quantum_admin/components/admin/app/[name].q +558 -0
  301. quantum_admin/components/admin/applications.q +160 -0
  302. quantum_admin/components/admin/component/[...path].q +205 -0
  303. quantum_admin/components/admin/components.q +59 -0
  304. quantum_admin/components/admin/connectors.q +283 -0
  305. quantum_admin/components/admin/dashboard.q +86 -0
  306. quantum_admin/components/admin/database.q +95 -0
  307. quantum_admin/components/admin/features.q +69 -0
  308. quantum_admin/components/admin/index.q +12 -0
  309. quantum_admin/components/admin/jobs.q +75 -0
  310. quantum_admin/components/admin/login.q +65 -0
  311. quantum_admin/components/admin/logout.q +11 -0
  312. quantum_admin/components/admin/settings.q +174 -0
  313. quantum_admin/components/admin/source.q +45 -0
  314. quantum_admin/components/admin/tests.q +73 -0
  315. quantum_admin/run.py +13 -0
  316. quantum_admin/services/__init__.py +16 -0
  317. quantum_admin/services/_base.py +84 -0
  318. quantum_admin/services/_component_test_generator.py +205 -0
  319. quantum_admin/services/_yaml_editor.py +82 -0
  320. quantum_admin/services/apps.py +330 -0
  321. quantum_admin/services/auth.py +61 -0
  322. quantum_admin/services/components.py +210 -0
  323. quantum_admin/services/connectors.py +164 -0
  324. quantum_admin/services/projects.py +189 -0
  325. quantum_admin/services/repository.py +223 -0
  326. quantum_admin/services/settings.py +150 -0
  327. quantum_admin/services/yaml_import.py +118 -0
  328. quantum_framework-0.18.0.dist-info/METADATA +281 -0
  329. quantum_framework-0.18.0.dist-info/RECORD +333 -0
  330. quantum_framework-0.18.0.dist-info/WHEEL +5 -0
  331. quantum_framework-0.18.0.dist-info/entry_points.txt +2 -0
  332. quantum_framework-0.18.0.dist-info/licenses/LICENSE +21 -0
  333. quantum_framework-0.18.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,9 @@
1
+ """
2
+ Routing Parsers
3
+
4
+ Parsers for routing-related tags: route
5
+ """
6
+
7
+ from .route_parser import RouteParser
8
+
9
+ __all__ = ['RouteParser']
@@ -0,0 +1,41 @@
1
+ """
2
+ Route Parser - Parse q:route statements
3
+ """
4
+
5
+ from typing import List
6
+ from xml.etree import ElementTree as ET
7
+ from quantum.core.parsers.base import BaseTagParser
8
+ from quantum.core.ast_nodes import QuantumRoute
9
+
10
+
11
+ class RouteParser(BaseTagParser):
12
+ """
13
+ Parser for q:route statements.
14
+
15
+ Examples:
16
+ <q:route path="/users" method="GET" />
17
+ <q:route path="/api/products/{id}" method="POST">
18
+ <q:return name="product" type="object" />
19
+ </q:route>
20
+ """
21
+
22
+ @property
23
+ def tag_names(self) -> List[str]:
24
+ return ['route']
25
+
26
+ def parse(self, element: ET.Element) -> QuantumRoute:
27
+ """Parse q:route element"""
28
+ path = element.get('path', '/')
29
+ method = element.get('method', 'GET').upper()
30
+
31
+ route = QuantumRoute(path, method)
32
+
33
+ # Parse q:return inside the route
34
+ for child in element:
35
+ child_type = self._get_element_name(child)
36
+ if child_type == 'return':
37
+ return_node = self.parse_child(child)
38
+ if return_node:
39
+ route.returns.append(return_node)
40
+
41
+ return route
@@ -0,0 +1,12 @@
1
+ """
2
+ Scripting Parsers
3
+
4
+ Parsers for Python scripting: python, pyimport, pyclass, pydecorator.
5
+ """
6
+
7
+ from .python_parser import PythonParser
8
+ from .pyimport_parser import PyImportParser
9
+ from .pyclass_parser import PyClassParser
10
+ from .pydecorator_parser import PyDecoratorParser
11
+
12
+ __all__ = ['PythonParser', 'PyImportParser', 'PyClassParser', 'PyDecoratorParser']
@@ -0,0 +1,62 @@
1
+ """
2
+ PyClass Parser - Parse q:class statements
3
+
4
+ Handles inline Python class definitions.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser, ParserError
10
+ from quantum.core.ast_nodes import PyClassNode
11
+
12
+
13
+ class PyClassParser(BaseTagParser):
14
+ """
15
+ Parser for q:class statements.
16
+
17
+ Supports:
18
+ - Class definition
19
+ - Base class inheritance
20
+ - Decorator application
21
+ """
22
+
23
+ @property
24
+ def tag_names(self) -> List[str]:
25
+ return ['class', 'pyclass']
26
+
27
+ def parse(self, element: ET.Element) -> PyClassNode:
28
+ """
29
+ Parse q:class statement.
30
+
31
+ Args:
32
+ element: XML element for q:class
33
+
34
+ Returns:
35
+ PyClassNode AST node
36
+ """
37
+ name = self.get_attr(element, 'name')
38
+ code = self.get_text(element)
39
+
40
+ if not name:
41
+ raise ParserError("class requires 'name' attribute")
42
+ if not code or not code.strip():
43
+ raise ParserError("class body cannot be empty")
44
+
45
+ # Parse bases
46
+ bases_attr = self.get_attr(element, 'bases')
47
+ bases = []
48
+ if bases_attr:
49
+ bases = [b.strip() for b in bases_attr.split(',')]
50
+
51
+ # Parse decorators
52
+ decorators_attr = self.get_attr(element, 'decorators')
53
+ decorators = []
54
+ if decorators_attr:
55
+ decorators = [d.strip() for d in decorators_attr.split(',')]
56
+
57
+ return PyClassNode(
58
+ name=name,
59
+ code=code,
60
+ bases=bases,
61
+ decorators=decorators
62
+ )
@@ -0,0 +1,68 @@
1
+ """
2
+ PyDecorator Parser - Parse q:decorator statements
3
+ """
4
+
5
+ import textwrap
6
+ from typing import List
7
+ from xml.etree import ElementTree as ET
8
+ from quantum.core.parsers.base import BaseTagParser
9
+ from quantum.core.ast_nodes import PyDecoratorNode
10
+
11
+
12
+ class PyDecoratorParser(BaseTagParser):
13
+ """
14
+ Parser for q:decorator statements for Python decorator definitions.
15
+
16
+ Examples:
17
+ <!-- Caching decorator -->
18
+ <q:decorator name="cached">
19
+ from functools import wraps
20
+ def decorator(func):
21
+ cache = {}
22
+ @wraps(func)
23
+ def wrapper(*args):
24
+ if args in cache:
25
+ return cache[args]
26
+ result = func(*args)
27
+ cache[args] = result
28
+ return result
29
+ return wrapper
30
+ return decorator
31
+ </q:decorator>
32
+
33
+ <!-- Decorator with parameters -->
34
+ <q:decorator name="retry" params="attempts, delay">
35
+ import time
36
+ def decorator(func):
37
+ def wrapper(*args, **kwargs):
38
+ for i in range(attempts):
39
+ try:
40
+ return func(*args, **kwargs)
41
+ except Exception as e:
42
+ if i == attempts - 1:
43
+ raise
44
+ time.sleep(delay)
45
+ return wrapper
46
+ return decorator
47
+ </q:decorator>
48
+ """
49
+
50
+ @property
51
+ def tag_names(self) -> List[str]:
52
+ return ['decorator', 'pydecorator']
53
+
54
+ def parse(self, element: ET.Element) -> PyDecoratorNode:
55
+ """Parse q:decorator element"""
56
+ name = element.get('name', '')
57
+ code = element.text or ""
58
+ code = textwrap.dedent(code).strip()
59
+
60
+ # Parse params (comma-separated)
61
+ params_str = element.get('params', '')
62
+ params = [p.strip() for p in params_str.split(',') if p.strip()]
63
+
64
+ return PyDecoratorNode(
65
+ name=name,
66
+ code=code,
67
+ params=params
68
+ )
@@ -0,0 +1,52 @@
1
+ """
2
+ PyImport Parser - Parse q:pyimport statements
3
+
4
+ Handles Python module imports.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser, ParserError
10
+ from quantum.core.ast_nodes import PyImportNode
11
+
12
+
13
+ class PyImportParser(BaseTagParser):
14
+ """
15
+ Parser for q:pyimport statements.
16
+
17
+ Supports:
18
+ - Module import with alias
19
+ - Specific name imports
20
+ - Star imports
21
+ """
22
+
23
+ @property
24
+ def tag_names(self) -> List[str]:
25
+ return ['pyimport']
26
+
27
+ def parse(self, element: ET.Element) -> PyImportNode:
28
+ """
29
+ Parse q:pyimport statement.
30
+
31
+ Args:
32
+ element: XML element for q:pyimport
33
+
34
+ Returns:
35
+ PyImportNode AST node
36
+ """
37
+ module = self.get_attr(element, 'module')
38
+
39
+ if not module:
40
+ raise ParserError("pyimport requires 'module' attribute")
41
+
42
+ # Parse names if present
43
+ names_attr = self.get_attr(element, 'names')
44
+ names = []
45
+ if names_attr:
46
+ names = [n.strip() for n in names_attr.split(',')]
47
+
48
+ return PyImportNode(
49
+ module=module,
50
+ alias=self.get_attr(element, 'as'),
51
+ names=names
52
+ )
@@ -0,0 +1,49 @@
1
+ """
2
+ Python Parser - Parse q:python statements
3
+
4
+ Handles embedded Python code.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser, ParserError
10
+ from quantum.core.ast_nodes import PythonNode
11
+
12
+
13
+ class PythonParser(BaseTagParser):
14
+ """
15
+ Parser for q:python statements.
16
+
17
+ Supports:
18
+ - Inline Python code
19
+ - Scope management
20
+ - Async execution
21
+ - Result capture
22
+ """
23
+
24
+ @property
25
+ def tag_names(self) -> List[str]:
26
+ return ['python']
27
+
28
+ def parse(self, element: ET.Element) -> PythonNode:
29
+ """
30
+ Parse q:python statement.
31
+
32
+ Args:
33
+ element: XML element for q:python
34
+
35
+ Returns:
36
+ PythonNode AST node
37
+ """
38
+ code = self.get_text(element)
39
+
40
+ if not code or not code.strip():
41
+ raise ParserError("Python block cannot be empty")
42
+
43
+ return PythonNode(
44
+ code=code,
45
+ scope=self.get_attr(element, 'scope', 'component'),
46
+ async_mode=self.get_bool_attr(element, 'async', False),
47
+ timeout=self.get_attr(element, 'timeout'),
48
+ result=self.get_attr(element, 'result')
49
+ )
@@ -0,0 +1,12 @@
1
+ """
2
+ Services Parsers
3
+
4
+ Parsers for service operations: log, dump, file, mail.
5
+ """
6
+
7
+ from .log_parser import LogParser
8
+ from .dump_parser import DumpParser
9
+ from .file_parser import FileParser
10
+ from .mail_parser import MailParser
11
+
12
+ __all__ = ['LogParser', 'DumpParser', 'FileParser', 'MailParser']
@@ -0,0 +1,52 @@
1
+ """
2
+ Dump Parser - Parse q:dump statements
3
+
4
+ Handles variable inspection and debugging.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser
10
+ from quantum.core.features.dump.src import DumpNode
11
+
12
+
13
+ class DumpParser(BaseTagParser):
14
+ """
15
+ Parser for q:dump statements.
16
+
17
+ Supports:
18
+ - Variable inspection
19
+ - Multiple output formats
20
+ - Depth control
21
+ - Conditional dumping
22
+ """
23
+
24
+ @property
25
+ def tag_names(self) -> List[str]:
26
+ return ['dump']
27
+
28
+ def parse(self, element: ET.Element) -> DumpNode:
29
+ """
30
+ Parse q:dump statement.
31
+
32
+ Args:
33
+ element: XML element for q:dump
34
+
35
+ Returns:
36
+ DumpNode AST node
37
+ """
38
+ var = self.get_attr(element, 'var', '')
39
+ label = self.get_attr(element, 'label', var)
40
+ format_type = self.get_attr(element, 'format', 'text')
41
+ depth = self.get_int_attr(element, 'depth', 3)
42
+ when = self.get_attr(element, 'when')
43
+
44
+ dump_node = DumpNode(
45
+ var=var,
46
+ label=label,
47
+ format=format_type,
48
+ depth=depth,
49
+ when=when
50
+ )
51
+
52
+ return dump_node
@@ -0,0 +1,48 @@
1
+ """
2
+ File Parser - Parse q:file statements
3
+
4
+ Handles file upload and deletion.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser, ParserError
10
+ from quantum.core.ast_nodes import FileNode
11
+
12
+
13
+ class FileParser(BaseTagParser):
14
+ """
15
+ Parser for q:file statements.
16
+
17
+ Supports:
18
+ - File upload with conflict handling
19
+ - File deletion
20
+ - Result storage
21
+ """
22
+
23
+ @property
24
+ def tag_names(self) -> List[str]:
25
+ return ['file']
26
+
27
+ def parse(self, element: ET.Element) -> FileNode:
28
+ """
29
+ Parse q:file statement.
30
+
31
+ Args:
32
+ element: XML element for q:file
33
+
34
+ Returns:
35
+ FileNode AST node
36
+ """
37
+ action = self.get_attr(element, 'action', 'upload')
38
+ file_attr = self.get_attr(element, 'file')
39
+
40
+ if not file_attr:
41
+ raise ParserError("File requires 'file' attribute")
42
+
43
+ file_node = FileNode(action, file_attr)
44
+ file_node.destination = self.get_attr(element, 'destination')
45
+ file_node.name_conflict = self.get_attr(element, 'nameConflict', 'makeUnique')
46
+ file_node.result = self.get_attr(element, 'result')
47
+
48
+ return file_node
@@ -0,0 +1,46 @@
1
+ """
2
+ Log Parser - Parse q:log statements
3
+
4
+ Handles structured logging.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser
10
+ from quantum.core.features.logging.src import LogNode
11
+
12
+
13
+ class LogParser(BaseTagParser):
14
+ """
15
+ Parser for q:log statements.
16
+
17
+ Supports:
18
+ - Log levels (debug, info, warn, error)
19
+ - Conditional logging
20
+ - Context data
21
+ - Correlation IDs
22
+ """
23
+
24
+ @property
25
+ def tag_names(self) -> List[str]:
26
+ return ['log']
27
+
28
+ def parse(self, element: ET.Element) -> LogNode:
29
+ """
30
+ Parse q:log statement.
31
+
32
+ Args:
33
+ element: XML element for q:log
34
+
35
+ Returns:
36
+ LogNode AST node
37
+ """
38
+ level = self.get_attr(element, 'level', 'info')
39
+ message = self.get_attr(element, 'message') or self.get_text(element)
40
+
41
+ log_node = LogNode(level=level, message=message)
42
+ log_node.when = self.get_attr(element, 'when')
43
+ log_node.context = self.get_attr(element, 'context')
44
+ log_node.correlation_id = self.get_attr(element, 'correlationId')
45
+
46
+ return log_node
@@ -0,0 +1,65 @@
1
+ """
2
+ Mail Parser - Parse q:mail statements
3
+
4
+ Handles email sending.
5
+ """
6
+
7
+ from typing import List
8
+ from xml.etree import ElementTree as ET
9
+ from quantum.core.parsers.base import BaseTagParser, ParserError
10
+ from quantum.core.ast_nodes import MailNode
11
+
12
+
13
+ class MailParser(BaseTagParser):
14
+ """
15
+ Parser for q:mail statements.
16
+
17
+ Supports:
18
+ - HTML and plain text emails
19
+ - CC, BCC, Reply-To
20
+ - Attachments
21
+ """
22
+
23
+ @property
24
+ def tag_names(self) -> List[str]:
25
+ return ['mail']
26
+
27
+ def parse(self, element: ET.Element) -> MailNode:
28
+ """
29
+ Parse q:mail statement.
30
+
31
+ Args:
32
+ element: XML element for q:mail
33
+
34
+ Returns:
35
+ MailNode AST node
36
+ """
37
+ to = self.get_attr(element, 'to')
38
+ subject = self.get_attr(element, 'subject')
39
+
40
+ if not to:
41
+ raise ParserError("Mail requires 'to' attribute")
42
+ if not subject:
43
+ raise ParserError("Mail requires 'subject' attribute")
44
+
45
+ mail_node = MailNode(to, subject)
46
+
47
+ # Get body from content or attribute
48
+ mail_node.body = self.get_text(element) or self.get_attr(element, 'body', '')
49
+
50
+ # Optional attributes
51
+ mail_node.from_addr = self.get_attr(element, 'from')
52
+ mail_node.cc = self.get_attr(element, 'cc')
53
+ mail_node.bcc = self.get_attr(element, 'bcc')
54
+ mail_node.reply_to = self.get_attr(element, 'replyTo')
55
+ mail_node.type = self.get_attr(element, 'type', 'html')
56
+
57
+ # Parse attachments
58
+ for child in element:
59
+ child_type = self.get_element_name(child)
60
+ if child_type == 'attachment':
61
+ attachment = self.get_attr(child, 'file')
62
+ if attachment:
63
+ mail_node.attachments.append(attachment)
64
+
65
+ return mail_node
quantum/core/tiers.py ADDED
@@ -0,0 +1,164 @@
1
+ """
2
+ Support tiers for Quantum tags.
3
+
4
+ PRODUCTION_READINESS.md Fase 0. "Production-ready" is meaningful only relative
5
+ to a defined surface, so the surface is defined here, in code, and a tag
6
+ outside the supported set announces itself the first time it is used instead
7
+ of pretending to be first-class.
8
+
9
+ The lists mirror SUPPORT_TIERS.md. When they disagree, this file is the one the
10
+ engine actually enforces, so keep it in step.
11
+ """
12
+
13
+ import logging
14
+
15
+ logger = logging.getLogger("quantum.tiers")
16
+
17
+ # Documented, tested end-to-end, stable. A break here is a critical bug.
18
+ CORE = frozenset({
19
+ "component", "param", "return", "set", "if", "loop", "function",
20
+ "query", "action", "redirect", "flash", "invoke", "data",
21
+ "import", "slot",
22
+ })
23
+
24
+ # The reason the project exists. Same contract as Core is the goal; some of it
25
+ # is still being validated end-to-end (PRODUCTION_READINESS.md Fase 4).
26
+ DIFERENCIAL = frozenset({"llm", "knowledge", "agent", "team"})
27
+
28
+ # Kept and registered, but no stability promise and not in the README. Using
29
+ # one is fine for experiments; relying on one in production is not supported.
30
+ EXPERIMENTAL = frozenset({
31
+ "job", "schedule", "thread",
32
+ "message", "queue", "subscribe", "messageAck", "messageNack",
33
+ "websocket", "websocket-send", "websocket-close",
34
+ "mail", "file", "log", "dump",
35
+ "python", "pyclass", "pyimport", "class", "decorator", "pydecorator",
36
+ "dispatchEvent", "transaction",
37
+ })
38
+
39
+ SUPPORTED = CORE | DIFERENCIAL
40
+
41
+ # Authentication is Core too (decision D4, 2026-09-10), but it is not a tag:
42
+ # it is the require_auth / require_role attributes of q:component plus the
43
+ # session scope. Listed here so the surface is complete in one place.
44
+ CORE_ATTRIBUTES = frozenset({"require_auth", "require_role"})
45
+
46
+ # Application types, by tier. A q:application's type decides which engine
47
+ # runs it, so the tier of the type is the tier of the whole app.
48
+ #
49
+ # LABORATORIO (decision D1/D2): the 2D game engine (qg:, including the Godot
50
+ # codegen) stays in the repository on purpose — games press on the language
51
+ # and surface features and bugs the core needs — but it carries no stability
52
+ # promise and is not part of the pitch. Its tests run in the main suite, so a
53
+ # core change that breaks a game shows up in CI.
54
+ LAB_APP_TYPES = frozenset({"game"})
55
+ EXPERIMENTAL_APP_TYPES = frozenset({"terminal", "ui", "testing"})
56
+
57
+ # Removed in 0.11 (APP-1), because they never worked: `quantum run` on a
58
+ # type="html" application failed at once (gap G17), and the type="api" server —
59
+ # also behind "microservices" — never executed a route's body, serving the
60
+ # literal text of the first q:return (gap G18). A web app is pages in
61
+ # components/ served by `quantum start`. "html" was also the default when
62
+ # type= was left out.
63
+ REMOVED_APP_TYPES = frozenset({"html", "api", "microservices"})
64
+
65
+
66
+ def removed_app_type_message(app_type: str, declared: bool) -> str:
67
+ what = f'type="{app_type}"' if declared else 'with no type= (it meant type="html")'
68
+ return (
69
+ f"<q:application> {what} was removed in Quantum 0.11: it never ran its "
70
+ f"routes. Build a web app as pages in components/ (components/index.q is "
71
+ f"/) and run `quantum start`. See "
72
+ f"https://danielgregorio.github.io/quantum/guide/getting-started")
73
+
74
+
75
+ def tier_of(tag_name: str) -> str:
76
+ """'core' | 'diferencial' | 'experimental' | 'unknown'."""
77
+ if tag_name in CORE:
78
+ return "core"
79
+ if tag_name in DIFERENCIAL:
80
+ return "diferencial"
81
+ if tag_name in EXPERIMENTAL:
82
+ return "experimental"
83
+ return "unknown"
84
+
85
+
86
+ # Warn once per tag per process — a q:loop over 1,000 rows must not emit 1,000
87
+ # lines, the same discipline as expression_diagnostics.
88
+ _warned: set = set()
89
+
90
+
91
+ def warn_if_unsupported(tag_name: str) -> None:
92
+ """Emit a one-time warning when an experimental tag is used.
93
+
94
+ Not an error: experimental tags still run. The point is that an operator
95
+ reading the log sees, once, that their app leans on something the project
96
+ does not promise to keep working — the audit found apps built entirely on
97
+ tags that parse and then explode, with nothing warning anyone.
98
+ """
99
+ tier = tier_of(tag_name)
100
+ if tier in ("core", "diferencial", "unknown"):
101
+ # 'unknown' is handled by the parser's own error path, not here.
102
+ return
103
+ if tag_name in _warned:
104
+ return
105
+ _warned.add(tag_name)
106
+ logger.warning(
107
+ "q:%s is EXPERIMENTAL — not covered by the production support surface "
108
+ "(SUPPORT_TIERS.md). It may change or break without notice; do not rely "
109
+ "on it in production.", tag_name
110
+ )
111
+
112
+
113
+ def app_tier_of(app_type: str) -> str:
114
+ """'laboratorio' | 'experimental' | 'supported' for a q:application type."""
115
+ if app_type in LAB_APP_TYPES:
116
+ return "laboratorio"
117
+ if app_type in EXPERIMENTAL_APP_TYPES:
118
+ return "experimental"
119
+ return "supported"
120
+
121
+
122
+ def warn_app_type(app_type: str) -> None:
123
+ """One-time warning when an application of a non-supported type runs."""
124
+ tier = app_tier_of(app_type)
125
+ key = f"application:{app_type}"
126
+ if tier == "supported" or key in _warned:
127
+ return
128
+ _warned.add(key)
129
+ if tier == "laboratorio":
130
+ logger.warning(
131
+ "q:application type=%r is LABORATÓRIO — it exists to press on the "
132
+ "language, with no stability promise (SUPPORT_TIERS.md). It may "
133
+ "change or break without notice.", app_type
134
+ )
135
+ else:
136
+ logger.warning(
137
+ "q:application type=%r is EXPERIMENTAL — not covered by the "
138
+ "supported surface (SUPPORT_TIERS.md). It may change or break "
139
+ "without notice; do not rely on it in production.", app_type
140
+ )
141
+
142
+
143
+ # UI-8: React Native translates the logic to JavaScript on its own — the
144
+ # opposite of "one runtime, many renderers" — and phones are out of 1.0. It
145
+ # stays to press on the language, like the games.
146
+ LAB_UI_TARGETS = frozenset({"mobile", "react-native"})
147
+
148
+
149
+ def warn_ui_target(target: str) -> None:
150
+ """One-time warning when a LABORATÓRIO UI target is built."""
151
+ key = f"ui-target:{target}"
152
+ if target not in LAB_UI_TARGETS or key in _warned:
153
+ return
154
+ _warned.add(key)
155
+ logger.warning(
156
+ "quantum run --target %s is LABORATÓRIO — it translates q:set and "
157
+ "q:function to JavaScript with no stability promise (SUPPORT_TIERS.md). "
158
+ "It may change or break without notice.", target
159
+ )
160
+
161
+
162
+ def reset_warnings() -> None:
163
+ """For tests, and for a reloading server."""
164
+ _warned.clear()