quantum-framework 0.15.0__tar.gz → 0.16.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 (368) hide show
  1. {quantum_framework-0.15.0/quantum_framework.egg-info → quantum_framework-0.16.0}/PKG-INFO +3 -1
  2. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/pyproject.toml +5 -1
  3. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/build.py +4 -7
  4. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/runner.py +12 -0
  5. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/ast_nodes.py +1 -1
  6. quantum_framework-0.16.0/quantum/core/docs_links.py +8 -0
  7. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/state_management/src/ast_node.py +0 -107
  8. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/ui_engine/src/ast_nodes.py +24 -1
  9. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/ui_engine/src/parser.py +19 -2
  10. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parser.py +16 -7
  11. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/control_flow/set_parser.py +10 -11
  12. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/tiers.py +20 -1
  13. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/action_handler.py +2 -1
  14. quantum_framework-0.16.0/quantum/runtime/local_server.py +28 -0
  15. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_builder.py +50 -21
  16. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_console.py +167 -36
  17. quantum_framework-0.16.0/quantum/runtime/ui_desktop.py +56 -0
  18. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_html_adapter.py +43 -191
  19. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_html_templates.py +2 -247
  20. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_page_renderer.py +106 -3
  21. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_view.py +37 -2
  22. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/web_server.py +6 -5
  23. {quantum_framework-0.15.0 → quantum_framework-0.16.0/quantum_framework.egg-info}/PKG-INFO +3 -1
  24. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_framework.egg-info/SOURCES.txt +3 -6
  25. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_framework.egg-info/requires.txt +3 -0
  26. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_cli_commands.py +4 -5
  27. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_ui_html_adapter.py +0 -25
  28. quantum_framework-0.15.0/quantum/core/parsers/persistence/__init__.py +0 -9
  29. quantum_framework-0.15.0/quantum/core/parsers/persistence/persist_parser.py +0 -64
  30. quantum_framework-0.15.0/quantum/runtime/ui_desktop_adapter.py +0 -1730
  31. quantum_framework-0.15.0/quantum/runtime/ui_desktop_templates.py +0 -307
  32. quantum_framework-0.15.0/tests/test_desktop_bridge.py +0 -442
  33. quantum_framework-0.15.0/tests/test_state_persistence.py +0 -458
  34. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/LICENSE +0 -0
  35. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/README.md +0 -0
  36. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/__init__.py +0 -0
  37. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/__init__.py +0 -0
  38. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/admin.py +0 -0
  39. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/__init__.py +0 -0
  40. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/dev.py +0 -0
  41. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/docs.py +0 -0
  42. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/lint.py +0 -0
  43. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/migrate.py +0 -0
  44. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/new.py +0 -0
  45. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/serve.py +0 -0
  46. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/commands/test.py +0 -0
  47. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/deploy.py +0 -0
  48. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/hot_reload.py +0 -0
  49. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/jobs.py +0 -0
  50. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/mq.py +0 -0
  51. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/pkg.py +0 -0
  52. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/server_process.py +0 -0
  53. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/cli/utils.py +0 -0
  54. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/__init__.py +0 -0
  55. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/base_generator.py +0 -0
  56. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/cli.py +0 -0
  57. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/expression_transformer.py +0 -0
  58. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/javascript/__init__.py +0 -0
  59. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/javascript/generator.py +0 -0
  60. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/optimizer.py +0 -0
  61. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/python/__init__.py +0 -0
  62. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/python/generator.py +0 -0
  63. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/python/runtime.py +0 -0
  64. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/compiler/transpiler.py +0 -0
  65. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/__init__.py +0 -0
  66. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/config_env.py +0 -0
  67. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/expression_diagnostics.py +0 -0
  68. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/expression_stdlib.py +0 -0
  69. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/expressions.py +0 -0
  70. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/agents/src/__init__.py +0 -0
  71. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/agents/src/ast_node.py +0 -0
  72. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/conditionals/src/__init__.py +0 -0
  73. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/conditionals/src/ast_node.py +0 -0
  74. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/data_import/src/__init__.py +0 -0
  75. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/data_import/src/ast_node.py +0 -0
  76. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/data_import/src/runtime.py +0 -0
  77. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/dump/src/__init__.py +0 -0
  78. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/dump/src/ast_node.py +0 -0
  79. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/dump/src/parser.py +0 -0
  80. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/dump/src/runtime.py +0 -0
  81. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/functions/src/__init__.py +0 -0
  82. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/functions/src/ast_node.py +0 -0
  83. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/game_engine_2d/src/__init__.py +0 -0
  84. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/game_engine_2d/src/ast_nodes.py +0 -0
  85. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/game_engine_2d/src/parser.py +0 -0
  86. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/invocation/src/__init__.py +0 -0
  87. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/invocation/src/ast_node.py +0 -0
  88. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/invocation/src/runtime.py +0 -0
  89. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/knowledge_base/src/__init__.py +0 -0
  90. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/knowledge_base/src/ast_node.py +0 -0
  91. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/knowledge_base/src/parser.py +0 -0
  92. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/logging/src/__init__.py +0 -0
  93. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/logging/src/ast_node.py +0 -0
  94. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/logging/src/parser.py +0 -0
  95. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/logging/src/runtime.py +0 -0
  96. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/loops/src/__init__.py +0 -0
  97. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/loops/src/ast_node.py +0 -0
  98. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/query/src/__init__.py +0 -0
  99. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/query/src/query_validators.py +0 -0
  100. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/state_management/src/__init__.py +0 -0
  101. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/terminal_engine/src/__init__.py +0 -0
  102. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/terminal_engine/src/ast_nodes.py +0 -0
  103. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/terminal_engine/src/parser.py +0 -0
  104. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/testing_engine/src/__init__.py +0 -0
  105. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/testing_engine/src/ast_nodes.py +0 -0
  106. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/testing_engine/src/parser.py +0 -0
  107. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/theming/src/__init__.py +0 -0
  108. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/theming/src/ast_node.py +0 -0
  109. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/theming/src/presets.py +0 -0
  110. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/ui_engine/src/__init__.py +0 -0
  111. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/websocket/src/__init__.py +0 -0
  112. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/features/websocket/src/ast_node.py +0 -0
  113. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/guards.py +0 -0
  114. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/html_compat.py +0 -0
  115. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parser_registry.py +0 -0
  116. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/__init__.py +0 -0
  117. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/ai/__init__.py +0 -0
  118. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/ai/agent_parser.py +0 -0
  119. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/ai/knowledge_parser.py +0 -0
  120. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/ai/llm_parser.py +0 -0
  121. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/ai/team_parser.py +0 -0
  122. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/base.py +0 -0
  123. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/composition/__init__.py +0 -0
  124. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/composition/import_parser.py +0 -0
  125. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/composition/slot_parser.py +0 -0
  126. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/control_flow/__init__.py +0 -0
  127. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/control_flow/if_parser.py +0 -0
  128. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/control_flow/loop_parser.py +0 -0
  129. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/data/__init__.py +0 -0
  130. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/data/data_parser.py +0 -0
  131. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/data/invoke_parser.py +0 -0
  132. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/data/query_parser.py +0 -0
  133. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/data/transaction_parser.py +0 -0
  134. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/events/__init__.py +0 -0
  135. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/events/dispatch_event_parser.py +0 -0
  136. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/forms/__init__.py +0 -0
  137. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/forms/action_parser.py +0 -0
  138. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/forms/flash_parser.py +0 -0
  139. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/forms/redirect_parser.py +0 -0
  140. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/functions/__init__.py +0 -0
  141. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/functions/function_parser.py +0 -0
  142. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/functions/param_parser.py +0 -0
  143. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/functions/return_parser.py +0 -0
  144. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/html/__init__.py +0 -0
  145. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/html/component_call_parser.py +0 -0
  146. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/html/html_parser.py +0 -0
  147. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/jobs/__init__.py +0 -0
  148. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/jobs/job_parser.py +0 -0
  149. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/jobs/schedule_parser.py +0 -0
  150. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/jobs/thread_parser.py +0 -0
  151. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/messaging/__init__.py +0 -0
  152. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/messaging/message_ack_parser.py +0 -0
  153. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/messaging/message_nack_parser.py +0 -0
  154. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/messaging/message_parser.py +0 -0
  155. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/messaging/queue_parser.py +0 -0
  156. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/messaging/websocket_parser.py +0 -0
  157. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/routing/__init__.py +0 -0
  158. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/routing/route_parser.py +0 -0
  159. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/scripting/__init__.py +0 -0
  160. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/scripting/pyclass_parser.py +0 -0
  161. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/scripting/pydecorator_parser.py +0 -0
  162. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/scripting/pyimport_parser.py +0 -0
  163. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/scripting/python_parser.py +0 -0
  164. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/services/__init__.py +0 -0
  165. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/services/dump_parser.py +0 -0
  166. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/services/file_parser.py +0 -0
  167. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/services/log_parser.py +0 -0
  168. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/core/parsers/services/mail_parser.py +0 -0
  169. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/packages/__init__.py +0 -0
  170. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/packages/manager.py +0 -0
  171. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/packages/manifest.py +0 -0
  172. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/packages/registry.py +0 -0
  173. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/packages/resolver.py +0 -0
  174. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/plugins/__init__.py +0 -0
  175. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/plugins/hooks.py +0 -0
  176. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/plugins/loader.py +0 -0
  177. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/plugins/manifest.py +0 -0
  178. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/plugins/registry.py +0 -0
  179. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/__init__.py +0 -0
  180. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/adapters/__init__.py +0 -0
  181. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/adapters/memory_adapter.py +0 -0
  182. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/adapters/rabbitmq_adapter.py +0 -0
  183. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/adapters/redis_adapter.py +0 -0
  184. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/adapters/sqlite_adapter.py +0 -0
  185. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/agent_service.py +0 -0
  186. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ast_cache.py +0 -0
  187. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/auth_service.py +0 -0
  188. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/component.py +0 -0
  189. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/component_composer.py +0 -0
  190. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/component_resolver.py +0 -0
  191. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/conditions.py +0 -0
  192. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/database_service.py +0 -0
  193. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/email_service.py +0 -0
  194. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/error_handler.py +0 -0
  195. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/execution_context.py +0 -0
  196. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executor_registry.py +0 -0
  197. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/__init__.py +0 -0
  198. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/ai/__init__.py +0 -0
  199. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/ai/agent_executor.py +0 -0
  200. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/ai/knowledge_executor.py +0 -0
  201. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/ai/llm_executor.py +0 -0
  202. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/ai/team_executor.py +0 -0
  203. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/base.py +0 -0
  204. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/control_flow/__init__.py +0 -0
  205. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/control_flow/if_executor.py +0 -0
  206. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/control_flow/loop_executor.py +0 -0
  207. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/control_flow/redirect_executor.py +0 -0
  208. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/control_flow/set_executor.py +0 -0
  209. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/data/__init__.py +0 -0
  210. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/data/data_executor.py +0 -0
  211. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/data/invoke_executor.py +0 -0
  212. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/data/query_executor.py +0 -0
  213. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/data/transaction_executor.py +0 -0
  214. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/jobs/__init__.py +0 -0
  215. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/jobs/job_executor.py +0 -0
  216. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/jobs/schedule_executor.py +0 -0
  217. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/jobs/thread_executor.py +0 -0
  218. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/messaging/__init__.py +0 -0
  219. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/messaging/message_ack_executor.py +0 -0
  220. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/messaging/message_executor.py +0 -0
  221. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/messaging/queue_executor.py +0 -0
  222. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/messaging/websocket_executor.py +0 -0
  223. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/scripting/__init__.py +0 -0
  224. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/scripting/pyclass_executor.py +0 -0
  225. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/scripting/pyimport_executor.py +0 -0
  226. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/scripting/python_executor.py +0 -0
  227. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/services/__init__.py +0 -0
  228. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/services/dump_executor.py +0 -0
  229. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/services/file_executor.py +0 -0
  230. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/services/log_executor.py +0 -0
  231. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/executors/services/mail_executor.py +0 -0
  232. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/expression_cache.py +0 -0
  233. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/file_upload_service.py +0 -0
  234. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/function_registry.py +0 -0
  235. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/game_builder.py +0 -0
  236. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/game_code_generator.py +0 -0
  237. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/game_templates.py +0 -0
  238. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/godot_code_generator.py +0 -0
  239. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/godot_templates.py +0 -0
  240. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/job_executor.py +0 -0
  241. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/knowledge_service.py +0 -0
  242. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/llm_cache.py +0 -0
  243. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/llm_providers.py +0 -0
  244. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/llm_service.py +0 -0
  245. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/logging_setup.py +0 -0
  246. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/message_broker.py +0 -0
  247. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/message_queue_service.py +0 -0
  248. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/param_validation.py +0 -0
  249. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/pypy_compat.py +0 -0
  250. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/python_bridge.py +0 -0
  251. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/query_validators.py +0 -0
  252. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/renderer.py +0 -0
  253. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/service_container.py +0 -0
  254. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/terminal_builder.py +0 -0
  255. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/terminal_code_generator.py +0 -0
  256. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/terminal_templates.py +0 -0
  257. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/testing_builder.py +0 -0
  258. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/testing_code_generator.py +0 -0
  259. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/testing_templates.py +0 -0
  260. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_mobile_adapter.py +0 -0
  261. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_mobile_templates.py +0 -0
  262. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_textual_adapter.py +0 -0
  263. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_textual_templates.py +0 -0
  264. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_tokens.py +0 -0
  265. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/ui_validator.py +0 -0
  266. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/validators.py +0 -0
  267. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/websocket_adapter.py +0 -0
  268. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/websocket_service.py +0 -0
  269. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/websocket_transport.py +0 -0
  270. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/runtime/wsgi.py +0 -0
  271. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/services.py +0 -0
  272. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum/utils/__init__.py +0 -0
  273. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/__init__.py +0 -0
  274. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/assets/quantum-admin-connectors.js +0 -0
  275. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/assets/quantum-admin.css +0 -0
  276. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/assets/quantum-source-highlight.js +0 -0
  277. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/__init__.py +0 -0
  278. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/audit_service.py +0 -0
  279. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/auth_service.py +0 -0
  280. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/component_discovery.py +0 -0
  281. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/config_generator.py +0 -0
  282. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/connector_service.py +0 -0
  283. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/crud.py +0 -0
  284. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/database.py +0 -0
  285. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/db_setup_service.py +0 -0
  286. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/deploy_service.py +0 -0
  287. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/docker_service.py +0 -0
  288. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/environment_service.py +0 -0
  289. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/git_service.py +0 -0
  290. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/health_service.py +0 -0
  291. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/job_service.py +0 -0
  292. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/log_service.py +0 -0
  293. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/main.py +0 -0
  294. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/models.py +0 -0
  295. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/pipeline_service.py +0 -0
  296. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/resource_manager.py +0 -0
  297. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/schemas.py +0 -0
  298. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/secret_manager.py +0 -0
  299. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/settings_service.py +0 -0
  300. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/template_service.py +0 -0
  301. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/test_execution_service.py +0 -0
  302. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/test_generator.py +0 -0
  303. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/webhook_service.py +0 -0
  304. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/backend/websocket_manager.py +0 -0
  305. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/_layout/AdminShell.q +0 -0
  306. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/agents.q +0 -0
  307. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/app/[name].q +0 -0
  308. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/applications.q +0 -0
  309. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/component/[...path].q +0 -0
  310. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/components.q +0 -0
  311. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/connectors.q +0 -0
  312. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/dashboard.q +0 -0
  313. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/database.q +0 -0
  314. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/features.q +0 -0
  315. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/index.q +0 -0
  316. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/jobs.q +0 -0
  317. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/login.q +0 -0
  318. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/logout.q +0 -0
  319. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/settings.q +0 -0
  320. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/source.q +0 -0
  321. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/components/admin/tests.q +0 -0
  322. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/run.py +0 -0
  323. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/__init__.py +0 -0
  324. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/_base.py +0 -0
  325. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/_component_test_generator.py +0 -0
  326. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/_yaml_editor.py +0 -0
  327. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/apps.py +0 -0
  328. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/auth.py +0 -0
  329. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/components.py +0 -0
  330. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/connectors.py +0 -0
  331. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/projects.py +0 -0
  332. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/repository.py +0 -0
  333. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/settings.py +0 -0
  334. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_admin/services/yaml_import.py +0 -0
  335. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_framework.egg-info/dependency_links.txt +0 -0
  336. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_framework.egg-info/entry_points.txt +0 -0
  337. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/quantum_framework.egg-info/top_level.txt +0 -0
  338. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/setup.cfg +0 -0
  339. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_agent.py +0 -0
  340. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_animations.py +0 -0
  341. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_ast_cache.py +0 -0
  342. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_component_library.py +0 -0
  343. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_expression_cache.py +0 -0
  344. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_form_validation.py +0 -0
  345. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_game_codegen.py +0 -0
  346. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_game_e2e.py +0 -0
  347. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_game_engine.py +0 -0
  348. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_game_parser.py +0 -0
  349. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_godot_codegen.py +0 -0
  350. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_job_executor.py +0 -0
  351. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_llm_providers.py +0 -0
  352. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_message_broker.py +0 -0
  353. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_message_queue.py +0 -0
  354. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_mobile_target.py +0 -0
  355. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_multi_agent.py +0 -0
  356. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_packages.py +0 -0
  357. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_plugins.py +0 -0
  358. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_pypy_compat.py +0 -0
  359. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_python_scripting.py +0 -0
  360. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_terminal_codegen.py +0 -0
  361. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_terminal_parser.py +0 -0
  362. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_testing_codegen.py +0 -0
  363. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_testing_parser.py +0 -0
  364. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_theming.py +0 -0
  365. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_ui_parity.py +0 -0
  366. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_ui_parser.py +0 -0
  367. {quantum_framework-0.15.0 → quantum_framework-0.16.0}/tests/test_ui_textual_adapter.py +0 -0
  368. {quantum_framework-0.15.0 → quantum_framework-0.16.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.15.0
3
+ Version: 0.16.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
@@ -42,6 +42,8 @@ Provides-Extra: admin
42
42
  Requires-Dist: sqlalchemy>=2.0; extra == "admin"
43
43
  Requires-Dist: PyJWT>=2.8; extra == "admin"
44
44
  Requires-Dist: cryptography>=42.0; extra == "admin"
45
+ Provides-Extra: desktop
46
+ Requires-Dist: pywebview>=5.0; extra == "desktop"
45
47
  Provides-Extra: websocket
46
48
  Requires-Dist: websockets>=12.0; extra == "websocket"
47
49
  Dynamic: license-file
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quantum-framework"
7
- version = "0.15.0"
7
+ version = "0.16.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"}
@@ -58,6 +58,10 @@ admin = [
58
58
  "PyJWT>=2.8",
59
59
  "cryptography>=42.0",
60
60
  ]
