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,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Testing Engine - Python Code Templates
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- TEST_TEMPLATE: Base template for generated pytest files
|
|
6
|
+
- Reuses PyBuilder from terminal_templates
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from quantum.runtime.terminal_templates import PyBuilder, py_string, py_id
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ==========================================================================
|
|
13
|
+
# Test file template
|
|
14
|
+
# ==========================================================================
|
|
15
|
+
|
|
16
|
+
TEST_TEMPLATE = '''"""
|
|
17
|
+
{title} - Generated by Quantum Testing Engine
|
|
18
|
+
Run: pytest {filename} -v
|
|
19
|
+
Requires: pip install pytest playwright pytest-playwright
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import pytest
|
|
23
|
+
import json
|
|
24
|
+
import time
|
|
25
|
+
from unittest.mock import MagicMock, patch
|
|
26
|
+
{extra_imports}
|
|
27
|
+
|
|
28
|
+
{test_code}
|
|
29
|
+
'''
|
|
30
|
+
|
|
31
|
+
BROWSER_IMPORTS = """import re
|
|
32
|
+
from playwright.sync_api import Page, expect, BrowserContext
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
ASYNC_BROWSER_IMPORTS = """import asyncio
|
|
36
|
+
from playwright.async_api import async_playwright, Page, expect, BrowserContext
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# ==========================================================================
|
|
41
|
+
# Helper code snippets embedded in generated tests
|
|
42
|
+
# ==========================================================================
|
|
43
|
+
|
|
44
|
+
FIXTURE_HELPER = '''
|
|
45
|
+
@pytest.fixture
|
|
46
|
+
def {name}({params}):
|
|
47
|
+
"""{docstring}"""
|
|
48
|
+
{body}
|
|
49
|
+
'''
|
|
50
|
+
|
|
51
|
+
CONFTEST_TEMPLATE = '''"""
|
|
52
|
+
conftest.py - Generated by Quantum Testing Engine
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
import pytest
|
|
56
|
+
from playwright.sync_api import sync_playwright
|
|
57
|
+
|
|
58
|
+
{fixtures}
|
|
59
|
+
'''
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def sanitize_test_name(name: str) -> str:
|
|
63
|
+
"""Convert a human-readable test name to a valid Python identifier."""
|
|
64
|
+
result = name.lower()
|
|
65
|
+
result = result.replace(' ', '_').replace('-', '_').replace('.', '_')
|
|
66
|
+
result = ''.join(c for c in result if c.isalnum() or c == '_')
|
|
67
|
+
if result and result[0].isdigit():
|
|
68
|
+
result = '_' + result
|
|
69
|
+
return result
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def sanitize_class_name(name: str) -> str:
|
|
73
|
+
"""Convert a suite name to a valid Python class name."""
|
|
74
|
+
# Replace separators with spaces for splitting
|
|
75
|
+
normalized = name.replace('-', ' ').replace('_', ' ')
|
|
76
|
+
words = normalized.split()
|
|
77
|
+
# Capitalize first letter of each word, preserve rest of casing
|
|
78
|
+
result = ''.join(w[0].upper() + w[1:] if w else '' for w in words)
|
|
79
|
+
# Remove non-alphanumeric chars
|
|
80
|
+
result = ''.join(c for c in result if c.isalnum())
|
|
81
|
+
if result and result[0].isdigit():
|
|
82
|
+
result = 'Test' + result
|
|
83
|
+
if not result.startswith('Test'):
|
|
84
|
+
result = 'Test' + result
|
|
85
|
+
return result
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UI Engine - Builder/Orchestrator
|
|
3
|
+
|
|
4
|
+
Orchestrates the compilation pipeline:
|
|
5
|
+
ApplicationNode (type="ui") -> extract UI nodes -> Adapter -> output file
|
|
6
|
+
|
|
7
|
+
Supports multiple targets:
|
|
8
|
+
- html: HTML/CSS standalone page
|
|
9
|
+
- textual: Python Textual TUI application
|
|
10
|
+
- desktop: Python pywebview desktop application (with JS bridge)
|
|
11
|
+
- mobile / react-native: React Native mobile application
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
builder = UIBuilder()
|
|
15
|
+
code = builder.build(app_node, target='html')
|
|
16
|
+
builder.build_to_file(app_node, target='textual', output_path='app.py')
|
|
17
|
+
builder.build_to_file(app_node, target='mobile', output_path='App.js')
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Optional, Dict, Any, List
|
|
22
|
+
|
|
23
|
+
from quantum.core.ast_nodes import ApplicationNode
|
|
24
|
+
from quantum.core.features.state_management.src.ast_node import SetNode
|
|
25
|
+
from quantum.core.features.functions.src.ast_node import FunctionNode
|
|
26
|
+
from quantum.core.features.ui_engine.src.ast_nodes import UIWindowNode
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class UIBuildError(Exception):
|
|
30
|
+
"""Error during UI app build."""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class UIBuilder:
|
|
35
|
+
"""Builds multi-target UI output from a Quantum UI ApplicationNode."""
|
|
36
|
+
|
|
37
|
+
def build(self, app: ApplicationNode, target: str = 'html') -> str:
|
|
38
|
+
"""Build output string from an ApplicationNode with type='ui'.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
app: ApplicationNode with ui_windows and ui_children populated.
|
|
42
|
+
target: 'html', 'textual', or 'desktop'.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Generated source code string.
|
|
46
|
+
"""
|
|
47
|
+
windows = getattr(app, 'ui_windows', [])
|
|
48
|
+
ui_children = getattr(app, 'ui_children', [])
|
|
49
|
+
title = app.app_id or 'Quantum UI'
|
|
50
|
+
|
|
51
|
+
if not windows and not ui_children:
|
|
52
|
+
raise UIBuildError("No UI elements found in application")
|
|
53
|
+
|
|
54
|
+
# Get theme from application
|
|
55
|
+
theme = getattr(app, 'ui_theme', None)
|
|
56
|
+
|
|
57
|
+
if target == 'html':
|
|
58
|
+
from quantum.runtime.ui_html_adapter import UIHtmlAdapter
|
|
59
|
+
adapter = UIHtmlAdapter()
|
|
60
|
+
return adapter.generate(windows, ui_children, title, theme=theme)
|
|
61
|
+
elif target == 'textual':
|
|
62
|
+
from quantum.runtime.ui_textual_adapter import UITextualAdapter
|
|
63
|
+
adapter = UITextualAdapter()
|
|
64
|
+
return adapter.generate(windows, ui_children, title)
|
|
65
|
+
elif target == 'desktop':
|
|
66
|
+
from quantum.runtime.ui_desktop_adapter import UIDesktopAdapter
|
|
67
|
+
adapter = UIDesktopAdapter()
|
|
68
|
+
|
|
69
|
+
# Extract functions and state for desktop bridge
|
|
70
|
+
functions = self._extract_functions(app)
|
|
71
|
+
state_vars = self._extract_state(app)
|
|
72
|
+
|
|
73
|
+
return adapter.generate(
|
|
74
|
+
windows, ui_children, title,
|
|
75
|
+
functions=functions,
|
|
76
|
+
state_vars=state_vars
|
|
77
|
+
)
|
|
78
|
+
elif target in ('mobile', 'react-native'):
|
|
79
|
+
from quantum.runtime.ui_mobile_adapter import UIReactNativeAdapter
|
|
80
|
+
adapter = UIReactNativeAdapter()
|
|
81
|
+
|
|
82
|
+
# Extract functions and state for React Native hooks
|
|
83
|
+
functions = self._extract_functions(app)
|
|
84
|
+
state_vars = self._extract_state(app)
|
|
85
|
+
|
|
86
|
+
return adapter.generate(
|
|
87
|
+
windows, ui_children, title,
|
|
88
|
+
functions=functions,
|
|
89
|
+
state_vars=state_vars
|
|
90
|
+
)
|
|
91
|
+
else:
|
|
92
|
+
raise UIBuildError(f"Unknown target: {target}. Must be html, textual, desktop, or mobile")
|
|
93
|
+
|
|
94
|
+
def build_to_file(self, app: ApplicationNode, target: str = 'html',
|
|
95
|
+
output_path: Optional[str] = None) -> str:
|
|
96
|
+
"""Build and write output file. Returns the output file path."""
|
|
97
|
+
code = self.build(app, target)
|
|
98
|
+
|
|
99
|
+
if output_path is None:
|
|
100
|
+
if target == 'html':
|
|
101
|
+
ext = '.html'
|
|
102
|
+
elif target in ('mobile', 'react-native'):
|
|
103
|
+
ext = '.js'
|
|
104
|
+
else:
|
|
105
|
+
ext = '.py'
|
|
106
|
+
output_path = f"{app.app_id}{ext}"
|
|
107
|
+
|
|
108
|
+
path = Path(output_path)
|
|
109
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
110
|
+
path.write_text(code, encoding='utf-8')
|
|
111
|
+
|
|
112
|
+
return str(path.resolve())
|
|
113
|
+
|
|
114
|
+
def _extract_functions(self, app: ApplicationNode) -> Dict[str, FunctionNode]:
|
|
115
|
+
"""Extract q:function nodes from application.
|
|
116
|
+
|
|
117
|
+
Only extracts UI functions (those without REST endpoints),
|
|
118
|
+
as REST functions are for server-side use.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
app: ApplicationNode to extract functions from.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Dict mapping function name to FunctionNode.
|
|
125
|
+
"""
|
|
126
|
+
functions = {}
|
|
127
|
+
|
|
128
|
+
# Check components for functions
|
|
129
|
+
for component in getattr(app, 'components', []):
|
|
130
|
+
for func in getattr(component, 'functions', []):
|
|
131
|
+
# Only include UI functions (not REST endpoints)
|
|
132
|
+
if not func.is_rest_enabled():
|
|
133
|
+
functions[func.name] = func
|
|
134
|
+
|
|
135
|
+
# Check for functions directly on app (if any)
|
|
136
|
+
for func in getattr(app, 'functions', []):
|
|
137
|
+
if not func.is_rest_enabled():
|
|
138
|
+
functions[func.name] = func
|
|
139
|
+
|
|
140
|
+
# Check ui_children for functions (when parsed directly into app)
|
|
141
|
+
for child in getattr(app, 'ui_children', []):
|
|
142
|
+
if isinstance(child, FunctionNode) and not child.is_rest_enabled():
|
|
143
|
+
functions[child.name] = child
|
|
144
|
+
|
|
145
|
+
# Check ui_windows children for functions
|
|
146
|
+
for window in getattr(app, 'ui_windows', []):
|
|
147
|
+
for child in getattr(window, 'children', []):
|
|
148
|
+
if isinstance(child, FunctionNode) and not child.is_rest_enabled():
|
|
149
|
+
functions[child.name] = child
|
|
150
|
+
|
|
151
|
+
return functions
|
|
152
|
+
|
|
153
|
+
def _extract_state(self, app: ApplicationNode) -> Dict[str, Any]:
|
|
154
|
+
"""Extract q:set nodes from application level.
|
|
155
|
+
|
|
156
|
+
Extracts initial state variables defined at the application or
|
|
157
|
+
component level for state initialization.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
app: ApplicationNode to extract state from.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Dict mapping variable name to initial value.
|
|
164
|
+
"""
|
|
165
|
+
state = {}
|
|
166
|
+
|
|
167
|
+
# Check ui_children for SetNode (top-level state declarations)
|
|
168
|
+
for child in getattr(app, 'ui_children', []):
|
|
169
|
+
if isinstance(child, SetNode):
|
|
170
|
+
# Use default if value is not set
|
|
171
|
+
value = child.value if child.value is not None else child.default
|
|
172
|
+
state[child.name] = value
|
|
173
|
+
|
|
174
|
+
# Check ui_windows children for SetNode
|
|
175
|
+
for window in getattr(app, 'ui_windows', []):
|
|
176
|
+
for child in getattr(window, 'children', []):
|
|
177
|
+
if isinstance(child, SetNode):
|
|
178
|
+
value = child.value if child.value is not None else child.default
|
|
179
|
+
state[child.name] = value
|
|
180
|
+
|
|
181
|
+
# Check components for statements that are SetNode
|
|
182
|
+
for component in getattr(app, 'components', []):
|
|
183
|
+
for stmt in getattr(component, 'statements', []):
|
|
184
|
+
if isinstance(stmt, SetNode):
|
|
185
|
+
value = stmt.value if stmt.value is not None else stmt.default
|
|
186
|
+
state[stmt.name] = value
|
|
187
|
+
|
|
188
|
+
return state
|