quantum-framework 0.13.0__tar.gz → 0.14.0__tar.gz

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 (363) hide show
  1. {quantum_framework-0.13.0/quantum_framework.egg-info → quantum_framework-0.14.0}/PKG-INFO +2 -1
  2. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/pyproject.toml +2 -1
  3. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/migrate.py +13 -1
  4. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parser.py +22 -6
  5. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/control_flow/set_parser.py +6 -1
  6. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/data/invoke_parser.py +6 -1
  7. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/functions/function_parser.py +7 -0
  8. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/functions/param_parser.py +8 -1
  9. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/component.py +28 -52
  10. quantum_framework-0.14.0/quantum/runtime/conditions.py +54 -0
  11. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/logging_setup.py +3 -2
  12. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/param_validation.py +34 -2
  13. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/renderer.py +12 -38
  14. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_builder.py +12 -7
  15. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/web_server.py +14 -7
  16. {quantum_framework-0.13.0 → quantum_framework-0.14.0/quantum_framework.egg-info}/PKG-INFO +2 -1
  17. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_framework.egg-info/SOURCES.txt +1 -1
  18. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_framework.egg-info/requires.txt +1 -0
  19. quantum_framework-0.13.0/quantum/core/features/query/src/database_service.py +0 -322
  20. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/LICENSE +0 -0
  21. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/README.md +0 -0
  22. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/__init__.py +0 -0
  23. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/__init__.py +0 -0
  24. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/admin.py +0 -0
  25. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/__init__.py +0 -0
  26. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/build.py +0 -0
  27. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/dev.py +0 -0
  28. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/docs.py +0 -0
  29. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/lint.py +0 -0
  30. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/new.py +0 -0
  31. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/serve.py +0 -0
  32. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/commands/test.py +0 -0
  33. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/deploy.py +0 -0
  34. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/hot_reload.py +0 -0
  35. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/jobs.py +0 -0
  36. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/mq.py +0 -0
  37. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/pkg.py +0 -0
  38. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/runner.py +0 -0
  39. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/server_process.py +0 -0
  40. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/cli/utils.py +0 -0
  41. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/__init__.py +0 -0
  42. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/base_generator.py +0 -0
  43. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/cli.py +0 -0
  44. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/expression_transformer.py +0 -0
  45. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/javascript/__init__.py +0 -0
  46. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/javascript/generator.py +0 -0
  47. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/optimizer.py +0 -0
  48. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/python/__init__.py +0 -0
  49. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/python/generator.py +0 -0
  50. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/python/runtime.py +0 -0
  51. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/compiler/transpiler.py +0 -0
  52. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/__init__.py +0 -0
  53. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/ast_nodes.py +0 -0
  54. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/config_env.py +0 -0
  55. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/expression_diagnostics.py +0 -0
  56. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/expression_stdlib.py +0 -0
  57. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/expressions.py +0 -0
  58. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/agents/src/__init__.py +0 -0
  59. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/agents/src/ast_node.py +0 -0
  60. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/conditionals/src/__init__.py +0 -0
  61. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/conditionals/src/ast_node.py +0 -0
  62. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/data_import/src/__init__.py +0 -0
  63. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/data_import/src/ast_node.py +0 -0
  64. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/data_import/src/runtime.py +0 -0
  65. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/dump/src/__init__.py +0 -0
  66. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/dump/src/ast_node.py +0 -0
  67. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/dump/src/parser.py +0 -0
  68. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/dump/src/runtime.py +0 -0
  69. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/functions/src/__init__.py +0 -0
  70. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/functions/src/ast_node.py +0 -0
  71. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/game_engine_2d/src/__init__.py +0 -0
  72. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/game_engine_2d/src/ast_nodes.py +0 -0
  73. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/game_engine_2d/src/parser.py +0 -0
  74. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/invocation/src/__init__.py +0 -0
  75. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/invocation/src/ast_node.py +0 -0
  76. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/invocation/src/runtime.py +0 -0
  77. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/knowledge_base/src/__init__.py +0 -0
  78. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/knowledge_base/src/ast_node.py +0 -0
  79. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/knowledge_base/src/parser.py +0 -0
  80. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/logging/src/__init__.py +0 -0
  81. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/logging/src/ast_node.py +0 -0
  82. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/logging/src/parser.py +0 -0
  83. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/logging/src/runtime.py +0 -0
  84. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/loops/src/__init__.py +0 -0
  85. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/loops/src/ast_node.py +0 -0
  86. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/query/src/__init__.py +0 -0
  87. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/query/src/query_validators.py +0 -0
  88. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/state_management/src/__init__.py +0 -0
  89. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/state_management/src/ast_node.py +0 -0
  90. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/terminal_engine/src/__init__.py +0 -0
  91. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/terminal_engine/src/ast_nodes.py +0 -0
  92. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/terminal_engine/src/parser.py +0 -0
  93. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/testing_engine/src/__init__.py +0 -0
  94. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/testing_engine/src/ast_nodes.py +0 -0
  95. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/testing_engine/src/parser.py +0 -0
  96. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/theming/src/__init__.py +0 -0
  97. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/theming/src/ast_node.py +0 -0
  98. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/theming/src/presets.py +0 -0
  99. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/ui_engine/src/__init__.py +0 -0
  100. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/ui_engine/src/ast_nodes.py +0 -0
  101. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/ui_engine/src/parser.py +0 -0
  102. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/websocket/src/__init__.py +0 -0
  103. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/features/websocket/src/ast_node.py +0 -0
  104. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/guards.py +0 -0
  105. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/html_compat.py +0 -0
  106. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parser_registry.py +0 -0
  107. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/__init__.py +0 -0
  108. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/ai/__init__.py +0 -0
  109. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/ai/agent_parser.py +0 -0
  110. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/ai/knowledge_parser.py +0 -0
  111. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/ai/llm_parser.py +0 -0
  112. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/ai/team_parser.py +0 -0
  113. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/base.py +0 -0
  114. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/composition/__init__.py +0 -0
  115. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/composition/import_parser.py +0 -0
  116. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/composition/slot_parser.py +0 -0
  117. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/control_flow/__init__.py +0 -0
  118. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/control_flow/if_parser.py +0 -0
  119. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/control_flow/loop_parser.py +0 -0
  120. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/data/__init__.py +0 -0
  121. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/data/data_parser.py +0 -0
  122. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/data/query_parser.py +0 -0
  123. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/data/transaction_parser.py +0 -0
  124. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/events/__init__.py +0 -0
  125. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/events/dispatch_event_parser.py +0 -0
  126. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/forms/__init__.py +0 -0
  127. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/forms/action_parser.py +0 -0
  128. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/forms/flash_parser.py +0 -0
  129. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/forms/redirect_parser.py +0 -0
  130. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/functions/__init__.py +0 -0
  131. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/functions/return_parser.py +0 -0
  132. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/html/__init__.py +0 -0
  133. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/html/component_call_parser.py +0 -0
  134. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/html/html_parser.py +0 -0
  135. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/jobs/__init__.py +0 -0
  136. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/jobs/job_parser.py +0 -0
  137. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/jobs/schedule_parser.py +0 -0
  138. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/jobs/thread_parser.py +0 -0
  139. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/messaging/__init__.py +0 -0
  140. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/messaging/message_ack_parser.py +0 -0
  141. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/messaging/message_nack_parser.py +0 -0
  142. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/messaging/message_parser.py +0 -0
  143. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/messaging/queue_parser.py +0 -0
  144. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/messaging/websocket_parser.py +0 -0
  145. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/persistence/__init__.py +0 -0
  146. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/persistence/persist_parser.py +0 -0
  147. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/routing/__init__.py +0 -0
  148. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/routing/route_parser.py +0 -0
  149. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/scripting/__init__.py +0 -0
  150. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/scripting/pyclass_parser.py +0 -0
  151. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/scripting/pydecorator_parser.py +0 -0
  152. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/scripting/pyimport_parser.py +0 -0
  153. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/scripting/python_parser.py +0 -0
  154. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/services/__init__.py +0 -0
  155. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/services/dump_parser.py +0 -0
  156. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/services/file_parser.py +0 -0
  157. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/services/log_parser.py +0 -0
  158. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/parsers/services/mail_parser.py +0 -0
  159. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/core/tiers.py +0 -0
  160. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/packages/__init__.py +0 -0
  161. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/packages/manager.py +0 -0
  162. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/packages/manifest.py +0 -0
  163. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/packages/registry.py +0 -0
  164. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/packages/resolver.py +0 -0
  165. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/plugins/__init__.py +0 -0
  166. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/plugins/hooks.py +0 -0
  167. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/plugins/loader.py +0 -0
  168. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/plugins/manifest.py +0 -0
  169. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/plugins/registry.py +0 -0
  170. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/__init__.py +0 -0
  171. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/action_handler.py +0 -0
  172. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/adapters/__init__.py +0 -0
  173. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/adapters/memory_adapter.py +0 -0
  174. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/adapters/rabbitmq_adapter.py +0 -0
  175. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/adapters/redis_adapter.py +0 -0
  176. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/adapters/sqlite_adapter.py +0 -0
  177. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/agent_service.py +0 -0
  178. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ast_cache.py +0 -0
  179. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/auth_service.py +0 -0
  180. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/component_composer.py +0 -0
  181. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/component_resolver.py +0 -0
  182. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/database_service.py +0 -0
  183. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/email_service.py +0 -0
  184. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/error_handler.py +0 -0
  185. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/execution_context.py +0 -0
  186. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executor_registry.py +0 -0
  187. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/__init__.py +0 -0
  188. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/ai/__init__.py +0 -0
  189. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/ai/agent_executor.py +0 -0
  190. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/ai/knowledge_executor.py +0 -0
  191. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/ai/llm_executor.py +0 -0
  192. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/ai/team_executor.py +0 -0
  193. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/base.py +0 -0
  194. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/control_flow/__init__.py +0 -0
  195. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/control_flow/if_executor.py +0 -0
  196. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/control_flow/loop_executor.py +0 -0
  197. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/control_flow/redirect_executor.py +0 -0
  198. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/control_flow/set_executor.py +0 -0
  199. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/data/__init__.py +0 -0
  200. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/data/data_executor.py +0 -0
  201. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/data/invoke_executor.py +0 -0
  202. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/data/query_executor.py +0 -0
  203. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/data/transaction_executor.py +0 -0
  204. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/jobs/__init__.py +0 -0
  205. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/jobs/job_executor.py +0 -0
  206. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/jobs/schedule_executor.py +0 -0
  207. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/jobs/thread_executor.py +0 -0
  208. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/messaging/__init__.py +0 -0
  209. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/messaging/message_ack_executor.py +0 -0
  210. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/messaging/message_executor.py +0 -0
  211. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/messaging/queue_executor.py +0 -0
  212. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/messaging/websocket_executor.py +0 -0
  213. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/scripting/__init__.py +0 -0
  214. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/scripting/pyclass_executor.py +0 -0
  215. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/scripting/pyimport_executor.py +0 -0
  216. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/scripting/python_executor.py +0 -0
  217. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/services/__init__.py +0 -0
  218. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/services/dump_executor.py +0 -0
  219. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/services/file_executor.py +0 -0
  220. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/services/log_executor.py +0 -0
  221. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/executors/services/mail_executor.py +0 -0
  222. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/expression_cache.py +0 -0
  223. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/file_upload_service.py +0 -0
  224. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/function_registry.py +0 -0
  225. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/game_builder.py +0 -0
  226. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/game_code_generator.py +0 -0
  227. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/game_templates.py +0 -0
  228. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/godot_code_generator.py +0 -0
  229. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/godot_templates.py +0 -0
  230. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/job_executor.py +0 -0
  231. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/knowledge_service.py +0 -0
  232. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/llm_cache.py +0 -0
  233. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/llm_providers.py +0 -0
  234. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/llm_service.py +0 -0
  235. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/message_broker.py +0 -0
  236. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/message_queue_service.py +0 -0
  237. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/pypy_compat.py +0 -0
  238. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/python_bridge.py +0 -0
  239. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/query_validators.py +0 -0
  240. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/service_container.py +0 -0
  241. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/terminal_builder.py +0 -0
  242. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/terminal_code_generator.py +0 -0
  243. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/terminal_templates.py +0 -0
  244. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/testing_builder.py +0 -0
  245. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/testing_code_generator.py +0 -0
  246. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/testing_templates.py +0 -0
  247. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_desktop_adapter.py +0 -0
  248. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_desktop_templates.py +0 -0
  249. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_html_adapter.py +0 -0
  250. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_html_templates.py +0 -0
  251. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_mobile_adapter.py +0 -0
  252. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_mobile_templates.py +0 -0
  253. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_textual_adapter.py +0 -0
  254. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_textual_templates.py +0 -0
  255. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_tokens.py +0 -0
  256. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/ui_validator.py +0 -0
  257. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/validators.py +0 -0
  258. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/websocket_adapter.py +0 -0
  259. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/websocket_service.py +0 -0
  260. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/websocket_transport.py +0 -0
  261. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/runtime/wsgi.py +0 -0
  262. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/services.py +0 -0
  263. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum/utils/__init__.py +0 -0
  264. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/__init__.py +0 -0
  265. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/assets/quantum-admin-connectors.js +0 -0
  266. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/assets/quantum-admin.css +0 -0
  267. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/assets/quantum-source-highlight.js +0 -0
  268. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/__init__.py +0 -0
  269. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/audit_service.py +0 -0
  270. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/auth_service.py +0 -0
  271. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/component_discovery.py +0 -0
  272. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/config_generator.py +0 -0
  273. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/connector_service.py +0 -0
  274. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/crud.py +0 -0
  275. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/database.py +0 -0
  276. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/db_setup_service.py +0 -0
  277. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/deploy_service.py +0 -0
  278. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/docker_service.py +0 -0
  279. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/environment_service.py +0 -0
  280. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/git_service.py +0 -0
  281. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/health_service.py +0 -0
  282. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/job_service.py +0 -0
  283. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/log_service.py +0 -0
  284. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/main.py +0 -0
  285. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/models.py +0 -0
  286. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/pipeline_service.py +0 -0
  287. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/resource_manager.py +0 -0
  288. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/schemas.py +0 -0
  289. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/secret_manager.py +0 -0
  290. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/settings_service.py +0 -0
  291. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/template_service.py +0 -0
  292. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/test_execution_service.py +0 -0
  293. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/test_generator.py +0 -0
  294. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/webhook_service.py +0 -0
  295. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/backend/websocket_manager.py +0 -0
  296. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/_layout/AdminShell.q +0 -0
  297. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/agents.q +0 -0
  298. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/app/[name].q +0 -0
  299. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/applications.q +0 -0
  300. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/component/[...path].q +0 -0
  301. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/components.q +0 -0
  302. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/connectors.q +0 -0
  303. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/dashboard.q +0 -0
  304. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/database.q +0 -0
  305. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/features.q +0 -0
  306. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/index.q +0 -0
  307. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/jobs.q +0 -0
  308. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/login.q +0 -0
  309. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/logout.q +0 -0
  310. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/settings.q +0 -0
  311. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/source.q +0 -0
  312. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/components/admin/tests.q +0 -0
  313. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/run.py +0 -0
  314. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/__init__.py +0 -0
  315. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/_base.py +0 -0
  316. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/_component_test_generator.py +0 -0
  317. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/_yaml_editor.py +0 -0
  318. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/apps.py +0 -0
  319. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/auth.py +0 -0
  320. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/components.py +0 -0
  321. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/connectors.py +0 -0
  322. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/projects.py +0 -0
  323. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/repository.py +0 -0
  324. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/settings.py +0 -0
  325. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_admin/services/yaml_import.py +0 -0
  326. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_framework.egg-info/dependency_links.txt +0 -0
  327. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_framework.egg-info/entry_points.txt +0 -0
  328. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/quantum_framework.egg-info/top_level.txt +0 -0
  329. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/setup.cfg +0 -0
  330. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_agent.py +0 -0
  331. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_animations.py +0 -0
  332. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_ast_cache.py +0 -0
  333. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_cli_commands.py +0 -0
  334. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_component_library.py +0 -0
  335. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_desktop_bridge.py +0 -0
  336. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_expression_cache.py +0 -0
  337. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_form_validation.py +0 -0
  338. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_game_codegen.py +0 -0
  339. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_game_e2e.py +0 -0
  340. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_game_engine.py +0 -0
  341. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_game_parser.py +0 -0
  342. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_godot_codegen.py +0 -0
  343. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_job_executor.py +0 -0
  344. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_llm_providers.py +0 -0
  345. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_message_broker.py +0 -0
  346. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_message_queue.py +0 -0
  347. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_mobile_target.py +0 -0
  348. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_multi_agent.py +0 -0
  349. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_packages.py +0 -0
  350. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_plugins.py +0 -0
  351. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_pypy_compat.py +0 -0
  352. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_python_scripting.py +0 -0
  353. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_state_persistence.py +0 -0
  354. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_terminal_codegen.py +0 -0
  355. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_terminal_parser.py +0 -0
  356. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_testing_codegen.py +0 -0
  357. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_testing_parser.py +0 -0
  358. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_theming.py +0 -0
  359. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_ui_html_adapter.py +0 -0
  360. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_ui_parity.py +0 -0
  361. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_ui_parser.py +0 -0
  362. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_ui_textual_adapter.py +0 -0
  363. {quantum_framework-0.13.0 → quantum_framework-0.14.0}/tests/test_websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantum-framework
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Summary: Full-stack declarative framework for building web, desktop, and mobile applications
5
5
  Author-email: Daniel Gregorio <danielgregorio2611@gmail.com>
