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,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Parser for q:dump - Variable Inspection
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import xml.etree.ElementTree as ET
|
|
6
|
+
from .ast_node import DumpNode
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def parse_dump(dump_element: ET.Element) -> DumpNode:
|
|
10
|
+
"""
|
|
11
|
+
Parse a <q:dump> element into a DumpNode
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
dump_element: The XML element representing the dump statement
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
DumpNode instance
|
|
18
|
+
|
|
19
|
+
Raises:
|
|
20
|
+
ValueError: If required attributes are missing or invalid
|
|
21
|
+
"""
|
|
22
|
+
# Get required attribute
|
|
23
|
+
var = dump_element.get('var')
|
|
24
|
+
|
|
25
|
+
# Get optional attributes
|
|
26
|
+
label = dump_element.get('label')
|
|
27
|
+
format_str = dump_element.get('format', 'html')
|
|
28
|
+
depth_str = dump_element.get('depth', '10')
|
|
29
|
+
when = dump_element.get('when')
|
|
30
|
+
expand_str = dump_element.get('expand', '2')
|
|
31
|
+
show_types_str = dump_element.get('show_types', 'true')
|
|
32
|
+
|
|
33
|
+
# Parse depth
|
|
34
|
+
try:
|
|
35
|
+
depth = int(depth_str) if depth_str else 10
|
|
36
|
+
except ValueError:
|
|
37
|
+
depth = 10
|
|
38
|
+
|
|
39
|
+
# Parse expand
|
|
40
|
+
try:
|
|
41
|
+
expand = int(expand_str) if expand_str else 2
|
|
42
|
+
except ValueError:
|
|
43
|
+
expand = 2
|
|
44
|
+
|
|
45
|
+
# Parse show_types
|
|
46
|
+
show_types = show_types_str.lower() == 'true' if show_types_str else True
|
|
47
|
+
|
|
48
|
+
# Validate no child elements (q:dump should be self-closing)
|
|
49
|
+
if len(dump_element) > 0:
|
|
50
|
+
raise ValueError("Dump tag must be self-closing")
|
|
51
|
+
|
|
52
|
+
# Create and return DumpNode (validation happens in __init__)
|
|
53
|
+
return DumpNode(
|
|
54
|
+
var=var,
|
|
55
|
+
label=label,
|
|
56
|
+
format=format_str,
|
|
57
|
+
depth=depth,
|
|
58
|
+
when=when,
|
|
59
|
+
expand=expand,
|
|
60
|
+
show_types=show_types
|
|
61
|
+
)
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime service for q:dump - Variable Inspection
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any, Dict, Set
|
|
7
|
+
from html import escape
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DumpService:
|
|
11
|
+
"""
|
|
12
|
+
Service to handle variable inspection and formatted output
|
|
13
|
+
|
|
14
|
+
Phase 1 Features:
|
|
15
|
+
- HTML, JSON, and text output formats
|
|
16
|
+
- Depth limiting
|
|
17
|
+
- Type information
|
|
18
|
+
- Circular reference detection
|
|
19
|
+
|
|
20
|
+
Phase 2 Features (TODO):
|
|
21
|
+
- Rich library integration for beautiful output
|
|
22
|
+
- Expandable/collapsible trees
|
|
23
|
+
- Search within dumps
|
|
24
|
+
- Side-by-side comparison
|
|
25
|
+
- Custom themes
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
"""Initialize the dump service"""
|
|
30
|
+
self._seen_objects: Set[int] = set()
|
|
31
|
+
|
|
32
|
+
def dump(
|
|
33
|
+
self,
|
|
34
|
+
var: Any,
|
|
35
|
+
label: str,
|
|
36
|
+
format: str = 'html',
|
|
37
|
+
depth: int = 10,
|
|
38
|
+
current_depth: int = 0
|
|
39
|
+
) -> str:
|
|
40
|
+
"""
|
|
41
|
+
Generate formatted dump output for a variable
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
var: Variable to inspect
|
|
45
|
+
label: Label for the dump
|
|
46
|
+
format: Output format (html, json, text)
|
|
47
|
+
depth: Maximum nesting depth
|
|
48
|
+
current_depth: Current recursion depth
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Formatted string output
|
|
52
|
+
"""
|
|
53
|
+
# Reset seen objects for new dump
|
|
54
|
+
if current_depth == 0:
|
|
55
|
+
self._seen_objects = set()
|
|
56
|
+
|
|
57
|
+
if format == 'json':
|
|
58
|
+
return self._dump_json(var, label)
|
|
59
|
+
elif format == 'text':
|
|
60
|
+
return self._dump_text(var, label, depth, current_depth)
|
|
61
|
+
else: # html (default)
|
|
62
|
+
return self._dump_html(var, label, depth, current_depth)
|
|
63
|
+
|
|
64
|
+
def _dump_json(self, var: Any, label: str) -> str:
|
|
65
|
+
"""Dump as pretty-printed JSON"""
|
|
66
|
+
output = [f"=== {label} ==="]
|
|
67
|
+
try:
|
|
68
|
+
json_str = json.dumps(var, indent=2, default=str)
|
|
69
|
+
output.append(json_str)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
output.append(f"Error dumping as JSON: {e}")
|
|
72
|
+
output.append(f"Type: {type(var).__name__}")
|
|
73
|
+
output.append(f"Value: {str(var)}")
|
|
74
|
+
return '\n'.join(output)
|
|
75
|
+
|
|
76
|
+
def _dump_text(
|
|
77
|
+
self,
|
|
78
|
+
var: Any,
|
|
79
|
+
label: str,
|
|
80
|
+
max_depth: int,
|
|
81
|
+
current_depth: int,
|
|
82
|
+
prefix: str = ''
|
|
83
|
+
) -> str:
|
|
84
|
+
"""Dump as plain text tree structure"""
|
|
85
|
+
if current_depth == 0:
|
|
86
|
+
output = [f"=== {label} ==="]
|
|
87
|
+
else:
|
|
88
|
+
output = []
|
|
89
|
+
|
|
90
|
+
# Check depth limit
|
|
91
|
+
if current_depth >= max_depth:
|
|
92
|
+
output.append(f"{prefix}... (max depth reached)")
|
|
93
|
+
return '\n'.join(output)
|
|
94
|
+
|
|
95
|
+
# Get type name
|
|
96
|
+
type_name = type(var).__name__
|
|
97
|
+
|
|
98
|
+
# Handle None/null
|
|
99
|
+
if var is None:
|
|
100
|
+
output.append(f"{prefix}{label} => null")
|
|
101
|
+
return '\n'.join(output)
|
|
102
|
+
|
|
103
|
+
# Handle primitives
|
|
104
|
+
if isinstance(var, (str, int, float, bool)):
|
|
105
|
+
if isinstance(var, str):
|
|
106
|
+
value_repr = f'"{var}"'
|
|
107
|
+
else:
|
|
108
|
+
value_repr = str(var).lower() if isinstance(var, bool) else str(var)
|
|
109
|
+
output.append(f"{prefix}{label} => {value_repr} ({type_name})")
|
|
110
|
+
return '\n'.join(output)
|
|
111
|
+
|
|
112
|
+
# Handle dictionaries/objects
|
|
113
|
+
if isinstance(var, dict):
|
|
114
|
+
output.append(f"{prefix}{label} (dict, {len(var)} items):")
|
|
115
|
+
for key, value in var.items():
|
|
116
|
+
sub_output = self._dump_text(
|
|
117
|
+
value,
|
|
118
|
+
str(key),
|
|
119
|
+
max_depth,
|
|
120
|
+
current_depth + 1,
|
|
121
|
+
prefix + ' '
|
|
122
|
+
)
|
|
123
|
+
# Skip the header line for nested items
|
|
124
|
+
sub_lines = sub_output.split('\n')
|
|
125
|
+
if current_depth > 0 and sub_lines:
|
|
126
|
+
output.extend(sub_lines)
|
|
127
|
+
else:
|
|
128
|
+
output.append(sub_output)
|
|
129
|
+
return '\n'.join(output)
|
|
130
|
+
|
|
131
|
+
# Handle lists/arrays
|
|
132
|
+
if isinstance(var, (list, tuple)):
|
|
133
|
+
output.append(f"{prefix}{label} ({type_name}, {len(var)} items):")
|
|
134
|
+
for i, item in enumerate(var):
|
|
135
|
+
sub_output = self._dump_text(
|
|
136
|
+
item,
|
|
137
|
+
f"[{i}]",
|
|
138
|
+
max_depth,
|
|
139
|
+
current_depth + 1,
|
|
140
|
+
prefix + ' '
|
|
141
|
+
)
|
|
142
|
+
sub_lines = sub_output.split('\n')
|
|
143
|
+
if current_depth > 0 and sub_lines:
|
|
144
|
+
output.extend(sub_lines)
|
|
145
|
+
else:
|
|
146
|
+
output.append(sub_output)
|
|
147
|
+
return '\n'.join(output)
|
|
148
|
+
|
|
149
|
+
# Handle other types
|
|
150
|
+
output.append(f"{prefix}{label} => {str(var)} ({type_name})")
|
|
151
|
+
return '\n'.join(output)
|
|
152
|
+
|
|
153
|
+
def _dump_html(
|
|
154
|
+
self,
|
|
155
|
+
var: Any,
|
|
156
|
+
label: str,
|
|
157
|
+
max_depth: int,
|
|
158
|
+
current_depth: int
|
|
159
|
+
) -> str:
|
|
160
|
+
"""Dump as HTML with styling"""
|
|
161
|
+
if current_depth == 0:
|
|
162
|
+
output = [
|
|
163
|
+
'<div class="quantum-dump" style="font-family: monospace; background: #f5f5f5; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px;">',
|
|
164
|
+
f'<h4 style="margin: 0 0 10px 0; color: #333;">{escape(label)}</h4>'
|
|
165
|
+
]
|
|
166
|
+
else:
|
|
167
|
+
output = []
|
|
168
|
+
|
|
169
|
+
# Check depth limit
|
|
170
|
+
if current_depth >= max_depth:
|
|
171
|
+
output.append(f'<span style="color: #999;">... (max depth reached)</span>')
|
|
172
|
+
if current_depth == 0:
|
|
173
|
+
output.append('</div>')
|
|
174
|
+
return ''.join(output)
|
|
175
|
+
|
|
176
|
+
# Get type name
|
|
177
|
+
type_name = type(var).__name__
|
|
178
|
+
|
|
179
|
+
# Handle None/null
|
|
180
|
+
if var is None:
|
|
181
|
+
output.append('<span style="color: #999; font-style: italic;">null</span>')
|
|
182
|
+
if current_depth == 0:
|
|
183
|
+
output.append('</div>')
|
|
184
|
+
return ''.join(output)
|
|
185
|
+
|
|
186
|
+
# Handle primitives
|
|
187
|
+
if isinstance(var, bool):
|
|
188
|
+
color = '#008800' if var else '#cc0000'
|
|
189
|
+
output.append(f'<span style="color: {color}; font-weight: bold;">{str(var).lower()}</span>')
|
|
190
|
+
output.append(f' <span style="color: #999; font-size: 0.9em;">(boolean)</span>')
|
|
191
|
+
elif isinstance(var, (int, float)):
|
|
192
|
+
output.append(f'<span style="color: #0066cc; font-weight: bold;">{var}</span>')
|
|
193
|
+
output.append(f' <span style="color: #999; font-size: 0.9em;">({type_name})</span>')
|
|
194
|
+
elif isinstance(var, str):
|
|
195
|
+
output.append(f'<span style="color: #cc6600;">"{escape(var)}"</span>')
|
|
196
|
+
output.append(f' <span style="color: #999; font-size: 0.9em;">(string)</span>')
|
|
197
|
+
# Handle dictionaries/objects
|
|
198
|
+
elif isinstance(var, dict):
|
|
199
|
+
output.append(f'<span style="color: #999;">(dict, {len(var)} items)</span>')
|
|
200
|
+
output.append('<ul style="margin: 5px 0; padding-left: 20px; list-style: none;">')
|
|
201
|
+
for key, value in var.items():
|
|
202
|
+
output.append('<li style="margin: 2px 0;">')
|
|
203
|
+
output.append(f'<span style="color: #660066; font-weight: bold;">{escape(str(key))}</span>: ')
|
|
204
|
+
output.append(self._dump_html(value, '', max_depth, current_depth + 1))
|
|
205
|
+
output.append('</li>')
|
|
206
|
+
output.append('</ul>')
|
|
207
|
+
# Handle lists/arrays
|
|
208
|
+
elif isinstance(var, (list, tuple)):
|
|
209
|
+
output.append(f'<span style="color: #999;">({type_name}, {len(var)} items)</span>')
|
|
210
|
+
output.append('<ul style="margin: 5px 0; padding-left: 20px; list-style: none;">')
|
|
211
|
+
for i, item in enumerate(var):
|
|
212
|
+
output.append('<li style="margin: 2px 0;">')
|
|
213
|
+
output.append(f'<span style="color: #660066; font-weight: bold;">[{i}]</span>: ')
|
|
214
|
+
output.append(self._dump_html(item, '', max_depth, current_depth + 1))
|
|
215
|
+
output.append('</li>')
|
|
216
|
+
output.append('</ul>')
|
|
217
|
+
# Handle other types
|
|
218
|
+
else:
|
|
219
|
+
output.append(f'<span style="color: #666;">{escape(str(var))}</span>')
|
|
220
|
+
output.append(f' <span style="color: #999; font-size: 0.9em;">({type_name})</span>')
|
|
221
|
+
|
|
222
|
+
if current_depth == 0:
|
|
223
|
+
output.append('</div>')
|
|
224
|
+
|
|
225
|
+
return ''.join(output)
|
|
226
|
+
|
|
227
|
+
def should_dump(self, condition: Any) -> bool:
|
|
228
|
+
"""
|
|
229
|
+
Evaluate if dumping should occur based on 'when' condition
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
condition: Evaluated condition value
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
True if should dump, False otherwise
|
|
236
|
+
"""
|
|
237
|
+
# If no condition, always dump
|
|
238
|
+
if condition is None:
|
|
239
|
+
return True
|
|
240
|
+
|
|
241
|
+
# Evaluate boolean condition
|
|
242
|
+
if isinstance(condition, bool):
|
|
243
|
+
return condition
|
|
244
|
+
|
|
245
|
+
# Truthy evaluation for other types
|
|
246
|
+
return bool(condition)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AST Node for Functions (q:function)
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Dict, Any, List, Optional
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
# Import base class
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from quantum.core.ast_nodes import QuantumNode, QuantumParam
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class RestConfig:
|
|
16
|
+
"""REST configuration for a function - OPTIONAL"""
|
|
17
|
+
# Required (if REST enabled)
|
|
18
|
+
endpoint: str
|
|
19
|
+
method: str = "GET"
|
|
20
|
+
|
|
21
|
+
# Optional (with sensible defaults)
|
|
22
|
+
produces: str = "application/json"
|
|
23
|
+
consumes: str = "application/json"
|
|
24
|
+
auth: Optional[str] = None # None = no auth, or: bearer, basic, apikey
|
|
25
|
+
roles: List[str] = None # None = no role check
|
|
26
|
+
rate_limit: Optional[str] = None # "100/minute"
|
|
27
|
+
cors: bool = False
|
|
28
|
+
status: int = 200 # Default status code
|
|
29
|
+
|
|
30
|
+
def __post_init__(self):
|
|
31
|
+
if self.roles is None:
|
|
32
|
+
self.roles = []
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class FunctionNode(QuantumNode):
|
|
36
|
+
"""Represents a <q:function>"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, name: str):
|
|
39
|
+
# ========== CORE (required) ==========
|
|
40
|
+
self.name = name
|
|
41
|
+
self.return_type = "any"
|
|
42
|
+
self.scope = "component" # component, global, api
|
|
43
|
+
self.access = "public" # public, private, protected
|
|
44
|
+
self.params: List[QuantumParam] = []
|
|
45
|
+
self.body: List[QuantumNode] = []
|
|
46
|
+
|
|
47
|
+
# ========== OPTIONAL LAYERS ==========
|
|
48
|
+
|
|
49
|
+
# Layer 1: Documentation
|
|
50
|
+
self.description = None
|
|
51
|
+
self.hint = None
|
|
52
|
+
|
|
53
|
+
# Layer 2: Validation
|
|
54
|
+
self.validate_params = False # Auto-validate params
|
|
55
|
+
|
|
56
|
+
# Layer 3: Performance
|
|
57
|
+
self.cache = False
|
|
58
|
+
self.cache_ttl = None # seconds
|
|
59
|
+
self.memoize = False
|
|
60
|
+
self.pure = False
|
|
61
|
+
|
|
62
|
+
# Layer 4: Behavior
|
|
63
|
+
self.async_func = False
|
|
64
|
+
self.retry = 0
|
|
65
|
+
self.timeout = None # seconds
|
|
66
|
+
|
|
67
|
+
# Layer 5: REST API (completely optional)
|
|
68
|
+
self.rest_config: Optional[RestConfig] = None
|
|
69
|
+
|
|
70
|
+
# Back-reference to container
|
|
71
|
+
self.container: Optional['ComponentNode'] = None
|
|
72
|
+
|
|
73
|
+
def is_rest_enabled(self) -> bool:
|
|
74
|
+
"""Check if function has REST configuration"""
|
|
75
|
+
return self.rest_config is not None
|
|
76
|
+
|
|
77
|
+
def enable_rest(self, endpoint: str, method: str = "GET"):
|
|
78
|
+
"""Enable REST for this function"""
|
|
79
|
+
self.rest_config = RestConfig(
|
|
80
|
+
endpoint=endpoint,
|
|
81
|
+
method=method
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def is_private(self) -> bool:
|
|
85
|
+
"""Check if function is private (starts with _ or access=private)"""
|
|
86
|
+
return self.access == "private" or self.name.startswith('_')
|
|
87
|
+
|
|
88
|
+
def add_param(self, param: QuantumParam):
|
|
89
|
+
"""Add parameter to function"""
|
|
90
|
+
self.params.append(param)
|
|
91
|
+
|
|
92
|
+
def add_statement(self, statement: QuantumNode):
|
|
93
|
+
"""Add statement to function body"""
|
|
94
|
+
self.body.append(statement)
|
|
95
|
+
|
|
96
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
97
|
+
result = {
|
|
98
|
+
"type": "function",
|
|
99
|
+
"name": self.name,
|
|
100
|
+
"return_type": self.return_type,
|
|
101
|
+
"scope": self.scope,
|
|
102
|
+
"access": self.access,
|
|
103
|
+
"params_count": len(self.params),
|
|
104
|
+
"body_statements": len(self.body),
|
|
105
|
+
"description": self.description,
|
|
106
|
+
"validate_params": self.validate_params,
|
|
107
|
+
"cache": self.cache,
|
|
108
|
+
"memoize": self.memoize,
|
|
109
|
+
"pure": self.pure,
|
|
110
|
+
"async": self.async_func,
|
|
111
|
+
"retry": self.retry,
|
|
112
|
+
"timeout": self.timeout
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if self.rest_config:
|
|
116
|
+
result["rest"] = {
|
|
117
|
+
"endpoint": self.rest_config.endpoint,
|
|
118
|
+
"method": self.rest_config.method,
|
|
119
|
+
"produces": self.rest_config.produces,
|
|
120
|
+
"consumes": self.rest_config.consumes,
|
|
121
|
+
"auth": self.rest_config.auth,
|
|
122
|
+
"roles": self.rest_config.roles,
|
|
123
|
+
"status": self.rest_config.status
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
def validate(self) -> List[str]:
|
|
129
|
+
errors = []
|
|
130
|
+
|
|
131
|
+
if not self.name:
|
|
132
|
+
errors.append("Function name is required")
|
|
133
|
+
|
|
134
|
+
# Validate params
|
|
135
|
+
for param in self.params:
|
|
136
|
+
errors.extend(param.validate())
|
|
137
|
+
|
|
138
|
+
# Validate body
|
|
139
|
+
for statement in self.body:
|
|
140
|
+
errors.extend(statement.validate())
|
|
141
|
+
|
|
142
|
+
# Validate REST config if present
|
|
143
|
+
if self.rest_config:
|
|
144
|
+
if not self.rest_config.endpoint:
|
|
145
|
+
errors.append("REST endpoint is required when REST is enabled")
|
|
146
|
+
if self.rest_config.method not in ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']:
|
|
147
|
+
errors.append(f"Invalid HTTP method: {self.rest_config.method}")
|
|
148
|
+
|
|
149
|
+
return errors
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Game Engine 2D - AST nodes and parser for the qg: namespace.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .ast_nodes import (
|
|
6
|
+
SceneNode, SpriteNode, PhysicsNode, ColliderNode, AnimationNode,
|
|
7
|
+
OnCollisionNode, CameraNode, InputNode, SoundNode, ParticleNode, TimerNode,
|
|
8
|
+
SpawnNode, HudNode, TweenNode, TilemapNode, TilemapLayerNode,
|
|
9
|
+
BehaviorNode, UseNode, PrefabNode, InstanceNode, GroupNode,
|
|
10
|
+
StateMachineNode, StateNode, TransitionNode,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
'SceneNode', 'SpriteNode', 'PhysicsNode', 'ColliderNode', 'AnimationNode',
|
|
15
|
+
'OnCollisionNode', 'CameraNode', 'InputNode', 'SoundNode', 'ParticleNode', 'TimerNode',
|
|
16
|
+
'SpawnNode', 'HudNode', 'TweenNode', 'TilemapNode', 'TilemapLayerNode',
|
|
17
|
+
'BehaviorNode', 'UseNode', 'PrefabNode', 'InstanceNode', 'GroupNode',
|
|
18
|
+
'StateMachineNode', 'StateNode', 'TransitionNode',
|
|
19
|
+
]
|