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,351 @@
1
+ """
2
+ Quantum Package Manifest Handler
3
+
4
+ Handles parsing and validation of quantum.yaml package manifests.
5
+
6
+ Package structure:
7
+ my-component/
8
+ ├── quantum.yaml # Package manifest
9
+ ├── src/
10
+ │ └── MyComponent.q # Component file
11
+ ├── examples/
12
+ │ └── demo.q
13
+ └── README.md
14
+ """
15
+
16
+ import os
17
+ import re
18
+ from pathlib import Path
19
+ from typing import Dict, List, Optional, Any
20
+ from dataclasses import dataclass, field
21
+
22
+ try:
23
+ import yaml
24
+ except ImportError:
25
+ yaml = None
26
+
27
+
28
+ class ManifestError(Exception):
29
+ """Error parsing or validating package manifest."""
30
+ pass
31
+
32
+
33
+ @dataclass
34
+ class PackageManifest:
35
+ """
36
+ Represents a quantum.yaml package manifest.
37
+
38
+ Attributes:
39
+ name: Package name (lowercase, alphanumeric, hyphens allowed)
40
+ version: Semantic version (e.g., "1.0.0")
41
+ description: Package description
42
+ author: Package author
43
+ license: License identifier (e.g., "MIT", "Apache-2.0")
44
+ main: Main component file path (relative to package root)
45
+ dependencies: Dict of package name -> version constraint
46
+ keywords: List of keywords for search
47
+ repository: Optional repository URL
48
+ homepage: Optional homepage URL
49
+ exports: List of exported component names
50
+ """
51
+ name: str
52
+ version: str
53
+ description: str = ""
54
+ author: str = ""
55
+ license: str = "MIT"
56
+ main: str = "src/index.q"
57
+ dependencies: Dict[str, str] = field(default_factory=dict)
58
+ keywords: List[str] = field(default_factory=list)
59
+ repository: Optional[str] = None
60
+ homepage: Optional[str] = None
61
+ exports: List[str] = field(default_factory=list)
62
+
63
+ # Internal
64
+ _path: Optional[Path] = None
65
+
66
+ @classmethod
67
+ def load(cls, manifest_path: Path) -> 'PackageManifest':
68
+ """Load manifest from quantum.yaml file."""
69
+ if yaml is None:
70
+ raise ManifestError("PyYAML not installed. Install with: pip install pyyaml")
71
+
72
+ if not manifest_path.exists():
73
+ raise ManifestError(f"Manifest not found: {manifest_path}")
74
+
75
+ try:
76
+ with open(manifest_path, 'r', encoding='utf-8') as f:
77
+ data = yaml.safe_load(f)
78
+ except yaml.YAMLError as e:
79
+ raise ManifestError(f"Invalid YAML in manifest: {e}")
80
+
81
+ if not data:
82
+ raise ManifestError("Empty manifest file")
83
+
84
+ # Validate required fields
85
+ if 'name' not in data:
86
+ raise ManifestError("Package name is required")
87
+ if 'version' not in data:
88
+ raise ManifestError("Package version is required")
89
+
90
+ # Validate name format
91
+ name = data['name']
92
+ if not cls._validate_name(name):
93
+ raise ManifestError(
94
+ f"Invalid package name: {name}. "
95
+ "Names must be lowercase, alphanumeric with hyphens allowed."
96
+ )
97
+
98
+ # Validate version format
99
+ version = data['version']
100
+ if not cls._validate_version(version):
101
+ raise ManifestError(
102
+ f"Invalid version: {version}. "
103
+ "Use semantic versioning (e.g., 1.0.0)"
104
+ )
105
+
106
+ # Parse dependencies
107
+ dependencies = {}
108
+ if 'dependencies' in data and data['dependencies']:
109
+ for dep_name, dep_version in data['dependencies'].items():
110
+ if not cls._validate_name(dep_name):
111
+ raise ManifestError(f"Invalid dependency name: {dep_name}")
112
+ if not cls._validate_version_constraint(dep_version):
113
+ raise ManifestError(f"Invalid version constraint for {dep_name}: {dep_version}")
114
+ dependencies[dep_name] = dep_version
115
+
116
+ manifest = cls(
117
+ name=name,
118
+ version=str(version),
119
+ description=data.get('description', ''),
120
+ author=data.get('author', ''),
121
+ license=data.get('license', 'MIT'),
122
+ main=data.get('main', 'src/index.q'),
123
+ dependencies=dependencies,
124
+ keywords=data.get('keywords', []) or [],
125
+ repository=data.get('repository'),
126
+ homepage=data.get('homepage'),
127
+ exports=data.get('exports', []) or [],
128
+ )
129
+ manifest._path = manifest_path.parent
130
+
131
+ return manifest
132
+
133
+ @staticmethod
134
+ def _validate_name(name: str) -> bool:
135
+ """Validate package name format."""
136
+ if not name:
137
+ return False
138
+ # lowercase, alphanumeric, hyphens allowed, must start with letter
139
+ pattern = r'^[a-z][a-z0-9-]*$'
140
+ return bool(re.match(pattern, name))
141
+
142
+ @staticmethod
143
+ def _validate_version(version: str) -> bool:
144
+ """Validate semantic version format."""
145
+ if not version:
146
+ return False
147
+ # Basic semver: major.minor.patch with optional prerelease
148
+ pattern = r'^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$'
149
+ return bool(re.match(pattern, str(version)))
150
+
151
+ @staticmethod
152
+ def _validate_version_constraint(constraint: str) -> bool:
153
+ """Validate version constraint format."""
154
+ if not constraint:
155
+ return False
156
+ # Support: exact, ^, ~, >=, >, <=, <, or ranges
157
+ patterns = [
158
+ r'^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$', # exact: 1.0.0
159
+ r'^\^?\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$', # caret: ^1.0.0
160
+ r'^~\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$', # tilde: ~1.0.0
161
+ r'^[><]=?\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$', # comparison: >=1.0.0
162
+ r'^\*$', # any version
163
+ ]
164
+ return any(re.match(p, str(constraint)) for p in patterns)
165
+
166
+ def save(self, path: Optional[Path] = None) -> None:
167
+ """Save manifest to quantum.yaml file."""
168
+ if yaml is None:
169
+ raise ManifestError("PyYAML not installed. Install with: pip install pyyaml")
170
+
171
+ target_path = path or (self._path / 'quantum.yaml' if self._path else None)
172
+ if not target_path:
173
+ raise ManifestError("No path specified for saving manifest")
174
+
175
+ if isinstance(target_path, Path) and target_path.is_dir():
176
+ target_path = target_path / 'quantum.yaml'
177
+
178
+ data = {
179
+ 'name': self.name,
180
+ 'version': self.version,
181
+ 'description': self.description,
182
+ 'author': self.author,
183
+ 'license': self.license,
184
+ 'main': self.main,
185
+ }
186
+
187
+ if self.dependencies:
188
+ data['dependencies'] = self.dependencies
189
+
190
+ if self.keywords:
191
+ data['keywords'] = self.keywords
192
+
193
+ if self.repository:
194
+ data['repository'] = self.repository
195
+
196
+ if self.homepage:
197
+ data['homepage'] = self.homepage
198
+
199
+ if self.exports:
200
+ data['exports'] = self.exports
201
+
202
+ with open(target_path, 'w', encoding='utf-8') as f:
203
+ yaml.dump(data, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
204
+
205
+ def to_dict(self) -> Dict[str, Any]:
206
+ """Convert manifest to dictionary."""
207
+ return {
208
+ 'name': self.name,
209
+ 'version': self.version,
210
+ 'description': self.description,
211
+ 'author': self.author,
212
+ 'license': self.license,
213
+ 'main': self.main,
214
+ 'dependencies': self.dependencies,
215
+ 'keywords': self.keywords,
216
+ 'repository': self.repository,
217
+ 'homepage': self.homepage,
218
+ 'exports': self.exports,
219
+ }
220
+
221
+ def get_main_component_path(self) -> Path:
222
+ """Get absolute path to main component file."""
223
+ if not self._path:
224
+ raise ManifestError("Package path not set")
225
+ return self._path / self.main
226
+
227
+ def get_component_paths(self) -> List[Path]:
228
+ """Get all component (.q) files in the package."""
229
+ if not self._path:
230
+ raise ManifestError("Package path not set")
231
+
232
+ components = []
233
+ src_dir = self._path / 'src'
234
+ if src_dir.exists():
235
+ for qfile in src_dir.rglob('*.q'):
236
+ components.append(qfile)
237
+
238
+ # Also check root if main is at root level
239
+ main_path = self.get_main_component_path()
240
+ if main_path.exists() and main_path not in components:
241
+ components.append(main_path)
242
+
243
+ return components
244
+
245
+
246
+ def init_package(
247
+ path: Path,
248
+ name: Optional[str] = None,
249
+ description: str = "",
250
+ author: str = "",
251
+ license_id: str = "MIT"
252
+ ) -> PackageManifest:
253
+ """
254
+ Initialize a new package in the given directory.
255
+
256
+ Creates:
257
+ - quantum.yaml manifest
258
+ - src/ directory with index.q
259
+ - examples/ directory
260
+ - README.md
261
+ """
262
+ if yaml is None:
263
+ raise ManifestError("PyYAML not installed. Install with: pip install pyyaml")
264
+
265
+ path = Path(path)
266
+
267
+ # Use directory name as package name if not provided
268
+ if not name:
269
+ name = path.name.lower().replace('_', '-').replace(' ', '-')
270
+ # Remove invalid characters
271
+ name = re.sub(r'[^a-z0-9-]', '', name)
272
+ if not name or not name[0].isalpha():
273
+ name = 'my-component'
274
+
275
+ # Create directories
276
+ path.mkdir(parents=True, exist_ok=True)
277
+ (path / 'src').mkdir(exist_ok=True)
278
+ (path / 'examples').mkdir(exist_ok=True)
279
+
280
+ # Create manifest
281
+ manifest = PackageManifest(
282
+ name=name,
283
+ version='1.0.0',
284
+ description=description,
285
+ author=author,
286
+ license=license_id,
287
+ main='src/index.q',
288
+ )
289
+ manifest._path = path
290
+ manifest.save()
291
+
292
+ # Create main component file
293
+ component_name = ''.join(word.capitalize() for word in name.split('-'))
294
+ main_content = f'''<q:component name="{component_name}">
295
+ <!-- Component parameters -->
296
+ <q:param name="title" type="string" default="{component_name}" />
297
+
298
+ <!-- Component template -->
299
+ <div class="{name}">
300
+ <h1>{{title}}</h1>
301
+ <q:slot />
302
+ </div>
303
+ </q:component>
304
+ '''
305
+
306
+ with open(path / 'src' / 'index.q', 'w', encoding='utf-8') as f:
307
+ f.write(main_content)
308
+
309
+ # Create example file
310
+ example_content = f'''<q:component name="Demo">
311
+ <q:import component="{component_name}" from="../src" />
312
+
313
+ <{component_name} title="Hello World">
314
+ <p>This is a demo of the {name} component.</p>
315
+ </{component_name}>
316
+ </q:component>
317
+ '''
318
+
319
+ with open(path / 'examples' / 'demo.q', 'w', encoding='utf-8') as f:
320
+ f.write(example_content)
321
+
322
+ # Create README
323
+ readme_content = f'''# {name}
324
+
325
+ {description or 'A Quantum component package.'}
326
+
327
+ ## Installation
328
+
329
+ ```bash
330
+ quantum pkg install {name}
331
+ ```
332
+
333
+ ## Usage
334
+
335
+ ```xml
336
+ <q:import component="{component_name}" from="{name}" />
337
+
338
+ <{component_name} title="Example">
339
+ <p>Content goes here</p>
340
+ </{component_name}>
341
+ ```
342
+
343
+ ## License
344
+
345
+ {license_id}
346
+ '''
347
+
348
+ with open(path / 'README.md', 'w', encoding='utf-8') as f:
349
+ f.write(readme_content)
350
+
351
+ return manifest