6
6
  License: MIT
@@ -28,6 +28,7 @@ Provides-Extra: dev
28
28
  Requires-Dist: pytest>=7.4.0; extra == "dev"
29
29
  Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
30
30
  Requires-Dist: pytest-mock>=3.11.1; extra == "dev"
31
+ Requires-Dist: pytest-xdist>=3.5; extra == "dev"
31
32
  Requires-Dist: black>=23.0.0; extra == "dev"
32
33
  Requires-Dist: ruff>=0.1.0; extra == "dev"
33
34
  Provides-Extra: db
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quantum-framework"
7
- version = "0.13.0"
7
+ version = "0.14.0"
8
8
  description = "Full-stack declarative framework for building web, desktop, and mobile applications"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -35,6 +35,7 @@ dev = [
35
35
  "pytest>=7.4.0",
36
36
  "pytest-cov>=4.1.0",
37
37
  "pytest-mock>=3.11.1",
38
+ "pytest-xdist>=3.5",
38
39
  "black>=23.0.0",
39
40
  "ruff>=0.1.0",
40
41
  ]
@@ -167,6 +167,18 @@ class DatabaseConnection:
167
167
  self._conn.close()
168
168
 
169
169
 
170
+ def _paths_migrations(project_path: Path) -> str:
171
+ """CFG-3: paths.migrations in quantum.config.yaml (default ./migrations)."""
172
+ try:
173
+ import yaml
174
+ from quantum.core.config_env import expand_env
175
+ with open(project_path / "quantum.config.yaml", encoding="utf-8") as f:
176
+ config = expand_env(yaml.safe_load(f) or {})
177
+ return (config.get("paths") or {}).get("migrations") or "migrations"
178
+ except (OSError, ValueError, AttributeError):
179
+ return "migrations"
180
+
181
+
170
182
  class MigrationRunner:
