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,291 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data Import Feature - AST Nodes
|
|
3
|
+
Defines DataNode and related nodes for q:data
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import List, Dict, Any, Optional
|
|
7
|
+
from quantum.core.ast_nodes import QuantumNode
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DataNode(QuantumNode):
|
|
11
|
+
"""Represents a <q:data> - Data import and transformation component"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, name: str, source: str, data_type: str):
|
|
14
|
+
self.name = name # Variable name for result
|
|
15
|
+
self.source = source # File path, URL, or variable reference
|
|
16
|
+
self.data_type = data_type # csv, json, xml, transform
|
|
17
|
+
|
|
18
|
+
# Caching
|
|
19
|
+
self.cache = True # Cache by default
|
|
20
|
+
self.ttl = None # Cache TTL in seconds
|
|
21
|
+
|
|
22
|
+
# CSV-specific attributes
|
|
23
|
+
self.delimiter = ","
|
|
24
|
+
self.quote = '"'
|
|
25
|
+
self.header = True # First row contains headers
|
|
26
|
+
self.encoding = "utf-8"
|
|
27
|
+
self.skip_rows = 0
|
|
28
|
+
|
|
29
|
+
# XML-specific attributes
|
|
30
|
+
self.xpath = None # XPath expression to select nodes
|
|
31
|
+
self.namespace = None # XML namespace URI
|
|
32
|
+
|
|
33
|
+
# Child elements
|
|
34
|
+
self.columns: List['ColumnNode'] = [] # For CSV
|
|
35
|
+
self.fields: List['FieldNode'] = [] # For XML
|
|
36
|
+
self.transforms: List['TransformNode'] = [] # For transformations
|
|
37
|
+
self.headers: List['HeaderNode'] = [] # For HTTP headers (URL sources)
|
|
38
|
+
|
|
39
|
+
# Result metadata
|
|
40
|
+
self.result = None # Variable name for metadata
|
|
41
|
+
|
|
42
|
+
def add_column(self, column: 'ColumnNode'):
|
|
43
|
+
"""Add CSV column definition"""
|
|
44
|
+
self.columns.append(column)
|
|
45
|
+
|
|
46
|
+
def add_field(self, field: 'FieldNode'):
|
|
47
|
+
"""Add XML field mapping"""
|
|
48
|
+
self.fields.append(field)
|
|
49
|
+
|
|
50
|
+
def add_transform(self, transform: 'TransformNode'):
|
|
51
|
+
"""Add transformation operation"""
|
|
52
|
+
self.transforms.append(transform)
|
|
53
|
+
|
|
54
|
+
def add_header(self, header: 'HeaderNode'):
|
|
55
|
+
"""Add HTTP header"""
|
|
56
|
+
self.headers.append(header)
|
|
57
|
+
|
|
58
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
59
|
+
return {
|
|
60
|
+
"type": "data",
|
|
61
|
+
"name": self.name,
|
|
62
|
+
"source": self.source,
|
|
63
|
+
"data_type": self.data_type,
|
|
64
|
+
"cache": self.cache,
|
|
65
|
+
"ttl": self.ttl,
|
|
66
|
+
"columns": [c.to_dict() for c in self.columns],
|
|
67
|
+
"fields": [f.to_dict() for f in self.fields],
|
|
68
|
+
"transforms": [t.to_dict() for t in self.transforms],
|
|
69
|
+
"headers": [h.to_dict() for h in self.headers]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def validate(self) -> List[str]:
|
|
73
|
+
errors = []
|
|
74
|
+
if not self.name:
|
|
75
|
+
errors.append("Data name is required")
|
|
76
|
+
if not self.source:
|
|
77
|
+
errors.append("Data source is required")
|
|
78
|
+
if self.data_type not in ['csv', 'json', 'xml', 'transform']:
|
|
79
|
+
errors.append(f"Invalid data type: {self.data_type}. Must be csv, json, xml, or transform")
|
|
80
|
+
|
|
81
|
+
# Validate child elements
|
|
82
|
+
for column in self.columns:
|
|
83
|
+
errors.extend(column.validate())
|
|
84
|
+
for field in self.fields:
|
|
85
|
+
errors.extend(field.validate())
|
|
86
|
+
for transform in self.transforms:
|
|
87
|
+
errors.extend(transform.validate())
|
|
88
|
+
for header in self.headers:
|
|
89
|
+
errors.extend(header.validate())
|
|
90
|
+
|
|
91
|
+
return errors
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ColumnNode(QuantumNode):
|
|
95
|
+
"""Represents a <q:column> - CSV column definition"""
|
|
96
|
+
|
|
97
|
+
def __init__(self, name: str, col_type: str = "string"):
|
|
98
|
+
self.name = name
|
|
99
|
+
self.col_type = col_type # string, integer, decimal, boolean, date, datetime
|
|
100
|
+
|
|
101
|
+
# Validation (same as QuantumParam)
|
|
102
|
+
self.required = False
|
|
103
|
+
self.default = None
|
|
104
|
+
self.validate_rule = None
|
|
105
|
+
self.pattern = None
|
|
106
|
+
self.min = None
|
|
107
|
+
self.max = None
|
|
108
|
+
self.minlength = None
|
|
109
|
+
self.maxlength = None
|
|
110
|
+
self.range = None
|
|
111
|
+
self.enum = None
|
|
112
|
+
|
|
113
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
114
|
+
return {
|
|
115
|
+
"type": "column",
|
|
116
|
+
"name": self.name,
|
|
117
|
+
"col_type": self.col_type,
|
|
118
|
+
"required": self.required,
|
|
119
|
+
"default": self.default
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
def validate(self) -> List[str]:
|
|
123
|
+
errors = []
|
|
124
|
+
if not self.name:
|
|
125
|
+
errors.append("Column name is required")
|
|
126
|
+
valid_types = ['string', 'integer', 'decimal', 'boolean', 'date', 'datetime', 'json', 'array']
|
|
127
|
+
if self.col_type not in valid_types:
|
|
128
|
+
errors.append(f"Invalid column type: {self.col_type}. Must be one of {valid_types}")
|
|
129
|
+
return errors
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class FieldNode(QuantumNode):
|
|
133
|
+
"""Represents a <q:field> - XML field mapping"""
|
|
134
|
+
|
|
135
|
+
def __init__(self, name: str, xpath: str, field_type: str = "string"):
|
|
136
|
+
self.name = name
|
|
137
|
+
self.xpath = xpath # XPath expression to extract value
|
|
138
|
+
self.field_type = field_type # string, integer, decimal, boolean, date, datetime
|
|
139
|
+
|
|
140
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
141
|
+
return {
|
|
142
|
+
"type": "field",
|
|
143
|
+
"name": self.name,
|
|
144
|
+
"xpath": self.xpath,
|
|
145
|
+
"field_type": self.field_type
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
def validate(self) -> List[str]:
|
|
149
|
+
errors = []
|
|
150
|
+
if not self.name:
|
|
151
|
+
errors.append("Field name is required")
|
|
152
|
+
if not self.xpath:
|
|
153
|
+
errors.append("Field xpath is required")
|
|
154
|
+
valid_types = ['string', 'integer', 'decimal', 'boolean', 'date', 'datetime', 'json', 'array']
|
|
155
|
+
if self.field_type not in valid_types:
|
|
156
|
+
errors.append(f"Invalid field type: {self.field_type}. Must be one of {valid_types}")
|
|
157
|
+
return errors
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class TransformNode(QuantumNode):
|
|
161
|
+
"""Represents a <q:transform> - Container for transformation operations"""
|
|
162
|
+
|
|
163
|
+
def __init__(self):
|
|
164
|
+
self.operations: List[QuantumNode] = [] # Filter, Sort, Limit, Compute, etc.
|
|
165
|
+
|
|
166
|
+
def add_operation(self, operation: QuantumNode):
|
|
167
|
+
"""Add transformation operation"""
|
|
168
|
+
self.operations.append(operation)
|
|
169
|
+
|
|
170
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
171
|
+
return {
|
|
172
|
+
"type": "transform",
|
|
173
|
+
"operations": [op.to_dict() for op in self.operations]
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
def validate(self) -> List[str]:
|
|
177
|
+
errors = []
|
|
178
|
+
for operation in self.operations:
|
|
179
|
+
errors.extend(operation.validate())
|
|
180
|
+
return errors
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class FilterNode(QuantumNode):
|
|
184
|
+
"""Represents a <q:filter> - Filter operation"""
|
|
185
|
+
|
|
186
|
+
def __init__(self, condition: str):
|
|
187
|
+
self.condition = condition # Filter expression
|
|
188
|
+
|
|
189
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
190
|
+
return {
|
|
191
|
+
"type": "filter",
|
|
192
|
+
"condition": self.condition
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
def validate(self) -> List[str]:
|
|
196
|
+
errors = []
|
|
197
|
+
if not self.condition:
|
|
198
|
+
errors.append("Filter condition is required")
|
|
199
|
+
return errors
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class SortNode(QuantumNode):
|
|
203
|
+
"""Represents a <q:sort> - Sort operation"""
|
|
204
|
+
|
|
205
|
+
def __init__(self, by: str, order: str = "asc"):
|
|
206
|
+
self.by = by # Field name to sort by
|
|
207
|
+
self.order = order # asc or desc
|
|
208
|
+
|
|
209
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
210
|
+
return {
|
|
211
|
+
"type": "sort",
|
|
212
|
+
"by": self.by,
|
|
213
|
+
"order": self.order
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
def validate(self) -> List[str]:
|
|
217
|
+
errors = []
|
|
218
|
+
if not self.by:
|
|
219
|
+
errors.append("Sort 'by' field is required")
|
|
220
|
+
if self.order not in ['asc', 'desc']:
|
|
221
|
+
errors.append(f"Invalid sort order: {self.order}. Must be 'asc' or 'desc'")
|
|
222
|
+
return errors
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class LimitNode(QuantumNode):
|
|
226
|
+
"""Represents a <q:limit> - Limit operation"""
|
|
227
|
+
|
|
228
|
+
def __init__(self, value: int):
|
|
229
|
+
self.value = value # Maximum number of records
|
|
230
|
+
|
|
231
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
232
|
+
return {
|
|
233
|
+
"type": "limit",
|
|
234
|
+
"value": self.value
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
def validate(self) -> List[str]:
|
|
238
|
+
errors = []
|
|
239
|
+
if self.value is None:
|
|
240
|
+
errors.append("Limit value is required")
|
|
241
|
+
if isinstance(self.value, int) and self.value < 0:
|
|
242
|
+
errors.append("Limit value must be >= 0")
|
|
243
|
+
return errors
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class ComputeNode(QuantumNode):
|
|
247
|
+
"""Represents a <q:compute> - Compute derived field"""
|
|
248
|
+
|
|
249
|
+
def __init__(self, field: str, expression: str, comp_type: str = "string"):
|
|
250
|
+
self.field = field # New field name
|
|
251
|
+
self.expression = expression # Expression to compute value
|
|
252
|
+
self.comp_type = comp_type # Result type
|
|
253
|
+
|
|
254
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
255
|
+
return {
|
|
256
|
+
"type": "compute",
|
|
257
|
+
"field": self.field,
|
|
258
|
+
"expression": self.expression,
|
|
259
|
+
"comp_type": self.comp_type
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
def validate(self) -> List[str]:
|
|
263
|
+
errors = []
|
|
264
|
+
if not self.field:
|
|
265
|
+
errors.append("Compute field name is required")
|
|
266
|
+
if not self.expression:
|
|
267
|
+
errors.append("Compute expression is required")
|
|
268
|
+
return errors
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class HeaderNode(QuantumNode):
|
|
272
|
+
"""Represents a <q:header> - HTTP header for URL sources"""
|
|
273
|
+
|
|
274
|
+
def __init__(self, name: str, value: str):
|
|
275
|
+
self.name = name
|
|
276
|
+
self.value = value
|
|
277
|
+
|
|
278
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
279
|
+
return {
|
|
280
|
+
"type": "header",
|
|
281
|
+
"name": self.name,
|
|
282
|
+
"value": self.value[:50] + "..." if len(str(self.value)) > 50 else self.value
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
def validate(self) -> List[str]:
|
|
286
|
+
errors = []
|
|
287
|
+
if not self.name:
|
|
288
|
+
errors.append("Header name is required")
|
|
289
|
+
if self.value is None:
|
|
290
|
+
errors.append(f"Header '{self.name}' value is required")
|
|
291
|
+
return errors
|