quantum-framework 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quantum/__init__.py +1 -0
- quantum/cli/__init__.py +2 -0
- quantum/cli/commands/__init__.py +15 -0
- quantum/cli/commands/build.py +417 -0
- quantum/cli/commands/dev.py +185 -0
- quantum/cli/commands/docs.py +329 -0
- quantum/cli/commands/lint.py +523 -0
- quantum/cli/commands/migrate.py +527 -0
- quantum/cli/commands/new.py +622 -0
- quantum/cli/commands/serve.py +190 -0
- quantum/cli/commands/test.py +193 -0
- quantum/cli/deploy.py +810 -0
- quantum/cli/hot_reload.py +951 -0
- quantum/cli/jobs.py +356 -0
- quantum/cli/mq.py +582 -0
- quantum/cli/pkg.py +390 -0
- quantum/cli/runner.py +547 -0
- quantum/cli/server_process.py +159 -0
- quantum/cli/utils.py +334 -0
- quantum/compiler/__init__.py +30 -0
- quantum/compiler/base_generator.py +367 -0
- quantum/compiler/cli.py +295 -0
- quantum/compiler/expression_transformer.py +444 -0
- quantum/compiler/javascript/__init__.py +10 -0
- quantum/compiler/javascript/generator.py +659 -0
- quantum/compiler/optimizer.py +270 -0
- quantum/compiler/python/__init__.py +10 -0
- quantum/compiler/python/generator.py +883 -0
- quantum/compiler/python/runtime.py +863 -0
- quantum/compiler/transpiler.py +330 -0
- quantum/core/__init__.py +3 -0
- quantum/core/ast_nodes.py +2611 -0
- quantum/core/expression_diagnostics.py +87 -0
- quantum/core/expression_stdlib.py +148 -0
- quantum/core/expressions.py +591 -0
- quantum/core/features/agents/src/__init__.py +30 -0
- quantum/core/features/agents/src/ast_node.py +540 -0
- quantum/core/features/conditionals/src/__init__.py +8 -0
- quantum/core/features/conditionals/src/ast_node.py +68 -0
- quantum/core/features/data_fetching/src/__init__.py +21 -0
- quantum/core/features/data_fetching/src/ast_node.py +312 -0
- quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
- quantum/core/features/data_fetching/src/html_adapter.py +474 -0
- quantum/core/features/data_fetching/src/parser.py +225 -0
- quantum/core/features/data_import/src/__init__.py +0 -0
- quantum/core/features/data_import/src/ast_node.py +291 -0
- quantum/core/features/data_import/src/runtime.py +538 -0
- quantum/core/features/dump/src/__init__.py +12 -0
- quantum/core/features/dump/src/ast_node.py +106 -0
- quantum/core/features/dump/src/parser.py +61 -0
- quantum/core/features/dump/src/runtime.py +246 -0
- quantum/core/features/functions/src/__init__.py +8 -0
- quantum/core/features/functions/src/ast_node.py +149 -0
- quantum/core/features/game_engine_2d/src/__init__.py +19 -0
- quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
- quantum/core/features/game_engine_2d/src/parser.py +983 -0
- quantum/core/features/invocation/src/__init__.py +0 -0
- quantum/core/features/invocation/src/ast_node.py +146 -0
- quantum/core/features/invocation/src/runtime.py +327 -0
- quantum/core/features/knowledge_base/src/__init__.py +6 -0
- quantum/core/features/knowledge_base/src/ast_node.py +113 -0
- quantum/core/features/knowledge_base/src/parser.py +82 -0
- quantum/core/features/logging/src/__init__.py +12 -0
- quantum/core/features/logging/src/ast_node.py +111 -0
- quantum/core/features/logging/src/parser.py +50 -0
- quantum/core/features/logging/src/runtime.py +190 -0
- quantum/core/features/loops/src/__init__.py +8 -0
- quantum/core/features/loops/src/ast_node.py +60 -0
- quantum/core/features/query/src/__init__.py +0 -0
- quantum/core/features/query/src/database_service.py +322 -0
- quantum/core/features/query/src/query_validators.py +20 -0
- quantum/core/features/state_management/src/__init__.py +11 -0
- quantum/core/features/state_management/src/ast_node.py +228 -0
- quantum/core/features/terminal_engine/src/__init__.py +21 -0
- quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
- quantum/core/features/terminal_engine/src/parser.py +361 -0
- quantum/core/features/testing_engine/src/__init__.py +41 -0
- quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
- quantum/core/features/testing_engine/src/parser.py +604 -0
- quantum/core/features/theming/src/__init__.py +48 -0
- quantum/core/features/theming/src/ast_node.py +137 -0
- quantum/core/features/theming/src/presets.py +405 -0
- quantum/core/features/ui_engine/src/__init__.py +20 -0
- quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
- quantum/core/features/ui_engine/src/parser.py +1106 -0
- quantum/core/features/websocket/src/__init__.py +24 -0
- quantum/core/features/websocket/src/ast_node.py +247 -0
- quantum/core/html_compat.py +299 -0
- quantum/core/parser.py +1235 -0
- quantum/core/parser_registry.py +213 -0
- quantum/core/parsers/__init__.py +76 -0
- quantum/core/parsers/ai/__init__.py +12 -0
- quantum/core/parsers/ai/agent_parser.py +106 -0
- quantum/core/parsers/ai/knowledge_parser.py +86 -0
- quantum/core/parsers/ai/llm_parser.py +78 -0
- quantum/core/parsers/ai/team_parser.py +88 -0
- quantum/core/parsers/base.py +322 -0
- quantum/core/parsers/composition/__init__.py +10 -0
- quantum/core/parsers/composition/import_parser.py +50 -0
- quantum/core/parsers/composition/slot_parser.py +48 -0
- quantum/core/parsers/control_flow/__init__.py +11 -0
- quantum/core/parsers/control_flow/if_parser.py +68 -0
- quantum/core/parsers/control_flow/loop_parser.py +105 -0
- quantum/core/parsers/control_flow/set_parser.py +89 -0
- quantum/core/parsers/data/__init__.py +12 -0
- quantum/core/parsers/data/data_parser.py +217 -0
- quantum/core/parsers/data/invoke_parser.py +116 -0
- quantum/core/parsers/data/query_parser.py +188 -0
- quantum/core/parsers/data/transaction_parser.py +77 -0
- quantum/core/parsers/events/__init__.py +9 -0
- quantum/core/parsers/events/dispatch_event_parser.py +44 -0
- quantum/core/parsers/forms/__init__.py +11 -0
- quantum/core/parsers/forms/action_parser.py +54 -0
- quantum/core/parsers/forms/flash_parser.py +34 -0
- quantum/core/parsers/forms/redirect_parser.py +33 -0
- quantum/core/parsers/functions/__init__.py +11 -0
- quantum/core/parsers/functions/function_parser.py +137 -0
- quantum/core/parsers/functions/param_parser.py +66 -0
- quantum/core/parsers/functions/return_parser.py +31 -0
- quantum/core/parsers/html/__init__.py +10 -0
- quantum/core/parsers/html/component_call_parser.py +130 -0
- quantum/core/parsers/html/html_parser.py +115 -0
- quantum/core/parsers/jobs/__init__.py +11 -0
- quantum/core/parsers/jobs/job_parser.py +71 -0
- quantum/core/parsers/jobs/schedule_parser.py +62 -0
- quantum/core/parsers/jobs/thread_parser.py +57 -0
- quantum/core/parsers/messaging/__init__.py +17 -0
- quantum/core/parsers/messaging/message_ack_parser.py +30 -0
- quantum/core/parsers/messaging/message_nack_parser.py +30 -0
- quantum/core/parsers/messaging/message_parser.py +114 -0
- quantum/core/parsers/messaging/queue_parser.py +61 -0
- quantum/core/parsers/messaging/websocket_parser.py +121 -0
- quantum/core/parsers/persistence/__init__.py +9 -0
- quantum/core/parsers/persistence/persist_parser.py +64 -0
- quantum/core/parsers/routing/__init__.py +9 -0
- quantum/core/parsers/routing/route_parser.py +41 -0
- quantum/core/parsers/scripting/__init__.py +12 -0
- quantum/core/parsers/scripting/pyclass_parser.py +62 -0
- quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
- quantum/core/parsers/scripting/pyimport_parser.py +52 -0
- quantum/core/parsers/scripting/python_parser.py +49 -0
- quantum/core/parsers/services/__init__.py +12 -0
- quantum/core/parsers/services/dump_parser.py +52 -0
- quantum/core/parsers/services/file_parser.py +48 -0
- quantum/core/parsers/services/log_parser.py +46 -0
- quantum/core/parsers/services/mail_parser.py +65 -0
- quantum/core/tiers.py +82 -0
- quantum/packages/__init__.py +28 -0
- quantum/packages/manager.py +413 -0
- quantum/packages/manifest.py +351 -0
- quantum/packages/registry.py +399 -0
- quantum/packages/resolver.py +336 -0
- quantum/plugins/__init__.py +33 -0
- quantum/plugins/hooks.py +329 -0
- quantum/plugins/loader.py +479 -0
- quantum/plugins/manifest.py +336 -0
- quantum/plugins/registry.py +371 -0
- quantum/runtime/__init__.py +28 -0
- quantum/runtime/action_handler.py +443 -0
- quantum/runtime/adapters/__init__.py +88 -0
- quantum/runtime/adapters/memory_adapter.py +690 -0
- quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
- quantum/runtime/adapters/redis_adapter.py +582 -0
- quantum/runtime/adapters/sqlite_adapter.py +414 -0
- quantum/runtime/agent_service.py +1133 -0
- quantum/runtime/api_server.py +86 -0
- quantum/runtime/ast_cache.py +506 -0
- quantum/runtime/auth_service.py +267 -0
- quantum/runtime/component.py +990 -0
- quantum/runtime/component_composer.py +319 -0
- quantum/runtime/component_resolver.py +174 -0
- quantum/runtime/database_service.py +598 -0
- quantum/runtime/email_service.py +162 -0
- quantum/runtime/error_handler.py +295 -0
- quantum/runtime/execution_context.py +286 -0
- quantum/runtime/executor_registry.py +171 -0
- quantum/runtime/executors/__init__.py +71 -0
- quantum/runtime/executors/ai/__init__.py +12 -0
- quantum/runtime/executors/ai/agent_executor.py +217 -0
- quantum/runtime/executors/ai/knowledge_executor.py +114 -0
- quantum/runtime/executors/ai/llm_executor.py +153 -0
- quantum/runtime/executors/ai/team_executor.py +171 -0
- quantum/runtime/executors/base.py +262 -0
- quantum/runtime/executors/control_flow/__init__.py +11 -0
- quantum/runtime/executors/control_flow/if_executor.py +93 -0
- quantum/runtime/executors/control_flow/loop_executor.py +307 -0
- quantum/runtime/executors/control_flow/set_executor.py +412 -0
- quantum/runtime/executors/data/__init__.py +12 -0
- quantum/runtime/executors/data/data_executor.py +145 -0
- quantum/runtime/executors/data/invoke_executor.py +176 -0
- quantum/runtime/executors/data/query_executor.py +256 -0
- quantum/runtime/executors/data/transaction_executor.py +91 -0
- quantum/runtime/executors/jobs/__init__.py +11 -0
- quantum/runtime/executors/jobs/job_executor.py +190 -0
- quantum/runtime/executors/jobs/schedule_executor.py +132 -0
- quantum/runtime/executors/jobs/thread_executor.py +127 -0
- quantum/runtime/executors/messaging/__init__.py +17 -0
- quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
- quantum/runtime/executors/messaging/message_executor.py +174 -0
- quantum/runtime/executors/messaging/queue_executor.py +103 -0
- quantum/runtime/executors/messaging/websocket_executor.py +197 -0
- quantum/runtime/executors/scripting/__init__.py +11 -0
- quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
- quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
- quantum/runtime/executors/scripting/python_executor.py +249 -0
- quantum/runtime/executors/services/__init__.py +12 -0
- quantum/runtime/executors/services/dump_executor.py +72 -0
- quantum/runtime/executors/services/file_executor.py +89 -0
- quantum/runtime/executors/services/log_executor.py +77 -0
- quantum/runtime/executors/services/mail_executor.py +81 -0
- quantum/runtime/expression_cache.py +498 -0
- quantum/runtime/file_upload_service.py +326 -0
- quantum/runtime/function_registry.py +118 -0
- quantum/runtime/game_builder.py +166 -0
- quantum/runtime/game_code_generator.py +2371 -0
- quantum/runtime/game_templates.py +2006 -0
- quantum/runtime/godot_code_generator.py +4681 -0
- quantum/runtime/godot_templates.py +1449 -0
- quantum/runtime/job_executor.py +1599 -0
- quantum/runtime/knowledge_service.py +500 -0
- quantum/runtime/llm_cache.py +100 -0
- quantum/runtime/llm_providers.py +704 -0
- quantum/runtime/llm_service.py +287 -0
- quantum/runtime/logging_setup.py +140 -0
- quantum/runtime/message_broker.py +364 -0
- quantum/runtime/message_queue_service.py +571 -0
- quantum/runtime/param_validation.py +184 -0
- quantum/runtime/pypy_compat.py +315 -0
- quantum/runtime/python_bridge.py +698 -0
- quantum/runtime/query_validators.py +304 -0
- quantum/runtime/renderer.py +733 -0
- quantum/runtime/service_container.py +444 -0
- quantum/runtime/terminal_builder.py +76 -0
- quantum/runtime/terminal_code_generator.py +607 -0
- quantum/runtime/terminal_templates.py +243 -0
- quantum/runtime/testing_builder.py +77 -0
- quantum/runtime/testing_code_generator.py +833 -0
- quantum/runtime/testing_templates.py +85 -0
- quantum/runtime/ui_builder.py +188 -0
- quantum/runtime/ui_desktop_adapter.py +1730 -0
- quantum/runtime/ui_desktop_templates.py +307 -0
- quantum/runtime/ui_html_adapter.py +2691 -0
- quantum/runtime/ui_html_templates.py +2297 -0
- quantum/runtime/ui_mobile_adapter.py +1832 -0
- quantum/runtime/ui_mobile_templates.py +1003 -0
- quantum/runtime/ui_textual_adapter.py +1866 -0
- quantum/runtime/ui_textual_templates.py +45 -0
- quantum/runtime/ui_tokens.py +465 -0
- quantum/runtime/ui_validator.py +365 -0
- quantum/runtime/validators.py +256 -0
- quantum/runtime/web_server.py +1766 -0
- quantum/runtime/websocket_adapter.py +501 -0
- quantum/runtime/websocket_service.py +585 -0
- quantum/runtime/websocket_transport.py +289 -0
- quantum/runtime/wsgi.py +101 -0
- quantum/utils/__init__.py +1 -0
- quantum_framework-0.9.0.dist-info/METADATA +244 -0
- quantum_framework-0.9.0.dist-info/RECORD +262 -0
- quantum_framework-0.9.0.dist-info/WHEEL +5 -0
- quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
- quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
- quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Quantum Execution Context - Manages variable scopes and state
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, Optional, List
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class VariableNotFoundError(Exception):
|
|
9
|
+
"""Raised when a variable is not found in any scope"""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExecutionContext:
|
|
14
|
+
"""
|
|
15
|
+
Manages execution context with nested scopes for variables
|
|
16
|
+
Supports: local, function, component, and session scopes
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, parent: Optional['ExecutionContext'] = None):
|
|
20
|
+
self.parent = parent
|
|
21
|
+
self.local_vars: Dict[str, Any] = {}
|
|
22
|
+
self.function_vars: Dict[str, Any] = {}
|
|
23
|
+
self.component_vars: Dict[str, Any] = {}
|
|
24
|
+
|
|
25
|
+
# Phase F: Scope support (session/application/request)
|
|
26
|
+
# Session vars are shared globally (user-specific, persistent)
|
|
27
|
+
if parent is None:
|
|
28
|
+
self.session_vars: Dict[str, Any] = {}
|
|
29
|
+
self.application_vars: Dict[str, Any] = {} # Global state
|
|
30
|
+
self.request_vars: Dict[str, Any] = {} # Request-scoped
|
|
31
|
+
else:
|
|
32
|
+
self.session_vars = parent.session_vars
|
|
33
|
+
self.application_vars = parent.application_vars
|
|
34
|
+
self.request_vars = parent.request_vars
|
|
35
|
+
|
|
36
|
+
def set_variable(self, name: str, value: Any, scope: str = "local"):
|
|
37
|
+
"""
|
|
38
|
+
Set a variable in the specified scope
|
|
39
|
+
|
|
40
|
+
Phase F: Supports session.variable, application.variable, request.variable syntax
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
name: Variable name (can include scope prefix like "session.userId")
|
|
44
|
+
value: Variable value
|
|
45
|
+
scope: 'local', 'function', 'component', 'session', 'application', or 'request'
|
|
46
|
+
"""
|
|
47
|
+
# Phase F: Parse scope prefix from variable name
|
|
48
|
+
if '.' in name:
|
|
49
|
+
prefix, var_name = name.split('.', 1)
|
|
50
|
+
if prefix in ['session', 'application', 'request', 'cookie']:
|
|
51
|
+
if prefix == 'session':
|
|
52
|
+
self.session_vars[var_name] = value
|
|
53
|
+
elif prefix == 'application':
|
|
54
|
+
self.application_vars[var_name] = value
|
|
55
|
+
elif prefix == 'request':
|
|
56
|
+
self.request_vars[var_name] = value
|
|
57
|
+
elif prefix == 'cookie':
|
|
58
|
+
# Store in session with cookie prefix for now
|
|
59
|
+
self.session_vars[f'__cookie_{var_name}'] = value
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
# Normal scope handling
|
|
63
|
+
if scope == "local":
|
|
64
|
+
self.local_vars[name] = value
|
|
65
|
+
elif scope == "function":
|
|
66
|
+
self.function_vars[name] = value
|
|
67
|
+
elif scope == "component":
|
|
68
|
+
# Set in root component context
|
|
69
|
+
ctx = self._get_root_context()
|
|
70
|
+
ctx.component_vars[name] = value
|
|
71
|
+
elif scope == "session":
|
|
72
|
+
# Set in session (shared globally)
|
|
73
|
+
self.session_vars[name] = value
|
|
74
|
+
elif scope == "application":
|
|
75
|
+
self.application_vars[name] = value
|
|
76
|
+
elif scope == "request":
|
|
77
|
+
self.request_vars[name] = value
|
|
78
|
+
else:
|
|
79
|
+
raise ValueError(f"Invalid scope: {scope}")
|
|
80
|
+
|
|
81
|
+
def update_variable(self, name: str, value: Any):
|
|
82
|
+
"""
|
|
83
|
+
Update a variable in whatever scope it already exists, or create in local scope if new
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
name: Variable name (can include scope prefix like "session.userId", "application.messages")
|
|
87
|
+
value: New value
|
|
88
|
+
"""
|
|
89
|
+
# Handle scope prefix (session.X, application.X, request.X)
|
|
90
|
+
if '.' in name:
|
|
91
|
+
prefix, var_name = name.split('.', 1)
|
|
92
|
+
if prefix in ['session', 'application', 'request', 'cookie']:
|
|
93
|
+
if prefix == 'session':
|
|
94
|
+
self.session_vars[var_name] = value
|
|
95
|
+
elif prefix == 'application':
|
|
96
|
+
self.application_vars[var_name] = value
|
|
97
|
+
elif prefix == 'request':
|
|
98
|
+
self.request_vars[var_name] = value
|
|
99
|
+
elif prefix == 'cookie':
|
|
100
|
+
self.session_vars[f'__cookie_{var_name}'] = value
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
# Check local scope first
|
|
104
|
+
if name in self.local_vars:
|
|
105
|
+
self.local_vars[name] = value
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
# Check function scope
|
|
109
|
+
if name in self.function_vars:
|
|
110
|
+
self.function_vars[name] = value
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
# Check component scope (including parent contexts)
|
|
114
|
+
ctx = self
|
|
115
|
+
while ctx:
|
|
116
|
+
if name in ctx.component_vars:
|
|
117
|
+
ctx.component_vars[name] = value
|
|
118
|
+
return
|
|
119
|
+
ctx = ctx.parent
|
|
120
|
+
|
|
121
|
+
# Check session scope
|
|
122
|
+
if name in self.session_vars:
|
|
123
|
+
self.session_vars[name] = value
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
# Variable doesn't exist - create in local scope
|
|
127
|
+
self.local_vars[name] = value
|
|
128
|
+
|
|
129
|
+
def get_variable(self, name: str) -> Any:
|
|
130
|
+
"""
|
|
131
|
+
Get a variable value, searching through scopes in order:
|
|
132
|
+
local -> function -> component -> session -> application -> request -> parent
|
|
133
|
+
|
|
134
|
+
Phase F: Supports session.variable, application.variable, request.variable syntax
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
name: Variable name (can include scope prefix like "session.userId")
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Variable value
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
VariableNotFoundError: If variable not found in any scope
|
|
144
|
+
"""
|
|
145
|
+
# Phase F: Parse scope prefix from variable name
|
|
146
|
+
if '.' in name:
|
|
147
|
+
prefix, var_name = name.split('.', 1)
|
|
148
|
+
if prefix in ['session', 'application', 'request', 'cookie']:
|
|
149
|
+
if prefix == 'session':
|
|
150
|
+
return self.session_vars.get(var_name, '')
|
|
151
|
+
elif prefix == 'application':
|
|
152
|
+
return self.application_vars.get(var_name, '')
|
|
153
|
+
elif prefix == 'request':
|
|
154
|
+
return self.request_vars.get(var_name, '')
|
|
155
|
+
elif prefix == 'cookie':
|
|
156
|
+
return self.session_vars.get(f'__cookie_{var_name}', '')
|
|
157
|
+
|
|
158
|
+
# Search local scope first
|
|
159
|
+
if name in self.local_vars:
|
|
160
|
+
return self.local_vars[name]
|
|
161
|
+
|
|
162
|
+
# Search function scope
|
|
163
|
+
if name in self.function_vars:
|
|
164
|
+
return self.function_vars[name]
|
|
165
|
+
|
|
166
|
+
# Search component scope (go to root)
|
|
167
|
+
root_ctx = self._get_root_context()
|
|
168
|
+
if name in root_ctx.component_vars:
|
|
169
|
+
return root_ctx.component_vars[name]
|
|
170
|
+
|
|
171
|
+
# Search session scope
|
|
172
|
+
if name in self.session_vars:
|
|
173
|
+
return self.session_vars[name]
|
|
174
|
+
|
|
175
|
+
# Search application scope
|
|
176
|
+
if name in self.application_vars:
|
|
177
|
+
return self.application_vars[name]
|
|
178
|
+
|
|
179
|
+
# Search request scope
|
|
180
|
+
if name in self.request_vars:
|
|
181
|
+
return self.request_vars[name]
|
|
182
|
+
|
|
183
|
+
# Search parent context
|
|
184
|
+
if self.parent:
|
|
185
|
+
try:
|
|
186
|
+
return self.parent.get_variable(name)
|
|
187
|
+
except VariableNotFoundError:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
raise VariableNotFoundError(f"Variable '{name}' not found in any scope")
|
|
191
|
+
|
|
192
|
+
def has_variable(self, name: str) -> bool:
|
|
193
|
+
"""Check if variable exists in any scope"""
|
|
194
|
+
try:
|
|
195
|
+
self.get_variable(name)
|
|
196
|
+
return True
|
|
197
|
+
except VariableNotFoundError:
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
def delete_variable(self, name: str, scope: str = "local") -> bool:
|
|
201
|
+
"""
|
|
202
|
+
Delete a variable from the specified scope
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
name: Variable name
|
|
206
|
+
scope: 'local', 'function', 'component', or 'session'
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
True if deleted, False if not found
|
|
210
|
+
"""
|
|
211
|
+
if scope == "local":
|
|
212
|
+
if name in self.local_vars:
|
|
213
|
+
del self.local_vars[name]
|
|
214
|
+
return True
|
|
215
|
+
elif scope == "function":
|
|
216
|
+
if name in self.function_vars:
|
|
217
|
+
del self.function_vars[name]
|
|
218
|
+
return True
|
|
219
|
+
elif scope == "component":
|
|
220
|
+
root_ctx = self._get_root_context()
|
|
221
|
+
if name in root_ctx.component_vars:
|
|
222
|
+
del root_ctx.component_vars[name]
|
|
223
|
+
return True
|
|
224
|
+
elif scope == "session":
|
|
225
|
+
if name in self.session_vars:
|
|
226
|
+
del self.session_vars[name]
|
|
227
|
+
return True
|
|
228
|
+
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
def create_child_context(self) -> 'ExecutionContext':
|
|
232
|
+
"""Create a child context (for nested scopes like loops/functions)"""
|
|
233
|
+
return ExecutionContext(parent=self)
|
|
234
|
+
|
|
235
|
+
def get_all_variables(self) -> Dict[str, Any]:
|
|
236
|
+
"""
|
|
237
|
+
Get all variables from all scopes as a flat dictionary
|
|
238
|
+
(for backward compatibility with existing code)
|
|
239
|
+
|
|
240
|
+
Phase F: Also includes scoped variables with dot notation (session.variable, application.variable, request.variable)
|
|
241
|
+
"""
|
|
242
|
+
all_vars = {}
|
|
243
|
+
|
|
244
|
+
# Start with parent vars (if any)
|
|
245
|
+
if self.parent:
|
|
246
|
+
all_vars.update(self.parent.get_all_variables())
|
|
247
|
+
|
|
248
|
+
# Phase F: Add session vars (both direct and with scope prefix)
|
|
249
|
+
all_vars.update(self.session_vars)
|
|
250
|
+
for key, value in self.session_vars.items():
|
|
251
|
+
all_vars[f'session.{key}'] = value
|
|
252
|
+
|
|
253
|
+
# Phase F: Add application vars (both direct and with scope prefix)
|
|
254
|
+
all_vars.update(self.application_vars)
|
|
255
|
+
for key, value in self.application_vars.items():
|
|
256
|
+
all_vars[f'application.{key}'] = value
|
|
257
|
+
|
|
258
|
+
# Phase F: Add request vars (both direct and with scope prefix)
|
|
259
|
+
all_vars.update(self.request_vars)
|
|
260
|
+
for key, value in self.request_vars.items():
|
|
261
|
+
all_vars[f'request.{key}'] = value
|
|
262
|
+
|
|
263
|
+
# Add component vars
|
|
264
|
+
root_ctx = self._get_root_context()
|
|
265
|
+
all_vars.update(root_ctx.component_vars)
|
|
266
|
+
|
|
267
|
+
# Add function vars
|
|
268
|
+
all_vars.update(self.function_vars)
|
|
269
|
+
|
|
270
|
+
# Add local vars (highest priority)
|
|
271
|
+
all_vars.update(self.local_vars)
|
|
272
|
+
|
|
273
|
+
return all_vars
|
|
274
|
+
|
|
275
|
+
def _get_root_context(self) -> 'ExecutionContext':
|
|
276
|
+
"""Get the root (component-level) context"""
|
|
277
|
+
ctx = self
|
|
278
|
+
while ctx.parent is not None:
|
|
279
|
+
ctx = ctx.parent
|
|
280
|
+
return ctx
|
|
281
|
+
|
|
282
|
+
def __repr__(self) -> str:
|
|
283
|
+
return (f"ExecutionContext(local={len(self.local_vars)}, "
|
|
284
|
+
f"function={len(self.function_vars)}, "
|
|
285
|
+
f"component={len(self.component_vars)}, "
|
|
286
|
+
f"session={len(self.session_vars)})")
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Executor Registry - Central dispatch for node execution
|
|
3
|
+
|
|
4
|
+
Replaces the large if-elif chain in component.py with a type-based lookup.
|
|
5
|
+
Executors register themselves for specific node types, and the registry
|
|
6
|
+
dispatches execution to the correct executor.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Dict, Type, Any, Optional, List, TYPE_CHECKING
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from quantum.runtime.executors.base import BaseExecutor
|
|
14
|
+
from quantum.runtime.execution_context import ExecutionContext
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ExecutorNotFoundError(Exception):
|
|
20
|
+
"""Raised when no executor is registered for a node type"""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ExecutorRegistry:
|
|
25
|
+
"""
|
|
26
|
+
Registry for node executors.
|
|
27
|
+
|
|
28
|
+
Maps AST node types to their executors and dispatches execution.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
registry = ExecutorRegistry()
|
|
32
|
+
registry.register(LoopExecutor(runtime))
|
|
33
|
+
registry.register(IfExecutor(runtime))
|
|
34
|
+
|
|
35
|
+
# Later, execute any node
|
|
36
|
+
result = registry.execute(loop_node, context)
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self):
|
|
40
|
+
"""Initialize empty registry"""
|
|
41
|
+
self._executors: Dict[Type, 'BaseExecutor'] = {}
|
|
42
|
+
self._fallback: Optional['BaseExecutor'] = None
|
|
43
|
+
|
|
44
|
+
def register(self, executor: 'BaseExecutor') -> 'ExecutorRegistry':
|
|
45
|
+
"""
|
|
46
|
+
Register an executor for its handled node types.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
executor: Executor instance to register
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Self for chaining
|
|
53
|
+
"""
|
|
54
|
+
for node_type in executor.handles:
|
|
55
|
+
if node_type in self._executors:
|
|
56
|
+
logger.warning(
|
|
57
|
+
f"Overwriting executor for {node_type.__name__}: "
|
|
58
|
+
f"{self._executors[node_type].__class__.__name__} -> "
|
|
59
|
+
f"{executor.__class__.__name__}"
|
|
60
|
+
)
|
|
61
|
+
self._executors[node_type] = executor
|
|
62
|
+
logger.debug(f"Registered {executor.__class__.__name__} for {node_type.__name__}")
|
|
63
|
+
|
|
64
|
+
return self
|
|
65
|
+
|
|
66
|
+
def register_all(self, executors: List['BaseExecutor']) -> 'ExecutorRegistry':
|
|
67
|
+
"""
|
|
68
|
+
Register multiple executors at once.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
executors: List of executor instances
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Self for chaining
|
|
75
|
+
"""
|
|
76
|
+
for executor in executors:
|
|
77
|
+
self.register(executor)
|
|
78
|
+
return self
|
|
79
|
+
|
|
80
|
+
def set_fallback(self, executor: 'BaseExecutor') -> 'ExecutorRegistry':
|
|
81
|
+
"""
|
|
82
|
+
Set a fallback executor for unregistered node types.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
executor: Fallback executor instance
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Self for chaining
|
|
89
|
+
"""
|
|
90
|
+
self._fallback = executor
|
|
91
|
+
return self
|
|
92
|
+
|
|
93
|
+
def get_executor(self, node: Any) -> Optional['BaseExecutor']:
|
|
94
|
+
"""
|
|
95
|
+
Get the executor for a node.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
node: AST node instance
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Executor instance or None if not found
|
|
102
|
+
"""
|
|
103
|
+
node_type = type(node)
|
|
104
|
+
return self._executors.get(node_type)
|
|
105
|
+
|
|
106
|
+
def has_executor(self, node_type: Type) -> bool:
|
|
107
|
+
"""
|
|
108
|
+
Check if an executor is registered for a node type.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
node_type: AST node class
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
True if executor exists
|
|
115
|
+
"""
|
|
116
|
+
return node_type in self._executors
|
|
117
|
+
|
|
118
|
+
def execute(self, node: Any, exec_context: 'ExecutionContext') -> Any:
|
|
119
|
+
"""
|
|
120
|
+
Execute a node using its registered executor.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
node: AST node to execute
|
|
124
|
+
exec_context: Execution context
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Result of execution
|
|
128
|
+
|
|
129
|
+
Raises:
|
|
130
|
+
ExecutorNotFoundError: If no executor is registered for the node type
|
|
131
|
+
"""
|
|
132
|
+
node_type = type(node)
|
|
133
|
+
executor = self._executors.get(node_type)
|
|
134
|
+
|
|
135
|
+
if executor is None:
|
|
136
|
+
if self._fallback is not None:
|
|
137
|
+
logger.debug(f"Using fallback executor for {node_type.__name__}")
|
|
138
|
+
return self._fallback.execute(node, exec_context)
|
|
139
|
+
|
|
140
|
+
raise ExecutorNotFoundError(
|
|
141
|
+
f"No executor registered for {node_type.__name__}. "
|
|
142
|
+
f"Registered types: {list(t.__name__ for t in self._executors.keys())}"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return executor.execute(node, exec_context)
|
|
146
|
+
|
|
147
|
+
def can_execute(self, node: Any) -> bool:
|
|
148
|
+
"""
|
|
149
|
+
Check if a node can be executed.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
node: AST node instance
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
True if an executor exists for this node type
|
|
156
|
+
"""
|
|
157
|
+
return type(node) in self._executors or self._fallback is not None
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def registered_types(self) -> List[Type]:
|
|
161
|
+
"""Get list of all registered node types"""
|
|
162
|
+
return list(self._executors.keys())
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def executor_count(self) -> int:
|
|
166
|
+
"""Get number of registered executors (unique)"""
|
|
167
|
+
return len(set(self._executors.values()))
|
|
168
|
+
|
|
169
|
+
def __repr__(self) -> str:
|
|
170
|
+
types = [t.__name__ for t in self._executors.keys()]
|
|
171
|
+
return f"ExecutorRegistry({len(types)} types: {types[:5]}{'...' if len(types) > 5 else ''})"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Quantum Executors Package
|
|
3
|
+
|
|
4
|
+
Modular executors for AST node execution. Each executor handles specific node types.
|
|
5
|
+
|
|
6
|
+
Categories:
|
|
7
|
+
- control_flow: if, loop, set
|
|
8
|
+
- data: query, invoke, data, transaction
|
|
9
|
+
- services: log, dump, file, mail
|
|
10
|
+
- ai: llm, agent, team, knowledge
|
|
11
|
+
- messaging: websocket, message, queue, subscribe
|
|
12
|
+
- jobs: schedule, thread, job
|
|
13
|
+
- scripting: python, pyimport, pyclass
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from .base import BaseExecutor, ExecutorError
|
|
17
|
+
|
|
18
|
+
# Control flow executors
|
|
19
|
+
from .control_flow import IfExecutor, LoopExecutor, SetExecutor
|
|
20
|
+
|
|
21
|
+
# Data executors
|
|
22
|
+
from .data import QueryExecutor, InvokeExecutor, DataExecutor, TransactionExecutor
|
|
23
|
+
|
|
24
|
+
# Service executors
|
|
25
|
+
from .services import LogExecutor, DumpExecutor, FileExecutor, MailExecutor
|
|
26
|
+
|
|
27
|
+
# AI executors
|
|
28
|
+
from .ai import LLMExecutor, AgentExecutor, TeamExecutor, KnowledgeExecutor
|
|
29
|
+
|
|
30
|
+
# Messaging executors
|
|
31
|
+
from .messaging import (
|
|
32
|
+
WebSocketExecutor, WebSocketSendExecutor, WebSocketCloseExecutor,
|
|
33
|
+
MessageExecutor, SubscribeExecutor, QueueExecutor,
|
|
34
|
+
MessageAckExecutor, MessageNackExecutor
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Jobs executors
|
|
38
|
+
from .jobs import ScheduleExecutor, ThreadExecutor, JobExecutor
|
|
39
|
+
|
|
40
|
+
# Scripting executors
|
|
41
|
+
from .scripting import PythonExecutor, PyImportExecutor, PyClassExecutor
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
# Base
|
|
46
|
+
'BaseExecutor', 'ExecutorError',
|
|
47
|
+
|
|
48
|
+
# Control flow
|
|
49
|
+
'IfExecutor', 'LoopExecutor', 'SetExecutor',
|
|
50
|
+
|
|
51
|
+
# Data
|
|
52
|
+
'QueryExecutor', 'InvokeExecutor', 'DataExecutor', 'TransactionExecutor',
|
|
53
|
+
|
|
54
|
+
# Services
|
|
55
|
+
'LogExecutor', 'DumpExecutor', 'FileExecutor', 'MailExecutor',
|
|
56
|
+
|
|
57
|
+
# AI
|
|
58
|
+
'LLMExecutor', 'AgentExecutor', 'TeamExecutor', 'KnowledgeExecutor',
|
|
59
|
+
|
|
60
|
+
# Messaging
|
|
61
|
+
'WebSocketExecutor', 'WebSocketSendExecutor', 'WebSocketCloseExecutor',
|
|
62
|
+
'MessageExecutor', 'SubscribeExecutor', 'QueueExecutor',
|
|
63
|
+
|
|
64
|
+
# Jobs
|
|
65
|
+
'ScheduleExecutor', 'ThreadExecutor', 'JobExecutor',
|
|
66
|
+
|
|
67
|
+
# Scripting
|
|
68
|
+
'PythonExecutor', 'PyImportExecutor', 'PyClassExecutor',
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
__version__ = '1.0.0'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AI Executors
|
|
3
|
+
|
|
4
|
+
Executors for AI operations: llm, agent, team, knowledge.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .llm_executor import LLMExecutor
|
|
8
|
+
from .agent_executor import AgentExecutor
|
|
9
|
+
from .team_executor import TeamExecutor
|
|
10
|
+
from .knowledge_executor import KnowledgeExecutor
|
|
11
|
+
|
|
12
|
+
__all__ = ['LLMExecutor', 'AgentExecutor', 'TeamExecutor', 'KnowledgeExecutor']
|