171
183
  """Runs database migrations"""
172
184
 
@@ -174,7 +186,7 @@ class MigrationRunner:
174
186
 
175
187
  def __init__(self, project_path: Path = None, datasource: str = None):
176
188
  self.project_path = project_path or Path.cwd()
177
- self.migrations_dir = self.project_path / "migrations"
189
+ self.migrations_dir = self.project_path / _paths_migrations(self.project_path)
178
190
  self.db = DatabaseConnection(self.project_path, datasource)
179
191
 
180
192
  def _ensure_migrations_table(self):
@@ -575,10 +575,12 @@ class QuantumParser:
575
575
 
576
576
  # Parse component-level attributes
577
577
  component.port = root.get('port')
578
- component.base_path = root.get('basePath')
579
- component.health_endpoint = root.get('health')
580
- component.metrics_provider = root.get('metrics')
581
- component.trace_provider = root.get('trace')
578
+ # A2: accepted and never read by anything — refused, like FN-2/DB-5.
579
+ for attr in ('basePath', 'health', 'metrics', 'trace'):
580
+ if root.get(attr) is not None:
581
+ raise QuantumParseError(
582
+ f'<q:component name="{name}"> {attr}= is not supported: it was accepted '
583
+ f'and never did anything.')
582
584
 
583
585
  # Phase G: Authentication & Security attributes
