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,190 @@
1
+ """
2
+ Quantum CLI - Serve Command
3
+
4
+ Serve built files with a static file server.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Optional
11
+ import mimetypes
12
+
13
+ import click
14
+
15
+ from quantum.cli.utils import get_console, find_project_root
16
+
17
+
18
+ @click.command('serve')
19
+ @click.option('--port', '-p', type=int, default=8080, help='Port to serve on')
20
+ @click.option('--host', '-h', type=str, default='0.0.0.0', help='Host to bind to')
21
+ @click.option('--directory', '-d', type=click.Path(exists=True), default='./dist',
22
+ help='Directory to serve')
23
+ @click.option('--cors', is_flag=True, help='Enable CORS headers')
24
+ @click.option('--spa', is_flag=True, help='SPA mode - serve index.html for all routes')
25
+ @click.option('--quiet', '-q', is_flag=True, help='Quiet mode')
26
+ def serve(port: int, host: str, directory: str, cors: bool, spa: bool, quiet: bool):
27
+ """Serve built files with a static file server.
28
+
29
+ Serves the contents of the dist directory (or specified directory).
30
+
31
+ Examples:
32
+
33
+ quantum serve
34
+
35
+ quantum serve --port 3000
36
+
37
+ quantum serve --directory ./build --cors
38
+
39
+ quantum serve --spa # For single-page applications
40
+ """
41
+ console = get_console(quiet=quiet)
42
+
43
+ # Resolve directory path
44
+ serve_dir = Path(directory)
45
+ if not serve_dir.is_absolute():
46
+ project_root = find_project_root() or Path.cwd()
47
+ serve_dir = project_root / directory
48
+
49
+ if not serve_dir.exists():
50
+ console.error(f"Directory not found: {serve_dir}")
51
+ console.info("Run 'quantum build' first to create build output")
52
+ raise click.Abort()
53
+
54
+ # Check for index.html
55
+ index_file = serve_dir / 'index.html'
56
+ if not index_file.exists():
57
+ # Look for any .html file
58
+ html_files = list(serve_dir.glob('*.html'))
59
+ if html_files:
60
+ console.warning(f"No index.html found, but found: {', '.join(f.name for f in html_files[:3])}")
61
+ else:
62
+ console.warning("No HTML files found in directory")
63
+
64
+ url = f"http://{host if host != '0.0.0.0' else 'localhost'}:{port}"
65
+
66
+ console.header(
67
+ "Quantum Static Server",
68
+ f"Serving: {serve_dir}"
69
+ )
70
+
71
+ console.panel(
72
+ f"[bold]URL:[/bold] {url}\n"
73
+ f"[bold]Directory:[/bold] {serve_dir}\n"
74
+ f"[bold]CORS:[/bold] {'Enabled' if cors else 'Disabled'}\n"
75
+ f"[bold]SPA Mode:[/bold] {'Enabled' if spa else 'Disabled'}",
76
+ title="Server Configuration",
77
+ style="green"
78
+ )
79
+
80
+ console.print()
81
+ console.info(f"Server running at {url}")
82
+ console.print("[dim]Press Ctrl+C to stop[/dim]")
83
+ console.print()
84
+
85
+ # Start server
86
+ try:
87
+ _run_server(serve_dir, host, port, cors, spa, console)
88
+ except KeyboardInterrupt:
89
+ console.print()
90
+ console.info("Server stopped")
91
+ except Exception as e:
92
+ console.error(f"Server error: {e}")
93
+ raise click.Abort()
94
+
95
+
96
+ def _run_server(
97
+ directory: Path,
98
+ host: str,
99
+ port: int,
100
+ cors: bool,
101
+ spa: bool,
102
+ console
103
+ ):
104
+ """Run the static file server."""
105
+ from http.server import HTTPServer, SimpleHTTPRequestHandler
106
+ import urllib.parse
107
+
108
+ class QuantumHandler(SimpleHTTPRequestHandler):
109
+ """Custom handler with CORS and SPA support."""
110
+
111
+ def __init__(self, *args, **kwargs):
112
+ super().__init__(*args, directory=str(directory), **kwargs)
113
+
114
+ def log_message(self, format, *args):
115
+ """Log requests to console."""
116
+ message = format % args
117
+ # Parse status code
118
+ parts = message.split('"')
119
+ if len(parts) >= 3:
120
+ status = parts[2].strip().split()[0]
121
+ method_path = parts[1]
122
+ if status.startswith('2'):
123
+ console.print(f"[green]{status}[/green] {method_path}")
124
+ elif status.startswith('3'):
125
+ console.print(f"[yellow]{status}[/yellow] {method_path}")
126
+ elif status.startswith('4') or status.startswith('5'):
127
+ console.print(f"[red]{status}[/red] {method_path}")
128
+ else:
129
+ console.print(f"{status} {method_path}")
130
+ else:
131
+ console.print(message)
132
+
133
+ def end_headers(self):
134
+ """Add CORS headers if enabled."""
135
+ if cors:
136
+ self.send_header('Access-Control-Allow-Origin', '*')
137
+ self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
138
+ self.send_header('Access-Control-Allow-Headers', 'Content-Type')
139
+ super().end_headers()
140
+
141
+ def do_OPTIONS(self):
142
+ """Handle CORS preflight requests."""
143
+ if cors:
144
+ self.send_response(200)
145
+ self.end_headers()
146
+ else:
147
+ self.send_error(405, "Method Not Allowed")
148
+
149
+ def do_GET(self):
150
+ """Handle GET requests with SPA support."""
151
+ if spa:
152
+ # Parse the URL path
153
+ parsed = urllib.parse.urlparse(self.path)
154
+ path = parsed.path
155
+
156
+ # Check if file exists
157
+ file_path = directory / path.lstrip('/')
158
+
159
+ if not file_path.exists() and not path.startswith('/assets'):
160
+ # Check if it's a file request (has extension)
161
+ if '.' not in Path(path).name:
162
+ # Serve index.html for SPA routes
163
+ self.path = '/index.html'
164
+
165
+ super().do_GET()
166
+
167
+ def guess_type(self, path):
168
+ """Guess content type with better defaults."""
169
+ content_type, _ = mimetypes.guess_type(path)
170
+ if content_type:
171
+ return content_type
172
+
173
+ # Additional mappings
174
+ ext = Path(path).suffix.lower()
175
+ type_map = {
176
+ '.q': 'text/xml',
177
+ '.yaml': 'text/yaml',
178
+ '.yml': 'text/yaml',
179
+ '.wasm': 'application/wasm',
180
+ '.mjs': 'application/javascript',
181
+ }
182
+ return type_map.get(ext, 'application/octet-stream')
183
+
184
+ # Create and start server
185
+ server = HTTPServer((host, port), QuantumHandler)
186
+
187
+ try:
188
+ server.serve_forever()
189
+ finally:
190
+ server.server_close()
@@ -0,0 +1,193 @@
1
+ """
2
+ Quantum CLI - Test Command
3
+
4
+ Run tests for Quantum applications.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import subprocess
10
+ from pathlib import Path
11
+ from typing import Optional, List
12
+
13
+ import click
14
+
15
+ from quantum.cli.utils import get_console, find_project_root
16
+
17
+
18
+ @click.command('test')
19
+ @click.argument('path', required=False, type=click.Path())
20
+ @click.option('--pattern', '-p', type=str, default='test_*.py',
21
+ help='Test file pattern')
22
+ @click.option('--coverage', '-c', is_flag=True, help='Run with coverage')
23
+ @click.option('--verbose', '-v', is_flag=True, help='Verbose output')
24
+ @click.option('--watch', '-w', is_flag=True, help='Watch mode - rerun on changes')
25
+ @click.option('--filter', '-k', type=str, help='Filter tests by name pattern')
26
+ @click.option('--markers', '-m', type=str, help='Run tests with specific markers')
27
+ @click.option('--fail-fast', '-x', is_flag=True, help='Stop on first failure')
28
+ @click.option('--quiet', '-q', is_flag=True, help='Quiet mode')
29
+ def test(
30
+ path: Optional[str],
31
+ pattern: str,
32
+ coverage: bool,
33
+ verbose: bool,
34
+ watch: bool,
35
+ filter: Optional[str],
36
+ markers: Optional[str],
37
+ fail_fast: bool,
38
+ quiet: bool
39
+ ):
40
+ """Run tests for Quantum applications.
41
+
42
+ Uses pytest to run tests from the tests/ directory.
43
+
44
+ Examples:
45
+
46
+ quantum test
47
+
48
+ quantum test tests/unit/
49
+
50
+ quantum test --coverage
51
+
52
+ quantum test -k "test_parser" -v
53
+
54
+ quantum test --watch
55
+ """
56
+ console = get_console(quiet=quiet)
57
+
58
+ # Find project root
59
+ project_root = find_project_root()
60
+ if not project_root:
61
+ console.error("No Quantum project found")
62
+ raise click.Abort()
63
+
64
+ # Determine test path
65
+ if path:
66
+ test_path = Path(path)
67
+ if not test_path.is_absolute():
68
+ test_path = project_root / path
69
+ else:
70
+ test_path = project_root / 'tests'
71
+
72
+ if not test_path.exists():
73
+ console.error(f"Test path not found: {test_path}")
74
+ console.info("Create a 'tests/' directory with test files")
75
+ raise click.Abort()
76
+
77
+ console.header(
78
+ "Running Quantum Tests",
79
+ f"Path: {test_path}"
80
+ )
81
+
82
+ # Check for pytest
83
+ try:
84
+ subprocess.run(['pytest', '--version'], capture_output=True, check=True)
85
+ except (subprocess.CalledProcessError, FileNotFoundError):
86
+ console.error("pytest not found. Install with: pip install pytest")
87
+ raise click.Abort()
88
+
89
+ # Build pytest command
90
+ cmd = ['pytest', str(test_path)]
91
+
92
+ if verbose:
93
+ cmd.append('-v')
94
+
95
+ if fail_fast:
96
+ cmd.append('-x')
97
+
98
+ if filter:
99
+ cmd.extend(['-k', filter])
100
+
101
+ if markers:
102
+ cmd.extend(['-m', markers])
103
+
104
+ if coverage:
105
+ # Check for pytest-cov
106
+ try:
107
+ import pytest_cov
108
+ except ImportError:
109
+ console.warning("pytest-cov not found. Install with: pip install pytest-cov")
110
+ console.info("Running without coverage...")
111
+ else:
112
+ cmd.extend(['--cov=src', '--cov-report=term-missing', '--cov-report=html'])
113
+
114
+ # Add src to PYTHONPATH
115
+ env = os.environ.copy()
116
+ src_path = str(project_root / 'src')
117
+ env['PYTHONPATH'] = src_path + os.pathsep + env.get('PYTHONPATH', '')
118
+
119
+ console.info(f"Running: {' '.join(cmd)}")
120
+ console.print()
121
+
122
+ if watch:
123
+ _watch_and_test(project_root, cmd, env, console)
124
+ else:
125
+ # Run tests
126
+ result = subprocess.run(cmd, cwd=project_root, env=env)
127
+
128
+ if result.returncode == 0:
129
+ console.print()
130
+ console.success("All tests passed!")
131
+ else:
132
+ console.print()
133
+ console.error(f"Tests failed with exit code {result.returncode}")
134
+ sys.exit(result.returncode)
135
+
136
+
137
+ def _watch_and_test(project_root: Path, cmd: List[str], env: dict, console):
138
+ """Watch for changes and rerun tests."""
139
+ import time
140
+ import signal
141
+
142
+ last_mtimes = {}
143
+
144
+ def get_file_mtimes():
145
+ mtimes = {}
146
+ for ext in ['.py', '.q']:
147
+ for f in project_root.rglob(f'*{ext}'):
148
+ # Skip __pycache__
149
+ if '__pycache__' in str(f):
150
+ continue
151
+ try:
152
+ mtimes[f] = f.stat().st_mtime
153
+ except OSError:
154
+ pass
155
+ return mtimes
156
+
157
+ def run_tests():
158
+ console.print()
159
+ console.info("Running tests...")
160
+ console.print()
161
+ subprocess.run(cmd, cwd=project_root, env=env)
162
+
163
+ def signal_handler(sig, frame):
164
+ console.print()
165
+ console.info("Stopping watch mode...")
166
+ raise SystemExit(0)
167
+
168
+ signal.signal(signal.SIGINT, signal_handler)
169
+
170
+ # Initial run
171
+ run_tests()
172
+ last_mtimes = get_file_mtimes()
173
+
174
+ console.print()
175
+ console.info("Watching for changes... (Ctrl+C to stop)")
176
+
177
+ while True:
178
+ time.sleep(1)
179
+ current_mtimes = get_file_mtimes()
180
+
181
+ changed = []
182
+ for f, mtime in current_mtimes.items():
183
+ if f not in last_mtimes or mtime > last_mtimes[f]:
184
+ changed.append(f)
185
+
186
+ if changed:
187
+ console.print()
188
+ for f in changed:
189
+ rel_path = f.relative_to(project_root)
190
+ console.info(f"Changed: {rel_path}")
191
+
192
+ run_tests()
193
+ last_mtimes = current_mtimes