61
+ desktop = [
62
+ # `quantum desktop`: the native window around the application's server.
63
+ "pywebview>=5.0",
64
+ ]
61
65
  websocket = [
62
66
  # The transport behind q:websocket. Without it the tag registers a
63
67
  # connection and opens nothing — and says so, rather than pretending.
@@ -16,12 +16,12 @@ from quantum.cli.utils import get_console, find_project_root, find_q_files
16
16
 
17
17
 
18
18
  # Available build targets
19
- TARGETS = ['html', 'desktop', 'mobile', 'textual', 'all']
19
+ TARGETS = ['html', 'mobile', 'textual', 'all']
20
20
 
21
21
 
22
22
  @click.command('build')
23
23
  @click.option('--target', '-t', type=click.Choice(TARGETS), default='html',
24
- help='Build target (html, desktop, mobile, textual, all)')
24
+ help='Build target (html, mobile, textual, all)')
25
25
  @click.option('--output', '-o', type=click.Path(), default='./dist',
26
26
  help='Output directory')
27
27
  @click.option('--minify', is_flag=True, default=True, help='Minify output')
@@ -53,8 +53,6 @@ def build(
53
53
 
54
54
  quantum build
55
55
 
56
- quantum build --target desktop
57
-
58
56
  quantum build --target all --output ./build
59
57
 
60
58
  quantum build --target mobile --no-minify
@@ -98,7 +96,7 @@ def build(
98
96
 
99
97
  # Determine targets to build
100
98
  if target == 'all':
101
- targets_to_build = ['html', 'desktop', 'mobile', 'textual']
99
+ targets_to_build = ['html', 'mobile', 'textual']
102
100
  else:
103
101
  targets_to_build = [target]
104
102
 
@@ -247,12 +245,11 @@ def _build_application(
247
245
  from quantum.runtime.testing_builder import TestingBuilder
248
246
  builder = TestingBuilder()
249
247
  ext = '.py'
250
- elif app_type == 'ui' or target in ('html', 'desktop', 'mobile', 'textual'):
248
+ elif app_type == 'ui' or target in ('html', 'mobile', 'textual'):
251
249
  builder = UIBuilder()
252
250
  # Map target to extension
253
251
  ext_map = {
254
252
  'html': '.html',
255
- 'desktop': '.py',
256
253
  'mobile': '.js',
257
254
  'textual': '.py',
258
255
  }
@@ -286,6 +286,7 @@ Examples:
286
286
  quantum run hello.q # Execute component
287
287
  quantum admin # Start the Quantum Admin
288
288
  quantum console # The application's pages in the terminal
289
+ quantum desktop # The application's pages in a desktop window
289
290
  quantum run game.q --engine godot # Build Godot 4 project
290
291
  quantum run backup-job.q # Execute job
291
292
  quantum deploy ./my-app # Deploy application
@@ -341,6 +342,13 @@ Examples:
341
342
  console_parser.add_argument('path', nargs='?', default='/', help='Page to open (default: /)')
342
343
  console_parser.add_argument('--config', default='quantum.config.yaml', help='Config file')
343
344
 
345
+ # Desktop: the application's pages in a native window (UI-4)
346
+ desktop_parser = subparsers.add_parser('desktop', help="Open the application's pages in a desktop window")
347
+ desktop_parser.add_argument('path', nargs='?', default='/', help='Page to open (default: /)')
348
+ desktop_parser.add_argument('--config', default='quantum.config.yaml', help='Config file')
349
+ desktop_parser.add_argument('--width', type=int, default=1024, help='Window width (default: 1024)')
350
+ desktop_parser.add_argument('--height', type=int, default=720, help='Window height (default: 720)')
351
+
344
352
  # Admin command (the screens need the [admin] extra; checked when run)
345
353
  from quantum.cli.admin import create_admin_parser
346
354
  create_admin_parser(subparsers)
@@ -411,6 +419,10 @@ Examples:
411
419
  from quantum.runtime.ui_console import run_console
412
420
  sys.exit(run_console(args.config, args.path))
413
421
 
422
+ elif args.command == 'desktop':
423
+ from quantum.runtime.ui_desktop import run_desktop
424
+ sys.exit(run_desktop(args.config, args.path, width=args.width, height=args.height))
425
+
414
426
  elif args.command == 'admin':
415
427
  from quantum.cli.admin import handle_admin
416
428
  sys.exit(handle_admin(args))
@@ -676,7 +676,7 @@ class OnEventNode(QuantumNode):
676
676
 
677
677
  # MIGRATED: SetNode and PersistNode moved to feature-based structure
678
678
  # Import from new location (Option C migration)
679
- from .features.state_management.src.ast_node import SetNode, PersistNode
679
+ from .features.state_management.src.ast_node import SetNode
680
680
 
681
681
 
682
682
  class QueryNode(QuantumNode):
@@ -0,0 +1,8 @@
1
+ """Documentation pages that error messages point to (one place, one spelling)."""
2
+
3
+ DOCS = 'https://danielgregorio.github.io/quantum'
4
+
5
+ # EXEC-*: the order in which a page's parts run. The traps — a statement in
6
+ # the markup, a variable the action cannot see, a guard reading the page —
7
+ # all come from that order, so their messages send the reader here.
8
+ HOW_A_PAGE_RUNS = f'{DOCS}/guide/how-a-page-runs'
@@ -3,11 +3,6 @@ AST Node for State Management (q:set)
3
3
 
4
4
  This module contains the SetNode class, which represents the <q:set> tag
5
5
  for state management in Quantum Language.
6
-
7
- State Persistence Support:
8
- - persist="local" - localStorage (browser) or file (desktop)
9
- - persist="session" - sessionStorage (browser) or memory (desktop)
10
- - persist="sync" - synchronized across tabs/windows (browser) or network (desktop)
11
6
  """
12
7
 
13
8
  from typing import Dict, Any, List, Optional
@@ -54,12 +49,6 @@ class SetNode(QuantumNode):
54
49
  self.key = None
55
50
  self.source = None
56
51
 
57
- # State Persistence
58
- self.persist: Optional[str] = None # None, "local", "session", "sync"
59
- self.persist_key: Optional[str] = None # Custom storage key (defaults to name)
60
- self.persist_encrypt: bool = False # Encrypt persisted data
61
- self.persist_ttl: Optional[int] = None # TTL in seconds for cached persistence
62
-
63
52
  def to_dict(self) -> Dict[str, Any]:
64
53
  result = {
65
54
  "type": "set",
@@ -84,14 +73,6 @@ class SetNode(QuantumNode):
84
73
  "maxlength": self.maxlength
85
74
  }
86
75
  }
87
- # Add persistence info if enabled
88
- if self.persist:
89
- result["persistence"] = {
90
- "scope": self.persist,
91
- "key": self.persist_key or self.name,
92
- "encrypt": self.persist_encrypt,
93
- "ttl": self.persist_ttl
94
- }
95
76
  return result
96
77
 
97
78
  def validate(self) -> List[str]:
@@ -136,93 +117,5 @@ class SetNode(QuantumNode):
136
117
  if self.maxlength and len(str(self.value)) > int(self.maxlength):
137
118
  errors.append(f"Value length {len(str(self.value))} exceeds maxlength {self.maxlength}")
138
119
 
139
- # Validar persist scope
140
- if self.persist:
141
- valid_persist_scopes = ['local', 'session', 'sync']
142
- if self.persist not in valid_persist_scopes:
143
- errors.append(f"Invalid persist scope: {self.persist}. Must be one of {valid_persist_scopes}")
144
-
145
- return errors
146
-
147
-
148
- class PersistNode(QuantumNode):
149
- """
150
- Represents a <q:persist> - Explicit persistence configuration.
151
-
152
- Allows fine-grained control over state persistence beyond the persist attribute on q:set.
153
-
154
- Examples:
155
- <q:persist scope="local" prefix="myapp_">
156
- <q:var name="theme" />
157
- <q:var name="locale" />
158
- </q:persist>
159
-
160
- <q:persist scope="sync" key="user_preferences" encrypt="true">
161
- <q:var name="darkMode" />
162
- <q:var name="fontSize" />
163
- </q:persist>
164
-
165
- Attributes:
166
- scope: "local" (localStorage), "session" (sessionStorage), "sync" (cross-tab/network)
167
- prefix: Optional prefix for all storage keys
168
- key: If set, all vars are stored under this single key as an object
169
- encrypt: Whether to encrypt persisted data
170
- ttl: Time-to-live in seconds (for cache invalidation)
171
- storage: Override storage backend ("localStorage", "indexedDB", "file", "db")
172
- """
173
-
174
- def __init__(
175
- self,
176
- scope: str = "local",
177
- prefix: Optional[str] = None,
178
- key: Optional[str] = None,
179
- encrypt: bool = False,
180
- ttl: Optional[int] = None,
181
- storage: Optional[str] = None
182
- ):
183
- self.scope = scope
184
- self.prefix = prefix
185
- self.key = key
186
- self.encrypt = encrypt
187
- self.ttl = ttl
188
- self.storage = storage
189
- self.variables: List[str] = [] # List of variable names to persist
190
-
191
- def add_variable(self, name: str):
192
- """Add a variable name to persist."""
193
- self.variables.append(name)
194
-
195
- def to_dict(self) -> Dict[str, Any]:
196
- return {
197
- "type": "persist",
198
- "scope": self.scope,
199
- "prefix": self.prefix,
200
- "key": self.key,
201
- "encrypt": self.encrypt,
202
- "ttl": self.ttl,
203
- "storage": self.storage,
204
- "variables": self.variables
205
- }
206
-
207
- def validate(self) -> List[str]:
208
- errors = []
209
-
210
- # Validate scope
211
- valid_scopes = ['local', 'session', 'sync']
212
- if self.scope not in valid_scopes:
213
- errors.append(f"Invalid persist scope: {self.scope}. Must be one of {valid_scopes}")
214
-
215
- # Validate storage backend if specified
216
- if self.storage:
217
- valid_storage = ['localStorage', 'sessionStorage', 'indexedDB', 'file', 'db']
218
- if self.storage not in valid_storage:
219
- errors.append(f"Invalid storage backend: {self.storage}. Must be one of {valid_storage}")
220
-
221
- # Validate variables
222
- if not self.variables:
223
- errors.append("q:persist must contain at least one q:var element")
224
-
225
120
  return errors
226
121
 
227
- def __repr__(self):
228
- return f'<PersistNode scope={self.scope} vars={len(self.variables)}>'
@@ -374,7 +374,7 @@ class UIValidatorNode(QuantumNode):
374
374
  Can be defined at form level (reusable) or inline in an input.
375
375
 
376
376
  Examples:
377
- <ui:validator name="phone" pattern="^\d{10,11}$" message="Invalid phone number" />
377
+ <ui:validator name="phone" pattern="^\\d{10,11}$" message="Invalid phone number" />
378
378
  <ui:validator name="passwordMatch" field="password" match="confirm_password"
379
379
  message="Passwords must match" />
380
380
  <ui:validator name="customEmail" type="email" message="Please enter a valid email" />
@@ -549,6 +549,7 @@ class UIInputNode(QuantumNode, UILayoutMixin):
549
549
 
550
550
  def __init__(self):
551
551
  self.bind: Optional[str] = None
552
+ self.value: Optional[str] = None # initial value (UI-6)
552
553
  self.placeholder: Optional[str] = None
553
554
  self.input_type: str = "text" # text, password, email, number
554
555
  self.on_change: Optional[str] = None
@@ -592,6 +593,7 @@ class UICheckboxNode(QuantumNode, UILayoutMixin):
592
593
 
593
594
  def __init__(self):
594
595
  self.bind: Optional[str] = None
596
+ self.checked: Optional[str] = None # "true"/"false" or {expr} (UI-6)
595
597
  self.label: Optional[str] = None
596
598
  self._init_layout_attrs()
597
599
 
@@ -609,6 +611,7 @@ class UIRadioNode(QuantumNode, UILayoutMixin):
609
611
 
610
612
  def __init__(self):
611
613
  self.bind: Optional[str] = None
614
+ self.value: Optional[str] = None # selected option (UI-6)
612
615
  self.options: Optional[str] = None # comma-separated or source ref
613
616
  self._init_layout_attrs()
614
617
 
@@ -626,6 +629,7 @@ class UISwitchNode(QuantumNode, UILayoutMixin):
626
629
 
627
630
  def __init__(self):
628
631
  self.bind: Optional[str] = None
632
+ self.checked: Optional[str] = None # "true"/"false" or {expr} (UI-6)
629
633
  self.label: Optional[str] = None
630
634
  self._init_layout_attrs()
631
635
 
@@ -643,6 +647,7 @@ class UISelectNode(QuantumNode, UILayoutMixin):
643
647
 
644
648
  def __init__(self):
645
649
  self.bind: Optional[str] = None
650
+ self.value: Optional[str] = None # selected option (UI-6)
646
651
  self.options: Optional[str] = None
647
652
  self.source: Optional[str] = None
648
653
  self.children: List[QuantumNode] = [] # UIOptionNode children
@@ -667,6 +672,7 @@ class UITableNode(QuantumNode, UILayoutMixin):
667
672
 
668
673
  def __init__(self):
669
674
  self.source: Optional[str] = None
675
+ self.as_var: Optional[str] = None # row variable for column content (UI-5)
670
676
  self.children: List[QuantumNode] = [] # UIColumnNode children
671
677
  self._init_layout_attrs()
672
678
 
@@ -691,6 +697,11 @@ class UIColumnNode(QuantumNode):
691
697
  self.label: Optional[str] = None
692
698
  self.column_width: Optional[str] = None
693
699
  self.align: Optional[str] = None # left, center, right
700
+ # UI-5: a column with content draws it once per row (buttons, links).
701
+ self.children: List[QuantumNode] = []
702
+
703
+ def add_child(self, child: QuantumNode):
704
+ self.children.append(child)
694
705
 
695
706
  def to_dict(self) -> Dict[str, Any]:
696
707
  return {"type": "ui_column", "key": self.key,
@@ -1862,3 +1873,15 @@ class UIDatePickerNode(QuantumNode, UILayoutMixin):
1862
1873
  def is_ui_node(node) -> bool:
1863
1874
  """A ui:* element (UI-1): markup, drawn by a renderer, never executed."""
1864
1875
  return type(node).__module__ == __name__
1876
+
1877
+
1878
+ # UI-7: the elements every renderer draws — browser, console and desktop — with
1879
+ # the same meaning, checked by tests/apps/test_ui_paridade.py. The other ui:*
1880
+ # tags work in the browser only; the console says it cannot draw them.
1881
+ CORE_TAGS = frozenset({
1882
+ 'window', 'hbox', 'vbox', 'grid', 'panel', 'section', 'scrollbox', 'spacer', 'rule',
1883
+ 'header', 'footer', 'card', 'card-header', 'card-body', 'card-footer', 'tabpanel', 'tab',
1884
+ 'text', 'badge', 'alert', 'link', 'image', 'progress',
1885
+ 'table', 'column', 'list', 'item',
1886
+ 'form', 'formitem', 'input', 'checkbox', 'switch', 'radio', 'select', 'option', 'button',
1887
+ })
@@ -31,6 +31,7 @@ from .ast_nodes import (
31
31
  UICalendarNode, UIDatePickerNode,
32
32
  )
33
33
  from quantum.core.features.theming.src import UIThemeNode, UIColorNode
34
+ from quantum.core.ast_nodes import TextNode
34
35
 
35
36
 
36
37
  class UIParseError(Exception):
@@ -252,11 +253,20 @@ class UIParser:
252
253
  return None
253
254
 
254
255
  def _parse_children(self, element: ET.Element, node):
255
- """Parse all children of an element, adding them to node."""
256
+ """Parse all children of an element, adding them to node.
257
+
258
+ UI-1: inside a page, a container's own text is content too
259
+ (`<ui:card-header>Resumo</ui:card-header>`); it used to vanish. Nodes
260
+ that keep their text in `content` read it themselves."""
261
+ texto_e_conteudo = self.page_mode and not hasattr(node, 'content')
262
+ if texto_e_conteudo and (element.text or '').strip():
263
+ node.add_child(TextNode(element.text.strip()))
256
264
  for child in element:
257
265
  parsed = self._parse_child(child)
258
266
  if parsed:
259
267
  node.add_child(parsed)
268
+ if texto_e_conteudo and (child.tail or '').strip():
269
+ node.add_child(TextNode(child.tail.strip()))
260
270
 
261
271
  # ------------------------------------------------------------------
262
272
  # Containers
@@ -404,6 +414,7 @@ class UIParser:
404
414
  def _parse_ui_input(self, element: ET.Element) -> UIInputNode:
405
415
  node = UIInputNode()
406
416
  node.bind = element.get('bind')
417
+ node.value = element.get('value')
407
418
  node.placeholder = element.get('placeholder')
408
419
  node.input_type = element.get('type', 'text')
409
420
  node.on_change = element.get('on-change')
@@ -436,6 +447,7 @@ class UIParser:
436
447
  def _parse_ui_checkbox(self, element: ET.Element) -> UICheckboxNode:
437
448
  node = UICheckboxNode()
438
449
  node.bind = element.get('bind')
450
+ node.checked = element.get('checked')
439
451
  node.label = element.get('label')
440
452
  self._apply_layout_attrs(node, element)
441
453
  return node
@@ -443,6 +455,7 @@ class UIParser:
443
455
  def _parse_ui_radio(self, element: ET.Element) -> UIRadioNode:
444
456
  node = UIRadioNode()
445
457
  node.bind = element.get('bind')
458
+ node.value = element.get('value')
446
459
  node.options = element.get('options')
447
460
  self._apply_layout_attrs(node, element)
448
461
  return node
@@ -450,6 +463,7 @@ class UIParser:
450
463
  def _parse_ui_switch(self, element: ET.Element) -> UISwitchNode:
451
464
  node = UISwitchNode()
452
465
  node.bind = element.get('bind')
466
+ node.checked = element.get('checked')
453
467
  node.label = element.get('label')
454
468
  self._apply_layout_attrs(node, element)
455
469
  return node
@@ -457,6 +471,7 @@ class UIParser:
457
471
  def _parse_ui_select(self, element: ET.Element) -> UISelectNode:
458
472
  node = UISelectNode()
459
473
  node.bind = element.get('bind')
474
+ node.value = element.get('value')
460
475
  node.options = element.get('options')
461
476
  node.source = element.get('source')
462
477
  self._apply_layout_attrs(node, element)
@@ -467,6 +482,7 @@ class UIParser:
467
482
  def _parse_ui_table(self, element: ET.Element) -> UITableNode:
468
483
  node = UITableNode()
469
484
  node.source = element.get('source')
485
+ node.as_var = element.get('as')
470
486
  self._apply_layout_attrs(node, element)
471
487
  # Parse child <ui:column> elements
472
488
  self._parse_children(element, node)
@@ -478,6 +494,7 @@ class UIParser:
478
494
  node.label = element.get('label')
479
495
  node.column_width = element.get('width')
480
496
  node.align = element.get('align')
497
+ self._parse_children(element, node)
481
498
  return node
482
499
 
483
500
  def _parse_ui_list(self, element: ET.Element) -> UIListNode:
@@ -586,7 +603,7 @@ class UIParser:
586
603
  Parse <ui:validator> custom validation rule.
587
604
 
588
605
  Examples:
589
- <ui:validator name="phone" pattern="^\d{10}$" message="Invalid phone" />
606
+ <ui:validator name="phone" pattern="^\\d{10}$" message="Invalid phone" />
590
607
  <ui:validator name="confirmPassword" match="password"
591
608
  message="Passwords must match" />
592
609
  <ui:validator name="custom" expression="value.length > 5"
@@ -31,7 +31,8 @@ from quantum.core.ast_nodes import (
31
31
  # Import feature AST nodes from their respective modules
32
32
  from quantum.core.features.conditionals.src.ast_node import IfNode
33
33
  from quantum.core.features.loops.src.ast_node import LoopNode
34
- from quantum.core.features.state_management.src.ast_node import SetNode, PersistNode
34
+ from quantum.core.features.state_management.src.ast_node import SetNode
35
+ from quantum.core.docs_links import HOW_A_PAGE_RUNS
35
36
  from quantum.core.features.functions.src.ast_node import FunctionNode, RestConfig
36
37
  from quantum.core.features.invocation.src.ast_node import InvokeNode
37
38
  from quantum.core.features.logging.src import LogNode, parse_log
@@ -109,7 +110,6 @@ def _create_parser_registry(parser: 'QuantumParser') -> ParserRegistry:
109
110
  from quantum.core.parsers.composition import ImportParser, SlotParser
110
111
  from quantum.core.parsers.functions import FunctionParser, ReturnParser, ParamParser
111
112
  from quantum.core.parsers.events import DispatchEventParser
112
- from quantum.core.parsers.persistence import PersistParser
113
113
  from quantum.core.parsers.routing import RouteParser
114
114
  from quantum.core.parsers.messaging import MessageAckParser, MessageNackParser
115
115
  from quantum.core.parsers.scripting import PyDecoratorParser
@@ -170,8 +170,6 @@ def _create_parser_registry(parser: 'QuantumParser') -> ParserRegistry:
170
170
  # They are internal parsers used by FunctionParser and other parsers
171
171
  # Events
172
172
  DispatchEventParser(parser),
173
- # Persistence
174
- PersistParser(parser),
175
173
  ]
176
174
 
177
175
  registry.register_all(parsers)
@@ -482,7 +480,16 @@ class QuantumParser:
482
480
  continue
483
481
  anterior = child if nome == 'if' and self._is_quantum_tag(child) else None
484
482
 
483
+ # Tags that existed and were removed, with what to use instead.
484
+ REMOVED_TAGS = {
485
+ 'persist': ('was removed in Quantum 0.16 (SET-2): it kept variables in the browser, '
486
+ 'and a page\'s variables live on the server, for one request. Keep what must '
487
+ 'last in session.x (per user) or in the database.'),
488
+ }
489
+
485
490
  def _unknown_tag_message(self, name: str) -> str:
491
+ if name in self.REMOVED_TAGS:
492
+ return f"<q:{name}> {self.REMOVED_TAGS[name]}"
486
493
  import difflib
487
494
  # Only Quantum tags: the registry also holds the HTML tag names, which
488
495
  # made <q:try> suggest <q:tr>.
@@ -681,7 +688,7 @@ class QuantumParser:
681
688
  f'redirects, so it also runs before the page\'s q:action — where the page '
682
689
  f'has not run and {{{nome}}} does not exist, and the guard would let the '
683
690
  f'action through. Read the scope directly (e.g. session.x), or protect the '
684
- f'page with require_auth / require_role.')
691
+ f'page with require_auth / require_role. See {HOW_A_PAGE_RUNS}')
685
692
 
686
693
  # Nodes the HTML renderer draws. Anything else inside markup is a statement,
687
694
  # and statements run in the execution pass, before the render pass sees
@@ -758,7 +765,8 @@ class QuantumParser:
758
765
  raise QuantumParseError(
759
766
  f'{tag(node)} inside {onde[1]} in <q:component name="{component.name}"> '
760
767
  f'never runs: statements run before the page is rendered, and markup '
761
- f'is only rendered. Move it above the markup (or into a q:action).')
768
+ f'is only rendered. Move it above the markup (or into a q:action). '
769
+ f'See {HOW_A_PAGE_RUNS}')
762
770
  nome = getattr(node, 'name', None)
763
771
  # A running total read AFTER the loop is fine; a value the
764
772
  # loop's own rows read is not.
@@ -767,7 +775,8 @@ class QuantumParser:
767
775
  f'{tag(node)} inside a q:loop whose rows use {{{nome}}} in '
768
776
  f'<q:component name="{component.name}">: the loop runs for every item '
769
777
  f'before any row is rendered, so every row would show the last value. '
770
- f'Compute it in the expression instead, e.g. {{item.price * item.qty}}.')
778
+ f'Compute it in the expression instead, e.g. {{item.price * item.qty}}. '
779
+ f'See {HOW_A_PAGE_RUNS}')
771
780
  continue
772
781
  if isinstance(node, HTMLNode):
773
782
  andar(filhos(node), onde if onde and onde[0] == 'markup' else ('markup', f'<{node.tag}>'))
@@ -79,16 +79,15 @@ class SetParser(BaseTagParser):
79
79
  set_node.key = self.get_attr(element, 'key')
80
80
  set_node.source = self.get_attr(element, 'source')
81
81
 
82
- # State persistence
83
- set_node.persist = self.get_attr(element, 'persist')
84
- set_node.persist_key = self.get_attr(element, 'persistKey')
85
- set_node.persist_encrypt = self.get_bool_attr(element, 'persistEncrypt', False)
86
-
87
- persist_ttl = self.get_attr(element, 'persistTtl')
88
- if persist_ttl:
89
- try:
90
- set_node.persist_ttl = int(persist_ttl)
91
- except ValueError:
92
- pass
82
+ # SET-2: browser persistence never ran in a page.
83
+ persist = [a for a in ('persist', 'persistKey', 'persistTtl', 'persistEncrypt')
84
+ if element.get(a) is not None]
85
+ if persist:
86
+ from quantum.core.parser import QuantumParseError
87
+ raise QuantumParseError(
88
+ f'<q:set name="{set_node.name}"> {persist[0]}= was removed in Quantum 0.16: it '
89
+ f'kept the variable in the browser, and a page\'s variables live on the server, '
90
+ f'for one request. Keep what must last in session.{set_node.name} (per user) '
91
+ f'or in the database.')
93
92
 
94
93
  return set_node
@@ -31,7 +31,7 @@ EXPERIMENTAL = frozenset({
31
31
  "job", "schedule", "thread",
32
32
  "message", "queue", "subscribe", "messageAck", "messageNack",
33
33
  "websocket", "websocket-send", "websocket-close",
34
- "mail", "file", "log", "dump", "persist",
34
+ "mail", "file", "log", "dump",
35
35
  "python", "pyclass", "pyimport", "class", "decorator", "pydecorator",
36
36
  "dispatchEvent", "transaction",
37
37
  })
@@ -140,6 +140,25 @@ def warn_app_type(app_type: str) -> None:
140
140
  )
141
141
 
142
142
 
143
+ # UI-8: React Native translates the logic to JavaScript on its own — the
144
+ # opposite of "one runtime, many renderers" — and phones are out of 1.0. It
145
+ # stays to press on the language, like the games.
146
+ LAB_UI_TARGETS = frozenset({"mobile", "react-native"})
147
+
148
+
149
+ def warn_ui_target(target: str) -> None:
150
+ """One-time warning when a LABORATÓRIO UI target is built."""
151
+ key = f"ui-target:{target}"
152
+ if target not in LAB_UI_TARGETS or key in _warned:
153
+ return
154
+ _warned.add(key)
155
+ logger.warning(
156
+ "quantum run --target %s is LABORATÓRIO — it translates q:set and "
157
+ "q:function to JavaScript with no stability promise (SUPPORT_TIERS.md). "
158
+ "It may change or break without notice.", target
159
+ )
160
+
161
+
143
162
  def reset_warnings() -> None:
144
163
  """For tests, and for a reloading server."""
145
164
  _warned.clear()
@@ -143,8 +143,9 @@ class ActionHandler:
143
143
  # page's statements, so a variable the page sets is not here.
144
144
  mensagem = str(e)
145
145
  if 'is not defined' in mensagem:
146
+ from quantum.core.docs_links import HOW_A_PAGE_RUNS
146
147
  mensagem += (". A q:action does not run the page's statements: "
147
- "query or compute what it needs inside the action")
148
+ f"query or compute what it needs inside the action. See {HOW_A_PAGE_RUNS}")
148
149
  logger.exception(
149
150
  "q:action %r failed: %s", getattr(action, 'name', '?'), mensagem
150
151
  )
@@ -0,0 +1,28 @@
1
+ """The application's server on a free local port, for renderers that are not a browser.
2
+
3
+ `quantum console` (UI-3) and `quantum desktop` (UI-4) open the whole
4
+ application — pages, actions, sessions — through the same server that
5
+ `quantum start` runs. Only the drawing differs; nothing of a page's logic runs
6
+ anywhere else.
7
+ """
8
+
9
+ import logging
10
+ import threading
11
+ from contextlib import contextmanager
12
+ from typing import Iterator
13
+
14
+
15
+ @contextmanager
16
+ def local_server(config_path: str = 'quantum.config.yaml') -> Iterator[str]:
17
+ """Serve the application on 127.0.0.1 (a free port) in a thread; yield its base URL."""
18
+ from werkzeug.serving import make_server
19
+ from quantum.runtime.web_server import QuantumWebServer
20
+
21
+ logging.getLogger('werkzeug').setLevel(logging.ERROR)
22
+ app = QuantumWebServer(config_path).app
23
+ servidor = make_server('127.0.0.1', 0, app, threaded=True)
24
+ threading.Thread(target=servidor.serve_forever, daemon=True).start()
25
+ try:
26
+ yield f'http://127.0.0.1:{servidor.server_port}/'
27
+ finally:
28
+ servidor.shutdown()