584
586
  require_auth_attr = root.get('require_auth', 'false').lower()
@@ -867,7 +869,14 @@ class QuantumParser:
867
869
 
868
870
  if self._is_html_element(element):
869
871
  if self._parser_registry.html_parser.can_parse(element_type):
870
- return self._parser_registry.html_parser.parse(element)
872
+ node = self._parser_registry.html_parser.parse(element)
873
+ # UI-0: a ui:* element inside a page. Parsed as before
874
+ # (examples and tests load these files), but flagged so the
875
+ # renderer refuses it instead of emitting <window>/<vbox>,
876
+ # which no browser lays out.
877
+ if self._get_element_ui_namespace(element) == 'ui':
878
+ node.ui_tag = element_type
879
+ return node
871
880
 
872
881
  # PARSE-1: a q: tag nobody parses is an error. It used to return
873
882
  # None here and vanish — <q:sett>, <q:retrun> and <q:iff> ran as if
@@ -1235,9 +1244,16 @@ class QuantumParser:
1235
1244
  type=element.get('type', 'string'),
1236
1245
  required=element.get('required', 'false').lower() == 'true',
1237
1246
  default=element.get('default'),
1238
- validation=element.get('validation'),
1239
1247
  description=element.get('description')
1240
1248
  )
1249
+ if element.get('validation') is not None:
1250
+ # A2: accepted and never read. The rules are validate=, type=,
1251
+ # pattern=, min/max, minlength/maxlength and enum=.
1252
+ from quantum.core.parser import QuantumParseError
1253
+ raise QuantumParseError(
1254
+ f'<q:param name="{element.get("name", "")}"> validation= is not supported: it was '
1255
+ f'accepted and never did anything. Use type=, pattern=, min/max, '
1256
+ f'minlength/maxlength or enum=.')
1241
1257
 
1242
1258
  # REST-specific
1243
1259
  param.source = element.get('source', 'auto')
@@ -53,7 +53,12 @@ class SetParser(BaseTagParser):
53
53
  set_node.nullable = self.get_bool_attr(element, 'nullable', True)
54
54
  set_node.validate_rule = self.get_attr(element, 'validate')
55
55
  set_node.pattern = self.get_attr(element, 'pattern')
56
- set_node.mask = self.get_attr(element, 'mask')
56
+ if element.get('mask') is not None:
57
+ # A2: accepted and never applied.
58
+ from quantum.core.parser import QuantumParseError
59
+ raise QuantumParseError(
60
+ f'<q:set name="{set_node.name}"> mask= is not supported: it was accepted and '
61
+ f'never did anything. To validate a format use pattern=.')
57
62
  set_node.range = self.get_attr(element, 'range')
58
63
  set_node.enum = self.get_attr(element, 'enum')
59
64
  set_node.unique = self.get_attr(element, 'unique')
@@ -70,7 +70,12 @@ class InvokeParser(BaseTagParser):
70
70
 
71
71
  # Response handling
72
72
  invoke_node.response_format = self.get_attr(element, 'responseFormat', 'auto')
73
- invoke_node.transform = self.get_attr(element, 'transform')
73
+ if element.get('transform') is not None:
74
+ # A2: accepted and never applied.
75
+ from quantum.core.parser import QuantumParseError
76
+ raise QuantumParseError(
77
+ f'<q:invoke name="{invoke_node.name}"> transform= is not supported: it was '
78
+ f'accepted and never did anything. Transform the result with q:set.')
74
79
  invoke_node.cache = self.get_bool_attr(element, 'cache', False)
75
80
  invoke_node.ttl = self.get_int_attr(element, 'ttl', 0) or None
76
81
  invoke_node.result = self.get_attr(element, 'result')
@@ -65,6 +65,13 @@ class FunctionParser(BaseTagParser):
65
65
 
66
66
  # Core attributes
67
67
  func_node.return_type = element.get('returnType', 'any')
68
+ # FN-4: returnType is checked on every return (see ComponentRuntime).
69
+ from quantum.runtime.param_validation import RETURN_TYPES
70
+ if func_node.return_type.lower() not in RETURN_TYPES:
71
+ from quantum.core.parser import QuantumParseError
72
+ raise QuantumParseError(
73
+ f'<q:function name="{name}"> returnType="{func_node.return_type}" is not a type; '
74
+ f'use one of: {", ".join(sorted(RETURN_TYPES))}')
68
75
  func_node.description = element.get('description')
69
76
  func_node.hint = element.get('hint')
70
77
 
@@ -29,9 +29,16 @@ class ParamParser(BaseTagParser):
29
29
  type=element.get('type', 'string'),
30
30
  required=element.get('required', 'false').lower() == 'true',
31
31
  default=element.get('default'),
32
- validation=element.get('validation'),
33
32
  description=element.get('description')
34
33
  )
34
+ if element.get('validation') is not None:
35
+ # A2: accepted and never read. The rules are validate=, type=,
36
+ # pattern=, min/max, minlength/maxlength and enum=.
37
+ from quantum.core.parser import QuantumParseError
38
+ raise QuantumParseError(
39
+ f'<q:param name="{element.get("name", "")}"> validation= is not supported: it was '
40
+ f'accepted and never did anything. Use type=, pattern=, min/max, '
41
+ f'minlength/maxlength or enum=.')
35
42
 
36
43
  # REST-specific
37
44
  param.source = element.get('source', 'auto')
@@ -68,6 +68,7 @@ from quantum.runtime.executors.control_flow.loop_executor import (
68
68
  as_return_value, produced_return,
69
69
  )
70
70
  from quantum.runtime.service_container import ServiceContainer
71
+ from quantum.runtime.conditions import evaluate_condition
71
72
  import re
72
73
  import logging
73
74
 
@@ -462,57 +463,8 @@ class ComponentRuntime:
462
463
  return None
463
464
 
464
465
  def _evaluate_condition(self, condition: str, context: Dict[str, Any], guard: bool = False) -> bool:
465
- """Evaluate a condition string using databinding"""
466
- if not condition:
467
- return False
468
-
469
- # Evaluate the condition as an expression, without interpolating any
470
- # values into it first. Stripping the braces leaves the variable NAMES
471
- # in place for the evaluator to resolve, so no value is ever parsed as
472
- # syntax — unlike the databinding-then-evaluate path below, which
473
- # assembles code out of data. Same change as HTMLRenderer.
474
- stripped = self._databinding_pattern.sub(lambda m: m.group(1), condition).strip()
475
-
476
- # IF-2: `1` and `{1}` are the number 1, true. There used to be a
477
- # regex-quantifier check here that made every such condition false;
478
- # a condition is never a regex, and HTMLRenderer never had the check.
479
- try:
480
- return bool(self._expressions.evaluate(stripped, context or {}, absent_scope_key_is_none=True))
481
- except UndefinedError as exc:
482
- if guard:
483
- # AUTH-6: a guard decides whether the page (and its actions)
484
- # may run. Reading a failure as false lets everything through,
485
- # so in a guard it is an error: the page fails closed.
486
- raise ExpressionError(
487
- f"guard condition {condition!r} could not be evaluated: {exc}. A guard "
488
- f"must decide; test each part first, e.g. "
489
- f"`not session.user or not session.user.is_admin`") from exc
490
- # EXPR-5: a condition is a presence test. A name, key or attribute
491
- # that does not exist makes it FALSE (never true, see below).
492
- # Anything else — a syntax error, a function that does not exist —
493
- # propagates as an error: reading those as false is how
494
- # `age >= 18 && ok` took the else branch for every input.
495
- #
496
- #
497
- # It used to fall through to a chain that interpolated the variable
498
- # VALUES into the text and took the truthiness of the result. For a
499
- # condition like `session.user.is_admin` on a logged-out request
500
- # that produced the literal string 'session.user.is_admin', which
501
- # is non-empty and therefore truthy — so the q:if fired its admin
502
- # branch and its q:else never did. A condition failing open is an
503
- # authorization bypass by construction. Reported by two audit
504
- # dimensions, reproduced directly, and the same fix as HTMLRenderer.
505
- #
506
- # That fallback chain also fed ExpressionCache's compile()+eval(),
507
- # whose regex denylist is bypassable by splitting a dunder across
508
- # adjacent string literals — so removing it closes a latent RCE
509
- # path as well as the fail-open.
510
- report_unresolved(stripped, ExpressionError(
511
- f"condition {condition!r} could not be evaluated; treated as false"
512
- ))
513
- return False
514
- except ExpressionError as exc:
515
- raise ExpressionError(f"condition {condition!r} could not be evaluated: {exc}") from exc
466
+ """A condition by the language's rules — see quantum/runtime/conditions.py."""
467
+ return evaluate_condition(self._expressions, condition, context, guard=guard)
516
468
 
517
469
  def _apply_databinding(self, text: str, context: Dict[str, Any]) -> Any:
518
470
  """Apply variable databinding to text using {variable} syntax.
@@ -839,7 +791,31 @@ class ComponentRuntime:
839
791
  finally:
840
792
  self.execution_context = previous_context
841
793
 
842
- return as_return_value(result)
794
+ return self._check_return_type(func_node, as_return_value(result))
795
+
796
+ def _check_return_type(self, func_node: FunctionNode, valor: Any) -> Any:
797
+ """FN-4: the value a q:function returns matches its returnType.
798
+
799
+ returnType= was accepted and never read: returnType="number" returned
800
+ whatever the body produced.
801
+ """
802
+ tipo = (getattr(func_node, 'return_type', None) or 'any').lower()
803
+ if tipo == 'any':
804
+ return valor
805
+ if tipo == 'void':
806
+ if valor is not None:
807
+ raise ComponentExecutionError(
808
+ f'q:function "{func_node.name}" declares returnType="void" but returned {valor!r}')
809
+ return valor
810
+ if valor is None:
811
+ raise ComponentExecutionError(
812
+ f'q:function "{func_node.name}" declares returnType="{tipo}" but returned nothing')
813
+ from types import SimpleNamespace
814
+ convertido, erro = param_validation.coerce(SimpleNamespace(type=tipo, name=func_node.name), valor)
815
+ if erro:
816
+ raise ComponentExecutionError(
817
+ f'q:function "{func_node.name}" declares returnType="{tipo}" but returned {valor!r}')
818
+ return convertido
843
819
 
844
820
  def _validate_function_args(self, func_node: FunctionNode, args: Dict[str, Any], only=None):
845
821
  """validate=/range=/enum= rules of the q:param (QuantumValidators)."""
@@ -0,0 +1,54 @@
1
+ """The one place a `condition` is evaluated (q:if, q:elseif, guards).
2
+
3
+ ComponentRuntime (statements) and HTMLRenderer (markup) each had their own
4
+ copy of this function. They drifted: IF-2 (`condition="1"` was false) existed
5
+ in one and not the other. Both call this now.
6
+ """
7
+
8
+ import re
9
+ from typing import Any, Dict
10
+
11
+ from quantum.core.expression_diagnostics import report_unresolved
12
+ from quantum.core.expressions import ExpressionError, ExpressionEvaluator, UndefinedError
13
+
14
+ _BRACES = re.compile(r'\{([^}]+)\}')
15
+
16
+
17
+ def evaluate_condition(evaluator: ExpressionEvaluator, condition: str,
18
+ variables: Dict[str, Any], guard: bool = False) -> bool:
19
+ """True or False for a condition, by the rules of SPEC IF-2, EXPR-5, EXPR-8, AUTH-6.
20
+
21
+ The condition is evaluated as an expression with the braces stripped:
22
+ the variable NAMES stay in place for the evaluator to resolve, so no
23
+ value is ever parsed as syntax. (It used to interpolate the values into
24
+ the text and eval() the result — code assembled out of data; a record
25
+ named "'; __import__(...)" became executable. PUBLIC_RELEASE_PLAN P0.1.)
26
+ """
27
+ if not condition:
28
+ return False
29
+ stripped = _BRACES.sub(lambda m: m.group(1), condition).strip()
30
+ try:
31
+ # EXPR-8: a key a scope does not have (session.userId before login)
32
+ # is None here, so `not session.authenticated` is true for a visitor.
33
+ return bool(evaluator.evaluate(stripped, variables or {}, absent_scope_key_is_none=True))
34
+ except UndefinedError as exc:
35
+ if guard:
36
+ # AUTH-6: a guard decides whether the page and its actions run.
37
+ # Reading a failure as false would let everything through, so in
38
+ # a guard it is an error: the page fails closed.
39
+ raise ExpressionError(
40
+ f"guard condition {condition!r} could not be evaluated: {exc}. A guard "
41
+ f"must decide; test each part first, e.g. "
42
+ f"`not session.user or not session.user.is_admin`") from exc
43
+ # EXPR-5: a condition is a presence test — a missing name, key or
44
+ # attribute makes it FALSE, never true. Before, the literal
45
+ # placeholder 'session.user.is_admin' came back as a non-empty string,
46
+ # read as true: the admin branch rendered for a logged-out visitor.
47
+ report_unresolved(stripped, ExpressionError(
48
+ f"condition {condition!r} could not be evaluated; treated as false"))
49
+ return False
50
+ except ExpressionError as exc:
51
+ # A syntax error or a function that does not exist is an error:
52
+ # reading it as false is how `age >= 18 && ok` took the else branch
53
+ # for every input.
54
+ raise ExpressionError(f"condition {condition!r} could not be evaluated: {exc}") from exc
@@ -84,14 +84,15 @@ def setup_logging(config: Dict[str, Any]) -> logging.Logger:
84
84
  logger.handlers.clear()
85
85
 
86
86
  datefmt = '%Y-%m-%d %H:%M:%S'
87
- plain_fmt = '%(asctime)s %(levelname)-8s %(name)s - %(message)s'
87
+ # CFG-3: logging.format was documented here and never read.
88
+ plain_fmt = log_config.get('format') or '%(asctime)s %(levelname)-8s %(name)s - %(message)s'
88
89
 
89
90
  # Console handler with color support
90
91
  if enable_console:
91
92
  console_handler = logging.StreamHandler(sys.stderr)
92
93
  console_handler.setLevel(level)
93
94
  use_color = _supports_color()
94
- colored_fmt = '%(asctime)s %(levelname)s %(name)s - %(message)s'
95
+ colored_fmt = log_config.get('format') or '%(asctime)s %(levelname)s %(name)s - %(message)s'
95
96
  formatter = ColoredFormatter(colored_fmt, datefmt=datefmt, use_color=use_color)
96
97
  console_handler.setFormatter(formatter)
97
98
  logger.addHandler(console_handler)
@@ -45,6 +45,9 @@ FILE_TYPES = ('file', 'binary', 'upload')
45
45
  # receber como veio.
46
46
  PASSTHROUGH_TYPES = ('string', 'text', 'array', 'object', 'any', 'json')
47
47
 
48
+ # FN-4: what q:function returnType= accepts ('void': returns nothing).
49
+ RETURN_TYPES = frozenset(INT_TYPES + FLOAT_TYPES + PASSTHROUGH_TYPES + ('boolean', 'email', 'url', 'void'))
50
+
48
51
  _EMAIL = re.compile(r'^[^@\s]+@[^@\s]+\.[^@\s]+$')
49
52
  _URL = re.compile(r'^https?://', re.IGNORECASE)
50
53
 
@@ -128,9 +131,13 @@ def check_rules(param_def, value: Any) -> List[str]:
128
131
  errors: List[str] = []
129
132
  name = getattr(param_def, 'name', '?')
130
133
 
131
- # Nada de comprimento, faixa ou padrao faz sentido sobre um arquivo; as
132
- # regras de upload sao maxsize/accept, que o q:file aplica.
134
+ # Nada de comprimento, faixa ou padrao faz sentido sobre um arquivo. O que
135
+ # vale para um upload e accept= (ACT-11).
133
136
  if is_uploaded_file(value):
137
+ accept = getattr(param_def, 'accept', None)
138
+ if accept and not accepts_file(value, accept):
139
+ errors.append(f"Parameter '{name}' accepts {accept}; got "
140
+ f"'{getattr(value, 'filename', '')}'")
134
141
  return errors
135
142
 
136
143
  minimo = getattr(param_def, 'min', None)
@@ -184,3 +191,28 @@ def check_rules(param_def, value: Any) -> List[str]:
184
191
  f"Parameter '{name}' must be one of: {', '.join(allowed)}")
185
192
 
186
193
  return errors
194
+
195
+
196
+ def accepts_file(upload, accept: str) -> bool:
197
+ """ACT-11: does an upload match an HTML-style accept list (".pdf", "image/*")?
198
+
199
+ The Content-Type an upload declares comes from the browser, so a MIME
200
+ pattern is matched against the type the FILE NAME implies as well: an
201
+ .exe sent as image/png does not pass image/*. An extension pattern is
202
+ matched against the file name.
203
+ """
204
+ import mimetypes
205
+ nome = (getattr(upload, 'filename', '') or '').lower()
206
+ pelo_nome = (mimetypes.guess_type(nome)[0] or '').lower()
207
+ declarado = (getattr(upload, 'content_type', '') or '').split(';')[0].strip().lower()
208
+ for item in (a.strip().lower() for a in accept.split(',') if a.strip()):
209
+ if item.startswith('.'):
210
+ if nome.endswith(item):
211
+ return True
212
+ elif item.endswith('/*'):
213
+ base = item[:-1]
214
+ if pelo_nome.startswith(base) and (not declarado or declarado.startswith(base)):
215
+ return True
216
+ elif pelo_nome == item and (not declarado or declarado == item):
217
+ return True
218
+ return False
@@ -27,6 +27,7 @@ from quantum.core.features.conditionals.src.ast_node import IfNode
27
27
  from quantum.core.features.loops.src.ast_node import LoopNode
28
28
  from quantum.core.features.state_management.src.ast_node import SetNode
29
29
  from quantum.runtime.execution_context import ExecutionContext
30
+ from quantum.runtime.conditions import evaluate_condition
30
31
 
31
32
  logger = logging.getLogger('quantum.renderer')
32
33
 
@@ -163,6 +164,15 @@ class HTMLRenderer:
163
164
  Returns:
164
165
  HTML string
165
166
  """
167
+ ui_tag = getattr(node, 'ui_tag', None)
168
+ if ui_tag:
169
+ # UI-0: until 0.15, ui:* is compiled from <q:application type="ui">
170
+ # (quantum run app.q --target html|textual|desktop). Served inside a
171
+ # page it came out as <window>/<vbox> tags no browser lays out.
172
+ raise ValueError(
173
+ f"<ui:{ui_tag}> cannot be used inside a page yet: ui:* elements are "
174
+ f"compiled from <q:application type=\"ui\"> with `quantum run app.q "
175
+ f"--target html`. Using them inside pages arrives in Quantum 0.15.")
166
176
 
167
177
  # Build opening tag
168
178
  tag_parts = [f'<{node.tag}']
@@ -422,44 +432,8 @@ class HTMLRenderer:
422
432
  return ''
423
433
 
424
434
  def _evaluate_condition(self, condition: str) -> bool:
425
- """Evaluate a condition expression."""
426
- if not condition:
427
- return False
428
-
429
- # Evaluate the condition as an expression, without interpolating any
430
- # values into it first.
431
- #
432
- # This used to build a string by substituting databinding results into
433
- # the condition and then eval() it. That is not a comparison, it is
434
- # code assembly from data: a record whose name is "'; __import__(...)"
435
- # became executable code. Stripping the braces instead leaves the
436
- # variable NAMES in place and lets the evaluator resolve them, so no
437
- # value is ever parsed as syntax. PUBLIC_RELEASE_PLAN.md P0.1.
438
- stripped = re.sub(r'\{([^}]+)\}', r'\1', condition).strip()
439
- try:
440
- return bool(self._expressions.evaluate(
441
- stripped, self.context.get_all_variables(), absent_scope_key_is_none=True
442
- ))
443
- except UndefinedError:
444
- # EXPR-5: a missing name, key or attribute makes a condition FALSE,
445
- # not true. Other failures raise (see ComponentRuntime).
446
- #
447
- #
448
- # This used to fall through to _apply_databinding, which hands back
449
- # the literal placeholder '{session.user.is_admin}' — a non-empty
450
- # string, which the truthiness rule below then read as True. So
451
- # <q:if condition="session.user.is_admin">
452
- # rendered its admin branch for a logged-out visitor whose session
453
- # had no `user`, and every q:else guarding it never fired. A
454
- # condition failing open is an authorization bypass by
455
- # construction. Reported by two audit dimensions, reproduced
456
- # directly. See tests/integration/test_condition_fails_closed.py.
457
- report_unresolved(stripped, ExpressionError(
458
- f"condition {condition!r} could not be evaluated; treated as false"
459
- ))
460
- return False
461
- except ExpressionError as exc:
462
- raise ExpressionError(f"condition {condition!r} could not be evaluated: {exc}") from exc
435
+ """A condition by the language's rules — see quantum/runtime/conditions.py."""
436
+ return evaluate_condition(self._expressions, condition, self.context.get_all_variables())
463
437
 
464
438
  def _render_comment(self, node: CommentNode) -> str:
465
439
  """
@@ -44,6 +44,13 @@ class UIBuilder:
44
44
  Returns:
45
45
  Generated source code string.
46
46
  """
47
+ if not isinstance(app, ApplicationNode) or getattr(app, 'app_type', None) != 'ui':
48
+ # UI-0: it used to fail with "'ComponentNode' object has no
49
+ # attribute 'app_id'".
50
+ raise UIBuildError(
51
+ 'a UI build needs <q:application type="ui">; this file is a '
52
+ f'<q:{"component" if not isinstance(app, ApplicationNode) else "application"}>. '
53
+ 'Wrap the ui:window in <q:application id="MyApp" type="ui">.')
47
54
  windows = getattr(app, 'ui_windows', [])
48
55
  ui_children = getattr(app, 'ui_children', [])
49
56
  title = app.app_id or 'Quantum UI'
@@ -97,13 +104,11 @@ class UIBuilder:
97
104
  code = self.build(app, target)
98
105
 
99
106
  if output_path is None:
100
- if target == 'html':
101
- ext = '.html'
102
- elif target in ('mobile', 'react-native'):
103
- ext = '.js'
104
- else:
105
- ext = '.py'
106
- output_path = f"{app.app_id}{ext}"
107
+ # UI-0: one file per target. textual and desktop both wrote
108
+ # <id>.py, so building one erased the other.
109
+ sufixo = {'html': '.html', 'textual': '_console.py', 'desktop': '_desktop.py',
110
+ 'mobile': '.js', 'react-native': '.js'}.get(target, '.py')
111
+ output_path = f"{app.app_id}{sufixo}"
107
112
 
108
113
  path = Path(output_path)
109
114
  path.parent.mkdir(parents=True, exist_ok=True)
@@ -74,6 +74,9 @@ _KNOWN_KEYS = {
74
74
  'security': {'secret_key', 'login_url', 'python_scripting', 'max_content_length',
75
75
  'xss_protection'},
76
76
  'performance': {'cache_templates', 'cache_ttl', 'cache_max_size'},
77
+ 'server': {'port', 'host', 'debug', 'reload'},
78
+ 'paths': {'components', 'static', 'logs', 'uploads', 'migrations'},
79
+ 'logging': {'level', 'format', 'console', 'file', 'filename'},
77
80
  }
78
81
 
79
82
  _DATASOURCE_KEYS = {'driver', 'type', 'database', 'host', 'port', 'username', 'user', 'password'}
@@ -220,11 +223,9 @@ class QuantumWebServer:
220
223
 
221
224
  self.parser = QuantumParser()
222
225
  self.template_cache: Dict[str, Any] = {} # AST cache
223
- # The runtime that executes q:action bodies needs the same config as
224
- # the page render. Built with no config, it could not see the
225
- # datasources declared in quantum.config.yaml: every q:query inside a
226
- # q:action failed with "Datasource 'db' is not declared locally" —
227
- # a form that writes to the database did not work at all.
226
+ # Flash helpers only (read/set the flash in the session). q:action
227
+ # bodies run in a runtime built for each request (ACT-10), never in a
228
+ # shared one.
228
229
  self.action_handler = ActionHandler(ComponentRuntime(config=self.config))
229
230
 
230
231
  # Phase F: Application scope (global state shared across all users)
@@ -620,9 +621,15 @@ class QuantumWebServer:
620
621
  return self._page_redirect(r, guard_runtime)
621
622
  session['quantum_session'] = guard_runtime.execution_context.session_vars
622
623
 
623
- # Handle action
624
+ # Handle action — in THIS request's runtime (ACT-10). It
625
+ # used to run in one ComponentRuntime shared by every
626
+ # request and thread, which never registered the page's
627
+ # q:functions: calling one inside an action was a 500.
628
+ # guard_runtime has entered this component with this
629
+ # request's scopes.
624
630
  try:
625
- redirect_url, status_code = self.action_handler.handle_action(action_node, route_params=path_params)
631
+ redirect_url, status_code = ActionHandler(guard_runtime).handle_action(
632
+ action_node, route_params=path_params)
626
633
  except PageRedirect as r:
627
634
  # q:redirect reached through a q:function or q:loop in the action
628
635
  return self._page_redirect(r)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantum-framework
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Summary: Full-stack declarative framework for building web, desktop, and mobile applications
5
5
  Author-email: Daniel Gregorio <danielgregorio2611@gmail.com>
6
6
  License: MIT
@@ -28,6 +28,7 @@ Provides-Extra: dev
28
28
  Requires-Dist: pytest>=7.4.0; extra == "dev"
29
29
  Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
30
30
  Requires-Dist: pytest-mock>=3.11.1; extra == "dev"
31
+ Requires-Dist: pytest-xdist>=3.5; extra == "dev"
31
32
  Requires-Dist: black>=23.0.0; extra == "dev"
32
33
  Requires-Dist: ruff>=0.1.0; extra == "dev"
33
34
  Provides-Extra: db
@@ -73,7 +73,6 @@ quantum/core/features/logging/src/runtime.py
73
73
  quantum/core/features/loops/src/__init__.py
74
74
  quantum/core/features/loops/src/ast_node.py
75
75
  quantum/core/features/query/src/__init__.py
76
- quantum/core/features/query/src/database_service.py
77
76
  quantum/core/features/query/src/query_validators.py
78
77
  quantum/core/features/state_management/src/__init__.py
79
78
  quantum/core/features/state_management/src/ast_node.py
@@ -165,6 +164,7 @@ quantum/runtime/auth_service.py
165
164
  quantum/runtime/component.py
166
165
  quantum/runtime/component_composer.py
167
166
  quantum/runtime/component_resolver.py
167
+ quantum/runtime/conditions.py
168
168
  quantum/runtime/database_service.py
169
169
  quantum/runtime/email_service.py
170
170
  quantum/runtime/error_handler.py
@@ -19,6 +19,7 @@ pymysql>=1.1.0
19
19
  pytest>=7.4.0
20
20
  pytest-cov>=4.1.0
21
21
  pytest-mock>=3.11.1
22
+ pytest-xdist>=3.5
22
23
  black>=23.0.0
23
24
  ruff>=0.1.0
24
25