symbolicai 1.0.0__py3-none-any.whl → 1.1.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.
- symai/__init__.py +198 -134
- symai/backend/base.py +51 -51
- symai/backend/engines/drawing/engine_bfl.py +33 -33
- symai/backend/engines/drawing/engine_gpt_image.py +4 -10
- symai/backend/engines/embedding/engine_llama_cpp.py +50 -35
- symai/backend/engines/embedding/engine_openai.py +22 -16
- symai/backend/engines/execute/engine_python.py +16 -16
- symai/backend/engines/files/engine_io.py +51 -49
- symai/backend/engines/imagecaptioning/engine_blip2.py +27 -23
- symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +53 -46
- symai/backend/engines/index/engine_pinecone.py +116 -88
- symai/backend/engines/index/engine_qdrant.py +1011 -0
- symai/backend/engines/index/engine_vectordb.py +78 -52
- symai/backend/engines/lean/engine_lean4.py +65 -25
- symai/backend/engines/neurosymbolic/__init__.py +28 -28
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +137 -135
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +145 -152
- symai/backend/engines/neurosymbolic/engine_cerebras.py +328 -0
- symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +75 -49
- symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +199 -155
- symai/backend/engines/neurosymbolic/engine_groq.py +106 -72
- symai/backend/engines/neurosymbolic/engine_huggingface.py +100 -67
- symai/backend/engines/neurosymbolic/engine_llama_cpp.py +121 -93
- symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +213 -132
- symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +180 -137
- symai/backend/engines/ocr/engine_apilayer.py +18 -20
- symai/backend/engines/output/engine_stdout.py +9 -9
- symai/backend/engines/{webscraping → scrape}/engine_requests.py +25 -11
- symai/backend/engines/search/engine_openai.py +95 -83
- symai/backend/engines/search/engine_parallel.py +665 -0
- symai/backend/engines/search/engine_perplexity.py +40 -41
- symai/backend/engines/search/engine_serpapi.py +33 -28
- symai/backend/engines/speech_to_text/engine_local_whisper.py +37 -27
- symai/backend/engines/symbolic/engine_wolframalpha.py +14 -8
- symai/backend/engines/text_to_speech/engine_openai.py +15 -19
- symai/backend/engines/text_vision/engine_clip.py +34 -28
- symai/backend/engines/userinput/engine_console.py +3 -4
- symai/backend/mixin/anthropic.py +48 -40
- symai/backend/mixin/deepseek.py +4 -5
- symai/backend/mixin/google.py +5 -4
- symai/backend/mixin/groq.py +2 -4
- symai/backend/mixin/openai.py +132 -110
- symai/backend/settings.py +14 -14
- symai/chat.py +164 -94
- symai/collect/dynamic.py +13 -11
- symai/collect/pipeline.py +39 -31
- symai/collect/stats.py +109 -69
- symai/components.py +556 -238
- symai/constraints.py +14 -5
- symai/core.py +1495 -1210
- symai/core_ext.py +55 -50
- symai/endpoints/api.py +113 -58
- symai/extended/api_builder.py +22 -17
- symai/extended/arxiv_pdf_parser.py +13 -5
- symai/extended/bibtex_parser.py +8 -4
- symai/extended/conversation.py +88 -69
- symai/extended/document.py +40 -27
- symai/extended/file_merger.py +45 -7
- symai/extended/graph.py +38 -24
- symai/extended/html_style_template.py +17 -11
- symai/extended/interfaces/blip_2.py +1 -1
- symai/extended/interfaces/clip.py +4 -2
- symai/extended/interfaces/console.py +5 -3
- symai/extended/interfaces/dall_e.py +3 -1
- symai/extended/interfaces/file.py +2 -0
- symai/extended/interfaces/flux.py +3 -1
- symai/extended/interfaces/gpt_image.py +15 -6
- symai/extended/interfaces/input.py +2 -1
- symai/extended/interfaces/llava.py +1 -1
- symai/extended/interfaces/{naive_webscraping.py → naive_scrape.py} +3 -2
- symai/extended/interfaces/naive_vectordb.py +2 -2
- symai/extended/interfaces/ocr.py +4 -2
- symai/extended/interfaces/openai_search.py +2 -0
- symai/extended/interfaces/parallel.py +30 -0
- symai/extended/interfaces/perplexity.py +2 -0
- symai/extended/interfaces/pinecone.py +6 -4
- symai/extended/interfaces/python.py +2 -0
- symai/extended/interfaces/serpapi.py +2 -0
- symai/extended/interfaces/terminal.py +0 -1
- symai/extended/interfaces/tts.py +2 -1
- symai/extended/interfaces/whisper.py +2 -1
- symai/extended/interfaces/wolframalpha.py +1 -0
- symai/extended/metrics/__init__.py +1 -1
- symai/extended/metrics/similarity.py +5 -2
- symai/extended/os_command.py +31 -22
- symai/extended/packages/symdev.py +39 -34
- symai/extended/packages/sympkg.py +30 -27
- symai/extended/packages/symrun.py +46 -35
- symai/extended/repo_cloner.py +10 -9
- symai/extended/seo_query_optimizer.py +15 -12
- symai/extended/solver.py +104 -76
- symai/extended/summarizer.py +8 -7
- symai/extended/taypan_interpreter.py +10 -9
- symai/extended/vectordb.py +28 -15
- symai/formatter/formatter.py +39 -31
- symai/formatter/regex.py +46 -44
- symai/functional.py +184 -86
- symai/imports.py +85 -51
- symai/interfaces.py +1 -1
- symai/memory.py +33 -24
- symai/menu/screen.py +28 -19
- symai/misc/console.py +27 -27
- symai/misc/loader.py +4 -3
- symai/models/base.py +147 -76
- symai/models/errors.py +1 -1
- symai/ops/__init__.py +1 -1
- symai/ops/measures.py +17 -14
- symai/ops/primitives.py +933 -635
- symai/post_processors.py +28 -24
- symai/pre_processors.py +58 -52
- symai/processor.py +15 -9
- symai/prompts.py +714 -649
- symai/server/huggingface_server.py +115 -32
- symai/server/llama_cpp_server.py +14 -6
- symai/server/qdrant_server.py +206 -0
- symai/shell.py +98 -39
- symai/shellsv.py +307 -223
- symai/strategy.py +135 -81
- symai/symbol.py +276 -225
- symai/utils.py +62 -46
- {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/METADATA +19 -9
- symbolicai-1.1.0.dist-info/RECORD +168 -0
- symbolicai-1.0.0.dist-info/RECORD +0 -163
- {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/WHEEL +0 -0
- {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/entry_points.txt +0 -0
- {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/top_level.txt +0 -0
symai/symbol.py
CHANGED
|
@@ -3,7 +3,7 @@ import html
|
|
|
3
3
|
import json
|
|
4
4
|
from collections.abc import Callable, Iterator
|
|
5
5
|
from json import JSONEncoder
|
|
6
|
-
from typing import Any, ClassVar
|
|
6
|
+
from typing import Any, ClassVar, Generic, TypeVar
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from box import Box
|
|
@@ -11,10 +11,12 @@ from box import Box
|
|
|
11
11
|
from . import core
|
|
12
12
|
from .ops import SYMBOL_PRIMITIVES
|
|
13
13
|
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
class SymbolEncoder(JSONEncoder):
|
|
16
18
|
def default(self, o):
|
|
17
|
-
|
|
19
|
+
"""
|
|
18
20
|
Encode a Symbol instance into its dictionary representation.
|
|
19
21
|
|
|
20
22
|
Args:
|
|
@@ -22,7 +24,7 @@ class SymbolEncoder(JSONEncoder):
|
|
|
22
24
|
|
|
23
25
|
Returns:
|
|
24
26
|
dict: The dictionary representation of the Symbol instance.
|
|
25
|
-
|
|
27
|
+
"""
|
|
26
28
|
if isinstance(o, Symbol):
|
|
27
29
|
return o.__getstate__()
|
|
28
30
|
return JSONEncoder.default(self, o)
|
|
@@ -38,7 +40,7 @@ class Metadata:
|
|
|
38
40
|
return self.__dict__.keys()
|
|
39
41
|
|
|
40
42
|
def __getattr__(self, name):
|
|
41
|
-
|
|
43
|
+
"""
|
|
42
44
|
Get a metadata attribute by name.
|
|
43
45
|
|
|
44
46
|
Args:
|
|
@@ -46,30 +48,30 @@ class Metadata:
|
|
|
46
48
|
|
|
47
49
|
Returns:
|
|
48
50
|
Any: The value of the metadata attribute.
|
|
49
|
-
|
|
51
|
+
"""
|
|
50
52
|
return self.__dict__.get(name)
|
|
51
53
|
|
|
52
54
|
def __setattr__(self, name, value):
|
|
53
|
-
|
|
55
|
+
"""
|
|
54
56
|
Set a metadata attribute by name.
|
|
55
57
|
|
|
56
58
|
Args:
|
|
57
59
|
name (str): The name of the metadata attribute to set.
|
|
58
60
|
value (Any): The value of the metadata attribute.
|
|
59
|
-
|
|
61
|
+
"""
|
|
60
62
|
self.__dict__[name] = value
|
|
61
63
|
|
|
62
64
|
def __delattr__(self, name):
|
|
63
|
-
|
|
65
|
+
"""
|
|
64
66
|
Delete a metadata attribute by name.
|
|
65
67
|
|
|
66
68
|
Args:
|
|
67
69
|
name (str): The name of the metadata attribute to delete.
|
|
68
|
-
|
|
70
|
+
"""
|
|
69
71
|
del self.__dict__[name]
|
|
70
72
|
|
|
71
73
|
def __getitem__(self, name):
|
|
72
|
-
|
|
74
|
+
"""
|
|
73
75
|
Get a metadata attribute by name.
|
|
74
76
|
|
|
75
77
|
Args:
|
|
@@ -77,75 +79,82 @@ class Metadata:
|
|
|
77
79
|
|
|
78
80
|
Returns:
|
|
79
81
|
Any: The value of the metadata attribute.
|
|
80
|
-
|
|
82
|
+
"""
|
|
81
83
|
return self.__getattr__(name)
|
|
82
84
|
|
|
83
85
|
def __setitem__(self, name, value):
|
|
84
|
-
|
|
86
|
+
"""
|
|
85
87
|
Set a metadata attribute by name.
|
|
86
88
|
|
|
87
89
|
Args:
|
|
88
90
|
name (str): The name of the metadata attribute to set.
|
|
89
91
|
value (Any): The value of the metadata attribute.
|
|
90
|
-
|
|
92
|
+
"""
|
|
91
93
|
self.__setattr__(name, value)
|
|
92
94
|
|
|
93
95
|
def __delitem__(self, name):
|
|
94
|
-
|
|
96
|
+
"""
|
|
95
97
|
Delete a metadata attribute by name.
|
|
96
98
|
|
|
97
99
|
Args:
|
|
98
100
|
name (str): The name of the metadata attribute to delete.
|
|
99
|
-
|
|
101
|
+
"""
|
|
100
102
|
self.__delattr__(name)
|
|
101
103
|
|
|
102
104
|
def __str__(self) -> str:
|
|
103
|
-
|
|
105
|
+
"""
|
|
104
106
|
Get the string representation of the Symbol's value.
|
|
105
107
|
|
|
106
108
|
Returns:
|
|
107
109
|
str: The string representation of the Symbol's value.
|
|
108
|
-
|
|
109
|
-
_val =
|
|
110
|
+
"""
|
|
111
|
+
_val = ""
|
|
110
112
|
if self.value is not None:
|
|
111
113
|
_val += str(self.value)
|
|
112
|
-
return
|
|
114
|
+
return (
|
|
115
|
+
_val
|
|
116
|
+
+ f"Properties({ {k: str(v) for k, v in self.__dict__.items() if not k.startswith('_')}!s})"
|
|
117
|
+
)
|
|
113
118
|
|
|
114
119
|
def __repr__(self) -> str:
|
|
115
|
-
|
|
120
|
+
"""
|
|
116
121
|
Get the representation of the Symbol object as a string.
|
|
117
122
|
|
|
118
123
|
Returns:
|
|
119
124
|
str: The representation of the Symbol object.
|
|
120
|
-
|
|
125
|
+
"""
|
|
121
126
|
# class with full path
|
|
122
|
-
class_ = self.__class__.__module__ +
|
|
123
|
-
hex_
|
|
124
|
-
from_symbol =
|
|
125
|
-
|
|
127
|
+
class_ = self.__class__.__module__ + "." + self.__class__.__name__
|
|
128
|
+
hex_ = hex(id(self))
|
|
129
|
+
from_symbol = (
|
|
130
|
+
f" from {self.symbol_type.__module__}.{self.symbol_type.__name__}"
|
|
131
|
+
if self.symbol_type
|
|
132
|
+
else ""
|
|
133
|
+
)
|
|
134
|
+
return f"<class {class_} at {hex_}{from_symbol}>"
|
|
126
135
|
|
|
127
136
|
|
|
128
137
|
class Linker(Metadata):
|
|
129
138
|
def keys(self) -> list[str]:
|
|
130
|
-
|
|
139
|
+
"""
|
|
131
140
|
Get all keys of the linker.
|
|
132
141
|
|
|
133
142
|
Returns:
|
|
134
143
|
List[str]: All keys of the linker.
|
|
135
|
-
|
|
144
|
+
"""
|
|
136
145
|
return list(self.results.keys())
|
|
137
146
|
|
|
138
147
|
def values(self) -> list[Any]:
|
|
139
|
-
|
|
148
|
+
"""
|
|
140
149
|
Get all values of the linker.
|
|
141
150
|
|
|
142
151
|
Returns:
|
|
143
152
|
List[Any]: All values of the linker.
|
|
144
|
-
|
|
153
|
+
"""
|
|
145
154
|
return list(self.results.values())
|
|
146
155
|
|
|
147
156
|
def find(self, name: str, single: bool = True, strict: bool = False) -> Any:
|
|
148
|
-
|
|
157
|
+
"""
|
|
149
158
|
Find a result in the linker.
|
|
150
159
|
|
|
151
160
|
Args:
|
|
@@ -155,9 +164,10 @@ class Linker(Metadata):
|
|
|
155
164
|
|
|
156
165
|
Returns:
|
|
157
166
|
Any: The result.
|
|
158
|
-
|
|
167
|
+
"""
|
|
159
168
|
# search all results and return the first one that matches the name
|
|
160
169
|
res = []
|
|
170
|
+
|
|
161
171
|
def match_(key, search_name):
|
|
162
172
|
if strict:
|
|
163
173
|
return str(search_name) == str(key)
|
|
@@ -167,7 +177,7 @@ class Linker(Metadata):
|
|
|
167
177
|
if match_(k, name):
|
|
168
178
|
res.append(self.results[k])
|
|
169
179
|
if single:
|
|
170
|
-
assert len(res) == 1, f
|
|
180
|
+
assert len(res) == 1, f"Found {len(res)} results for name {name}. Expected 1."
|
|
171
181
|
if len(res) == 0:
|
|
172
182
|
return None
|
|
173
183
|
if len(res) == 1:
|
|
@@ -178,13 +188,16 @@ class Linker(Metadata):
|
|
|
178
188
|
class PropertyReservedError(AttributeError):
|
|
179
189
|
def __init__(self, property_name):
|
|
180
190
|
self.property_name = property_name
|
|
181
|
-
super().__init__(
|
|
191
|
+
super().__init__(
|
|
192
|
+
f"Cannot set reserved property '{property_name}'. This property is defined in the 'Symbol' base class and cannot be assigned."
|
|
193
|
+
)
|
|
182
194
|
|
|
183
195
|
|
|
184
196
|
class SymbolMeta(type):
|
|
185
197
|
"""
|
|
186
198
|
Metaclass to unify metaclasses of mixed-in primitives.
|
|
187
199
|
"""
|
|
200
|
+
|
|
188
201
|
def __call__(cls, *args, **kwargs):
|
|
189
202
|
obj = type.__call__(cls, *args, **kwargs)
|
|
190
203
|
obj.__post_init__(*args, **kwargs)
|
|
@@ -202,24 +215,40 @@ class SymbolMeta(type):
|
|
|
202
215
|
# create a new cls type that inherits from Symbol and the mixin primitive types
|
|
203
216
|
cls = type.__new__(mcls, name, bases, attrs)
|
|
204
217
|
# inherit the base class module for dynamic type creation
|
|
205
|
-
if
|
|
206
|
-
cls.__module__ = attrs[
|
|
218
|
+
if "__module__" in attrs:
|
|
219
|
+
cls.__module__ = attrs["__module__"]
|
|
207
220
|
elif len(bases) > 0:
|
|
208
221
|
cls.__module__ = bases[0].__module__
|
|
209
222
|
return cls
|
|
210
223
|
|
|
211
224
|
|
|
212
|
-
class Symbol(metaclass=SymbolMeta):
|
|
225
|
+
class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
213
226
|
_mixin: ClassVar[bool] = True
|
|
214
227
|
_primitives: ClassVar[dict[str, type]] = SYMBOL_PRIMITIVES
|
|
215
228
|
_metadata: ClassVar[Metadata] = Metadata()
|
|
216
229
|
_metadata_primitives: ClassVar[dict[str, Callable]] = {}
|
|
217
230
|
_metadata._primitives = _metadata_primitives
|
|
218
231
|
_dynamic_context: ClassVar[dict[str, list[str]]] = {}
|
|
219
|
-
_RESERVED_PROPERTIES: ClassVar[set[str]] = {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
232
|
+
_RESERVED_PROPERTIES: ClassVar[set[str]] = {
|
|
233
|
+
"graph",
|
|
234
|
+
"linker",
|
|
235
|
+
"parent",
|
|
236
|
+
"children",
|
|
237
|
+
"metadata",
|
|
238
|
+
"value",
|
|
239
|
+
"root",
|
|
240
|
+
"nodes",
|
|
241
|
+
"edges",
|
|
242
|
+
"global_context",
|
|
243
|
+
"static_context",
|
|
244
|
+
"dynamic_context",
|
|
245
|
+
"shape",
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
def __init__(
|
|
249
|
+
self, *value, static_context: str | None = "", dynamic_context: str | None = None, **kwargs
|
|
250
|
+
) -> None:
|
|
251
|
+
"""
|
|
223
252
|
Initialize a Symbol instance with a specified value. Unwraps nested symbols.
|
|
224
253
|
|
|
225
254
|
Args:
|
|
@@ -229,37 +258,35 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
229
258
|
Attributes:
|
|
230
259
|
value (Any): The value of the symbol.
|
|
231
260
|
metadata (Optional[Dict[str, Any]]): The metadata associated with the symbol.
|
|
232
|
-
|
|
261
|
+
"""
|
|
233
262
|
super().__init__()
|
|
234
|
-
self._value
|
|
263
|
+
self._value = None
|
|
235
264
|
# store kwargs for new symbol instance type passing
|
|
236
|
-
self._kwargs
|
|
237
|
-
|
|
238
|
-
**kwargs
|
|
239
|
-
}
|
|
240
|
-
self._metadata = Metadata() # use global metadata by default
|
|
265
|
+
self._kwargs = {"static_context": static_context, **kwargs}
|
|
266
|
+
self._metadata = Metadata() # use global metadata by default
|
|
241
267
|
self._metadata.symbol_type = type(self)
|
|
242
|
-
self._parent
|
|
243
|
-
self._children
|
|
244
|
-
self._static_context
|
|
268
|
+
self._parent = None
|
|
269
|
+
self._children = []
|
|
270
|
+
self._static_context = static_context
|
|
245
271
|
self._dynamic_context = dynamic_context or Symbol._dynamic_context
|
|
246
272
|
# if value is a single value, unwrap it
|
|
247
|
-
_value
|
|
248
|
-
self._value
|
|
273
|
+
_value = self._unwrap_symbols_args(*value)
|
|
274
|
+
self._value = _value
|
|
249
275
|
# construct dependency graph for symbol
|
|
250
276
|
self._construct_dependency_graph(*value)
|
|
251
277
|
|
|
252
|
-
def __post_init__(self, *args, **kwargs):
|
|
253
|
-
|
|
278
|
+
def __post_init__(self, *args, **kwargs): # this is called at the end of __init__
|
|
279
|
+
"""
|
|
254
280
|
Post-initialization method that is called at the end of the __init__ method.
|
|
255
|
-
|
|
281
|
+
"""
|
|
282
|
+
|
|
256
283
|
def _func(k, v):
|
|
257
284
|
# check if property is of type Symbol and not private and a class variable (not a function)
|
|
258
|
-
if isinstance(v, Symbol) and not k.startswith(
|
|
285
|
+
if isinstance(v, Symbol) and not k.startswith("_") and v is not self:
|
|
259
286
|
v._parent = self
|
|
260
287
|
self._children.append(v)
|
|
261
288
|
# else if iterable, check if it contains symbols
|
|
262
|
-
elif isinstance(v, (list, tuple)) and not k.startswith(
|
|
289
|
+
elif isinstance(v, (list, tuple)) and not k.startswith("_"):
|
|
263
290
|
for i in v:
|
|
264
291
|
_func(k, i)
|
|
265
292
|
|
|
@@ -273,7 +300,10 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
273
300
|
if len(args) == 1:
|
|
274
301
|
return self._unwrap_single_symbol_arg(args[0], nested=nested)
|
|
275
302
|
if len(args) > 1:
|
|
276
|
-
return [
|
|
303
|
+
return [
|
|
304
|
+
self._unwrap_symbols_args(a, nested=True) if isinstance(a, Symbol) else a
|
|
305
|
+
for a in args
|
|
306
|
+
]
|
|
277
307
|
return None
|
|
278
308
|
|
|
279
309
|
def _unwrap_single_symbol_arg(self, value: Any, *, nested: bool) -> Any:
|
|
@@ -281,9 +311,9 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
281
311
|
return value
|
|
282
312
|
if isinstance(value, Symbol):
|
|
283
313
|
if not nested:
|
|
284
|
-
self._metadata
|
|
314
|
+
self._metadata = value.metadata
|
|
285
315
|
self._static_context = value.static_context
|
|
286
|
-
self._kwargs
|
|
316
|
+
self._kwargs = value._kwargs
|
|
287
317
|
return value.value
|
|
288
318
|
if isinstance(value, list):
|
|
289
319
|
return [self._unwrap_symbols_args(v, nested=True) for v in value]
|
|
@@ -299,12 +329,12 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
299
329
|
return value
|
|
300
330
|
|
|
301
331
|
def _construct_dependency_graph(self, *value):
|
|
302
|
-
|
|
332
|
+
"""
|
|
303
333
|
Construct a dependency graph for the symbol.
|
|
304
334
|
|
|
305
335
|
Args:
|
|
306
336
|
value (Any): The value of the symbol.
|
|
307
|
-
|
|
337
|
+
"""
|
|
308
338
|
# for each value
|
|
309
339
|
for v in value:
|
|
310
340
|
if isinstance(v, Symbol) and v is not self:
|
|
@@ -313,13 +343,16 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
313
343
|
# add new instance to children of previous instance
|
|
314
344
|
self._children.append(v)
|
|
315
345
|
|
|
316
|
-
def __new__(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
346
|
+
def __new__(
|
|
347
|
+
cls,
|
|
348
|
+
*_args,
|
|
349
|
+
mixin: bool | None = None,
|
|
350
|
+
primitives: list[type] | None = None,
|
|
351
|
+
callables: list[tuple[str, Callable]] | None = None,
|
|
352
|
+
semantic: bool = False,
|
|
353
|
+
**kwargs,
|
|
354
|
+
) -> "Symbol":
|
|
355
|
+
"""
|
|
323
356
|
Create a new Symbol instance.
|
|
324
357
|
|
|
325
358
|
Args:
|
|
@@ -332,10 +365,10 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
332
365
|
|
|
333
366
|
Returns:
|
|
334
367
|
Symbol: The new Symbol instance.
|
|
335
|
-
|
|
336
|
-
use_mixin
|
|
368
|
+
"""
|
|
369
|
+
use_mixin = mixin if mixin is not None else cls._mixin
|
|
337
370
|
standard_primitives = primitives is None
|
|
338
|
-
primitives
|
|
371
|
+
primitives = primitives if not standard_primitives else cls._primitives
|
|
339
372
|
if not isinstance(primitives, list):
|
|
340
373
|
primitives = [primitives]
|
|
341
374
|
# Initialize instance as a combination of Symbol and the mixin primitive types
|
|
@@ -346,11 +379,11 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
346
379
|
obj = super().__new__(target_cls)
|
|
347
380
|
# store to inherit when creating new instances
|
|
348
381
|
obj._kwargs = {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
**kwargs
|
|
382
|
+
"mixin": use_mixin,
|
|
383
|
+
"primitives": primitives,
|
|
384
|
+
"callables": callables,
|
|
385
|
+
"semantic": semantic,
|
|
386
|
+
**kwargs,
|
|
354
387
|
}
|
|
355
388
|
# configure standard primitives
|
|
356
389
|
if use_mixin and standard_primitives and semantic:
|
|
@@ -371,7 +404,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
371
404
|
return obj
|
|
372
405
|
|
|
373
406
|
def __setattr__(self, name: str, value: Any) -> None:
|
|
374
|
-
|
|
407
|
+
"""
|
|
375
408
|
Set the attribute of the Symbol's value with the specified name.
|
|
376
409
|
|
|
377
410
|
Args:
|
|
@@ -380,13 +413,13 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
380
413
|
|
|
381
414
|
Raises:
|
|
382
415
|
PropertyReservedError: If the property is reserved and cannot be set.
|
|
383
|
-
|
|
416
|
+
"""
|
|
384
417
|
if name in self._RESERVED_PROPERTIES:
|
|
385
418
|
raise PropertyReservedError(name)
|
|
386
419
|
super().__setattr__(name, value)
|
|
387
420
|
|
|
388
421
|
def __getattr__(self, name: str) -> Any:
|
|
389
|
-
|
|
422
|
+
"""
|
|
390
423
|
Get the attribute of the Symbol's value with the specified name or the attribute of the Symbol value with the specified name.
|
|
391
424
|
|
|
392
425
|
Args:
|
|
@@ -394,7 +427,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
394
427
|
|
|
395
428
|
Returns:
|
|
396
429
|
Any: The attribute of the Symbol's value with the specified name.
|
|
397
|
-
|
|
430
|
+
"""
|
|
398
431
|
try:
|
|
399
432
|
# try to get attribute from current instance
|
|
400
433
|
if name in self.__dict__:
|
|
@@ -406,21 +439,21 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
406
439
|
raise AttributeError(msg)
|
|
407
440
|
except AttributeError as ex:
|
|
408
441
|
# if has attribute and is public function
|
|
409
|
-
if hasattr(self.value, name) and not name.startswith(
|
|
442
|
+
if hasattr(self.value, name) and not name.startswith("_"):
|
|
410
443
|
return getattr(self.value, name)
|
|
411
444
|
raise ex
|
|
412
445
|
|
|
413
446
|
def __array__(self, dtype=None):
|
|
414
|
-
|
|
447
|
+
"""
|
|
415
448
|
Get the numpy array representation of the Symbol's value.
|
|
416
449
|
|
|
417
450
|
Returns:
|
|
418
451
|
np.ndarray: The numpy array representation of the Symbol's value.
|
|
419
|
-
|
|
452
|
+
"""
|
|
420
453
|
return self.embedding.astype(dtype, copy=False)
|
|
421
454
|
|
|
422
455
|
def __buffer__(self, flags=0):
|
|
423
|
-
|
|
456
|
+
"""
|
|
424
457
|
Get the buffer of the Symbol's value.
|
|
425
458
|
|
|
426
459
|
Args:
|
|
@@ -428,12 +461,12 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
428
461
|
|
|
429
462
|
Returns:
|
|
430
463
|
memoryview: The buffer of the Symbol's value.
|
|
431
|
-
|
|
464
|
+
"""
|
|
432
465
|
return memoryview(self.embedding)
|
|
433
466
|
|
|
434
467
|
@staticmethod
|
|
435
468
|
def symbols(*values) -> list["Symbol"]:
|
|
436
|
-
|
|
469
|
+
"""
|
|
437
470
|
Create a list of Symbol instances from a list of values.
|
|
438
471
|
|
|
439
472
|
Args:
|
|
@@ -441,11 +474,11 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
441
474
|
|
|
442
475
|
Returns:
|
|
443
476
|
List[Symbol]: The list of Symbol instances.
|
|
444
|
-
|
|
477
|
+
"""
|
|
445
478
|
return [Symbol(value) for value in values]
|
|
446
479
|
|
|
447
480
|
def __reduce__(self):
|
|
448
|
-
|
|
481
|
+
"""
|
|
449
482
|
This method is called by pickle to serialize the object.
|
|
450
483
|
It returns a tuple that contains:
|
|
451
484
|
- A callable object that when called produces a new object (e.g., the class of the object)
|
|
@@ -454,7 +487,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
454
487
|
|
|
455
488
|
Returns:
|
|
456
489
|
tuple: A tuple containing the callable object, the arguments for the callable object, and the state of the object.
|
|
457
|
-
|
|
490
|
+
"""
|
|
458
491
|
# Get the state of the object
|
|
459
492
|
state = self.__getstate__()
|
|
460
493
|
|
|
@@ -477,7 +510,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
477
510
|
# This will be called by pickle with the info from __reduce__ to recreate the dynamic class
|
|
478
511
|
@staticmethod
|
|
479
512
|
def _reconstruct_class(base_cls, use_mixin, primitives_info):
|
|
480
|
-
|
|
513
|
+
"""
|
|
481
514
|
Reconstruct the class from the serialized state.
|
|
482
515
|
|
|
483
516
|
Args:
|
|
@@ -487,53 +520,53 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
487
520
|
|
|
488
521
|
Returns:
|
|
489
522
|
Type: The reconstructed class.
|
|
490
|
-
|
|
523
|
+
"""
|
|
491
524
|
if use_mixin:
|
|
492
525
|
# Convert primitive info tuples back to types
|
|
493
|
-
primitives
|
|
526
|
+
primitives = [primitive for primitive, name in primitives_info]
|
|
494
527
|
# Create new cls with UnifiedMeta metaclass
|
|
495
528
|
cls = SymbolMeta(base_cls.__name__, (base_cls, *tuple(primitives)), {})
|
|
496
529
|
return cls()
|
|
497
530
|
return base_cls()
|
|
498
531
|
|
|
499
532
|
def __getstate__(self) -> dict[str, Any]:
|
|
500
|
-
|
|
533
|
+
"""
|
|
501
534
|
Get the state of the symbol for serialization.
|
|
502
535
|
|
|
503
536
|
Returns:
|
|
504
537
|
dict: The state of the symbol.
|
|
505
|
-
|
|
538
|
+
"""
|
|
506
539
|
state = vars(self).copy()
|
|
507
|
-
state.pop(
|
|
508
|
-
state.pop(
|
|
509
|
-
state.pop(
|
|
540
|
+
state.pop("_metadata", None)
|
|
541
|
+
state.pop("_parent", None)
|
|
542
|
+
state.pop("_children", None)
|
|
510
543
|
return state
|
|
511
544
|
|
|
512
545
|
def __setstate__(self, state) -> None:
|
|
513
|
-
|
|
546
|
+
"""
|
|
514
547
|
Set the state of the symbol for deserialization.
|
|
515
548
|
|
|
516
549
|
Args:
|
|
517
550
|
state (dict): The state to set the symbol to.
|
|
518
|
-
|
|
551
|
+
"""
|
|
519
552
|
vars(self).update(state)
|
|
520
|
-
self._metadata
|
|
553
|
+
self._metadata = Metadata()
|
|
521
554
|
self._metadata.symbol_type = type(self)
|
|
522
|
-
self._kwargs
|
|
523
|
-
self._parent
|
|
524
|
-
self._children
|
|
555
|
+
self._kwargs = self._kwargs
|
|
556
|
+
self._parent = None
|
|
557
|
+
self._children = []
|
|
525
558
|
|
|
526
559
|
def json(self) -> dict[str, Any]:
|
|
527
|
-
|
|
560
|
+
"""
|
|
528
561
|
Get the json-serializable dictionary representation of the Symbol instance.
|
|
529
562
|
|
|
530
563
|
Returns:
|
|
531
564
|
dict: The json-serializable dictionary representation of the Symbol instance.
|
|
532
|
-
|
|
565
|
+
"""
|
|
533
566
|
return self.__getstate__()
|
|
534
567
|
|
|
535
568
|
def serialize(self):
|
|
536
|
-
|
|
569
|
+
"""
|
|
537
570
|
Encode an Symbol instance into its dictionary representation.
|
|
538
571
|
|
|
539
572
|
Args:
|
|
@@ -541,11 +574,11 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
541
574
|
|
|
542
575
|
Returns:
|
|
543
576
|
dict: The dictionary representation of the Symbol instance.
|
|
544
|
-
|
|
577
|
+
"""
|
|
545
578
|
return json.dumps(self, cls=SymbolEncoder)
|
|
546
579
|
|
|
547
580
|
def _to_symbol(self, value: Any, **kwargs) -> "Symbol":
|
|
548
|
-
|
|
581
|
+
"""
|
|
549
582
|
Convert a value to a Symbol instance.
|
|
550
583
|
|
|
551
584
|
Args:
|
|
@@ -553,8 +586,8 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
553
586
|
|
|
554
587
|
Returns:
|
|
555
588
|
Symbol: The Symbol instance.
|
|
556
|
-
|
|
557
|
-
type_
|
|
589
|
+
"""
|
|
590
|
+
type_ = Symbol
|
|
558
591
|
if isinstance(value, type_):
|
|
559
592
|
return value
|
|
560
593
|
# inherit kwargs for new symbol instance
|
|
@@ -562,7 +595,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
562
595
|
return type_(value, **kwargs)
|
|
563
596
|
|
|
564
597
|
def _to_type(self, value: Any, **kwargs) -> "Symbol":
|
|
565
|
-
|
|
598
|
+
"""
|
|
566
599
|
Convert a value to its own type instance.
|
|
567
600
|
|
|
568
601
|
Args:
|
|
@@ -570,8 +603,8 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
570
603
|
|
|
571
604
|
Returns:
|
|
572
605
|
Type: The type instance.
|
|
573
|
-
|
|
574
|
-
type_
|
|
606
|
+
"""
|
|
607
|
+
type_ = type(self)
|
|
575
608
|
if isinstance(value, type_):
|
|
576
609
|
return value
|
|
577
610
|
# inherit kwargs for new symbol instance
|
|
@@ -580,101 +613,101 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
580
613
|
|
|
581
614
|
@property
|
|
582
615
|
def _symbol_type(self) -> "Symbol":
|
|
583
|
-
|
|
616
|
+
"""
|
|
584
617
|
Get the type of the Symbol instance.
|
|
585
618
|
|
|
586
619
|
Returns:
|
|
587
620
|
Symbol: The type of the Symbol instance.
|
|
588
|
-
|
|
621
|
+
"""
|
|
589
622
|
return Symbol
|
|
590
623
|
|
|
591
624
|
def __hash__(self) -> int:
|
|
592
|
-
|
|
625
|
+
"""
|
|
593
626
|
Get the hash value of the symbol.
|
|
594
627
|
|
|
595
628
|
Returns:
|
|
596
629
|
int: The hash value of the symbol.
|
|
597
|
-
|
|
630
|
+
"""
|
|
598
631
|
return str(self.value).__hash__()
|
|
599
632
|
|
|
600
633
|
@property
|
|
601
634
|
def metadata(self) -> dict[str, Any]:
|
|
602
|
-
|
|
635
|
+
"""
|
|
603
636
|
Get the metadata associated with the symbol.
|
|
604
637
|
|
|
605
638
|
Returns:
|
|
606
639
|
Dict[str, Any]: The metadata associated with the symbol.
|
|
607
|
-
|
|
640
|
+
"""
|
|
608
641
|
return self._metadata
|
|
609
642
|
|
|
610
643
|
@property
|
|
611
644
|
def value(self) -> Any:
|
|
612
|
-
|
|
645
|
+
"""
|
|
613
646
|
Get the value of the symbol.
|
|
614
647
|
|
|
615
648
|
Returns:
|
|
616
649
|
Any: The value of the symbol.
|
|
617
|
-
|
|
650
|
+
"""
|
|
618
651
|
return self._value
|
|
619
652
|
|
|
620
653
|
@property
|
|
621
654
|
def global_context(self) -> str:
|
|
622
|
-
|
|
655
|
+
"""
|
|
623
656
|
Get the global context of the symbol, which consists of the static and dynamic context.
|
|
624
657
|
|
|
625
658
|
Returns:
|
|
626
659
|
str: The global context of the symbol.
|
|
627
|
-
|
|
660
|
+
"""
|
|
628
661
|
return (self.static_context, self.dynamic_context)
|
|
629
662
|
|
|
630
663
|
@property
|
|
631
664
|
def static_context(self) -> str:
|
|
632
|
-
|
|
665
|
+
"""
|
|
633
666
|
Get the static context of the symbol which is defined by the user when creating a symbol subclass.
|
|
634
667
|
|
|
635
668
|
Returns:
|
|
636
669
|
str: The static context of the symbol.
|
|
637
|
-
|
|
638
|
-
return f
|
|
670
|
+
"""
|
|
671
|
+
return f"{self._static_context}" if self._static_context else ""
|
|
639
672
|
|
|
640
673
|
@static_context.setter
|
|
641
674
|
def static_context(self, value: str):
|
|
642
|
-
|
|
675
|
+
"""
|
|
643
676
|
Set the static context of the symbol which is defined by the user when creating a symbol subclass.
|
|
644
|
-
|
|
677
|
+
"""
|
|
645
678
|
self._static_context = value
|
|
646
679
|
|
|
647
680
|
@property
|
|
648
681
|
def dynamic_context(self) -> str:
|
|
649
|
-
|
|
682
|
+
"""
|
|
650
683
|
Get the dynamic context which is defined by the user at runtime.
|
|
651
684
|
It helps to alter the behavior of the symbol at runtime.
|
|
652
685
|
|
|
653
686
|
Returns:
|
|
654
687
|
str: The dynamic context associated with this symbol type.
|
|
655
|
-
|
|
688
|
+
"""
|
|
656
689
|
# if dynamic context is manually set to a string, return it
|
|
657
690
|
if isinstance(self._dynamic_context, str):
|
|
658
691
|
return self._dynamic_context
|
|
659
692
|
type_ = str(type(self))
|
|
660
693
|
if type_ not in Symbol._dynamic_context:
|
|
661
694
|
Symbol._dynamic_context[type_] = []
|
|
662
|
-
return
|
|
695
|
+
return ""
|
|
663
696
|
dyn_ctxt = Symbol._dynamic_context[type_]
|
|
664
697
|
if len(dyn_ctxt) == 0:
|
|
665
|
-
return
|
|
698
|
+
return ""
|
|
666
699
|
sym_val = [str(v.value) if isinstance(v, Symbol) else str(v) for v in dyn_ctxt]
|
|
667
|
-
val =
|
|
668
|
-
return f
|
|
700
|
+
val = "\n".join(sym_val)
|
|
701
|
+
return f"\n{val}" if val else ""
|
|
669
702
|
|
|
670
703
|
@property
|
|
671
704
|
def root(self) -> "Symbol":
|
|
672
|
-
|
|
705
|
+
"""
|
|
673
706
|
Get the root of the symbol.
|
|
674
707
|
|
|
675
708
|
Returns:
|
|
676
709
|
Symbol: The root of the symbol.
|
|
677
|
-
|
|
710
|
+
"""
|
|
678
711
|
root = self
|
|
679
712
|
while root.parent is not None:
|
|
680
713
|
root = root.parent
|
|
@@ -682,12 +715,13 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
682
715
|
|
|
683
716
|
@property
|
|
684
717
|
def nodes(self) -> list["Symbol"]:
|
|
685
|
-
|
|
718
|
+
"""
|
|
686
719
|
Get all nodes descending recursively from the symbol.
|
|
687
720
|
|
|
688
721
|
Returns:
|
|
689
722
|
List[Symbol]: All nodes of the symbol.
|
|
690
|
-
|
|
723
|
+
"""
|
|
724
|
+
|
|
691
725
|
def _func(node, nodes):
|
|
692
726
|
nodes.append(node)
|
|
693
727
|
for child in node.children:
|
|
@@ -699,12 +733,13 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
699
733
|
|
|
700
734
|
@property
|
|
701
735
|
def edges(self) -> list[tuple]:
|
|
702
|
-
|
|
736
|
+
"""
|
|
703
737
|
Get all edges descending recursively from the symbol.
|
|
704
738
|
|
|
705
739
|
Returns:
|
|
706
740
|
List[tuple]: All edges of the symbol.
|
|
707
|
-
|
|
741
|
+
"""
|
|
742
|
+
|
|
708
743
|
def _func(node, edges):
|
|
709
744
|
for child in node.children:
|
|
710
745
|
edges.append((node, child))
|
|
@@ -716,46 +751,46 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
716
751
|
|
|
717
752
|
@property
|
|
718
753
|
def graph(self) -> (list["Symbol"], list[tuple]):
|
|
719
|
-
|
|
754
|
+
"""
|
|
720
755
|
Get the graph representation of the symbol.
|
|
721
756
|
|
|
722
757
|
Returns:
|
|
723
758
|
List[Symbol], List[tuple]: The nodes and edges of the symbol.
|
|
724
|
-
|
|
759
|
+
"""
|
|
725
760
|
return self.nodes, self.edges
|
|
726
761
|
|
|
727
762
|
@property
|
|
728
763
|
def linker(self) -> list["Symbol"]:
|
|
729
|
-
|
|
764
|
+
"""
|
|
730
765
|
Returns the link object metadata by descending recursively from the root of the symbol to the root_link object.
|
|
731
766
|
|
|
732
767
|
Returns:
|
|
733
768
|
List[Symbol]: All results of the symbol.
|
|
734
|
-
|
|
769
|
+
"""
|
|
735
770
|
return self.root.metadata.root_link
|
|
736
771
|
|
|
737
772
|
@property
|
|
738
773
|
def parent(self) -> "Symbol":
|
|
739
|
-
|
|
774
|
+
"""
|
|
740
775
|
Get the parent of the symbol.
|
|
741
776
|
|
|
742
777
|
Returns:
|
|
743
778
|
Symbol: The parent of the symbol.
|
|
744
|
-
|
|
779
|
+
"""
|
|
745
780
|
return self._parent
|
|
746
781
|
|
|
747
782
|
@property
|
|
748
783
|
def children(self) -> list["Symbol"]:
|
|
749
|
-
|
|
784
|
+
"""
|
|
750
785
|
Get the children of the symbol.
|
|
751
786
|
|
|
752
787
|
Returns:
|
|
753
788
|
List[Symbol]: The children of the symbol.
|
|
754
|
-
|
|
789
|
+
"""
|
|
755
790
|
return self._children
|
|
756
791
|
|
|
757
792
|
def _root_link(self, sym: Any, **_kwargs) -> Any:
|
|
758
|
-
|
|
793
|
+
"""
|
|
759
794
|
Call the forward method and assign the result to the graph value attribute.
|
|
760
795
|
|
|
761
796
|
Args:
|
|
@@ -764,7 +799,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
764
799
|
|
|
765
800
|
Returns:
|
|
766
801
|
Any: The result of the forward method.
|
|
767
|
-
|
|
802
|
+
"""
|
|
768
803
|
# transport results to the root node for global access
|
|
769
804
|
if self is not self.root and not self.metadata.detach:
|
|
770
805
|
ref = self.root.metadata
|
|
@@ -774,7 +809,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
774
809
|
ref.root_link.results = {}
|
|
775
810
|
prev = None
|
|
776
811
|
if len(ref.root_link.results) > 0:
|
|
777
|
-
prev = list(ref.root_link.results.values())[-1]
|
|
812
|
+
prev = list(ref.root_link.results.values())[-1] # get previous result
|
|
778
813
|
# create new symbol to avoid circular references
|
|
779
814
|
res_ = Symbol(sym)
|
|
780
815
|
if prev is not None and prev is not res_.root:
|
|
@@ -783,14 +818,14 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
783
818
|
ref.root_link.results[self.__repr__()] = res_
|
|
784
819
|
|
|
785
820
|
def adapt(self, context: str, types: list[type] | None = None) -> None:
|
|
786
|
-
|
|
821
|
+
"""
|
|
787
822
|
Update the dynamic context with a given runtime context.
|
|
788
823
|
|
|
789
824
|
Args:
|
|
790
825
|
context (str): The context to be added to the dynamic context.
|
|
791
826
|
type (Type): The type used to update the dynamic context
|
|
792
827
|
|
|
793
|
-
|
|
828
|
+
"""
|
|
794
829
|
if types is None:
|
|
795
830
|
types = []
|
|
796
831
|
if not isinstance(types, list):
|
|
@@ -806,9 +841,9 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
806
841
|
Symbol._dynamic_context[type_key].append(str(context))
|
|
807
842
|
|
|
808
843
|
def clear(self, types: list[type] | None = None) -> None:
|
|
809
|
-
|
|
844
|
+
"""
|
|
810
845
|
Clear the dynamic context associated with this symbol type.
|
|
811
|
-
|
|
846
|
+
"""
|
|
812
847
|
if types is None:
|
|
813
848
|
types = []
|
|
814
849
|
if not isinstance(types, list):
|
|
@@ -825,33 +860,33 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
825
860
|
Symbol._dynamic_context[type_key].clear()
|
|
826
861
|
|
|
827
862
|
def __len__(self) -> int:
|
|
828
|
-
|
|
863
|
+
"""
|
|
829
864
|
Get the length of the value of the Symbol.
|
|
830
865
|
|
|
831
866
|
Returns:
|
|
832
867
|
int: The length of the value of the Symbol.
|
|
833
|
-
|
|
868
|
+
"""
|
|
834
869
|
return len(self.value)
|
|
835
870
|
|
|
836
871
|
@property
|
|
837
872
|
def shape(self) -> tuple:
|
|
838
|
-
|
|
873
|
+
"""
|
|
839
874
|
Get the shape of the value of the Symbol.
|
|
840
875
|
|
|
841
876
|
Returns:
|
|
842
877
|
tuple: The shape of the value of the Symbol.
|
|
843
|
-
|
|
878
|
+
"""
|
|
844
879
|
return self.value.shape
|
|
845
880
|
|
|
846
881
|
def __str__(self) -> str:
|
|
847
|
-
|
|
882
|
+
"""
|
|
848
883
|
Get the string representation of the Symbol's value.
|
|
849
884
|
|
|
850
885
|
Returns:
|
|
851
886
|
str: The string representation of the Symbol's value.
|
|
852
|
-
|
|
887
|
+
"""
|
|
853
888
|
if self.value is None:
|
|
854
|
-
return
|
|
889
|
+
return ""
|
|
855
890
|
if isinstance(self.value, (list, np.ndarray, tuple)):
|
|
856
891
|
return str([str(v) for v in self.value])
|
|
857
892
|
if isinstance(self.value, dict):
|
|
@@ -861,54 +896,56 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
861
896
|
return str(self.value)
|
|
862
897
|
|
|
863
898
|
def __repr__(self, simplified: bool = False) -> str:
|
|
864
|
-
|
|
899
|
+
"""
|
|
865
900
|
Get the representation of the Symbol object as a string.
|
|
866
901
|
|
|
867
902
|
Returns:
|
|
868
903
|
str: The representation of the Symbol object.
|
|
869
|
-
|
|
904
|
+
"""
|
|
870
905
|
# class with full path
|
|
871
|
-
class_ = self.__class__.__module__ +
|
|
872
|
-
hex_
|
|
873
|
-
val
|
|
906
|
+
class_ = self.__class__.__module__ + "." + self.__class__.__name__
|
|
907
|
+
hex_ = hex(id(self))
|
|
908
|
+
val = str(self.value)
|
|
874
909
|
# only show first n characters of value and then add '...' and the last x characters
|
|
875
910
|
if len(val) > 50:
|
|
876
|
-
val = val[:25] +
|
|
877
|
-
return
|
|
911
|
+
val = val[:25] + " ... " + val[-20:]
|
|
912
|
+
return (
|
|
913
|
+
f"<class {class_} at {hex_}>(value={val})" if not simplified else f"{class_} at {hex_}"
|
|
914
|
+
)
|
|
878
915
|
|
|
879
916
|
def _repr_html_(self) -> str:
|
|
880
|
-
|
|
917
|
+
"""
|
|
881
918
|
Get the HTML representation of the Symbol's value.
|
|
882
919
|
|
|
883
920
|
Returns:
|
|
884
921
|
str: The HTML representation of the Symbol's value.
|
|
885
|
-
|
|
922
|
+
"""
|
|
886
923
|
return html.escape(self.__repr__())
|
|
887
924
|
|
|
888
925
|
def __iter__(self) -> Iterator:
|
|
889
|
-
|
|
926
|
+
"""
|
|
890
927
|
Get an iterator for the Symbol's value.
|
|
891
928
|
If the Symbol's value is a list, tuple, or numpy.ndarray, iterate over the elements. Otherwise, create a new list with a single item and iterate over the list.
|
|
892
929
|
|
|
893
930
|
Returns:
|
|
894
931
|
Iterator: An iterator for the Symbol's value.
|
|
895
|
-
|
|
932
|
+
"""
|
|
896
933
|
if isinstance(self.value, (list, tuple, np.ndarray)):
|
|
897
934
|
return iter(self.value)
|
|
898
935
|
|
|
899
|
-
return self.list(
|
|
936
|
+
return self.list("item").value.__iter__()
|
|
900
937
|
|
|
901
938
|
def __reversed__(self) -> Iterator:
|
|
902
|
-
|
|
939
|
+
"""
|
|
903
940
|
Get a reversed iterator for the Symbol's value.
|
|
904
941
|
|
|
905
942
|
Returns:
|
|
906
943
|
Iterator: A reversed iterator for the Symbol's value.
|
|
907
|
-
|
|
944
|
+
"""
|
|
908
945
|
return reversed(list(self.__iter__()))
|
|
909
946
|
|
|
910
947
|
def __next__(self) -> Any:
|
|
911
|
-
|
|
948
|
+
"""
|
|
912
949
|
Get the next item in the iterable value of the Symbol.
|
|
913
950
|
If it is not a list, tuple, or numpy array, the method falls back to using the @core.next() decorator, which retrieves and returns the next item using core functions.
|
|
914
951
|
|
|
@@ -917,11 +954,11 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
917
954
|
|
|
918
955
|
Raises:
|
|
919
956
|
StopIteration: If the iterable value reaches its end.
|
|
920
|
-
|
|
957
|
+
"""
|
|
921
958
|
return next(self.__iter__())
|
|
922
959
|
|
|
923
960
|
def primitive(self, name: str, callable: callable) -> None:
|
|
924
|
-
|
|
961
|
+
"""
|
|
925
962
|
Set a primitive function to the Symbol instance.
|
|
926
963
|
|
|
927
964
|
Args:
|
|
@@ -931,21 +968,25 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
931
968
|
|
|
932
969
|
Args:
|
|
933
970
|
callable (callable): The primitive function to set.
|
|
934
|
-
|
|
971
|
+
"""
|
|
972
|
+
|
|
935
973
|
def _func(*args, **kwargs):
|
|
936
974
|
return callable(self, *args, **kwargs)
|
|
975
|
+
|
|
937
976
|
setattr(self, name, _func)
|
|
938
977
|
|
|
939
978
|
@staticmethod
|
|
940
979
|
def _global_primitive(name: str, callable: callable) -> None:
|
|
941
|
-
|
|
980
|
+
"""
|
|
942
981
|
Set a primitive function to the Symbol class.
|
|
943
982
|
|
|
944
983
|
Args:
|
|
945
984
|
callable (callable): The primitive function to set.
|
|
946
|
-
|
|
985
|
+
"""
|
|
986
|
+
|
|
947
987
|
def _func(obj):
|
|
948
988
|
return lambda *args, **kwargs: callable(obj, *args, **kwargs)
|
|
989
|
+
|
|
949
990
|
Symbol._metadata._primitives[name] = _func
|
|
950
991
|
|
|
951
992
|
|
|
@@ -954,7 +995,7 @@ class Symbol(metaclass=SymbolMeta):
|
|
|
954
995
|
# Need to contact Python developers to fix this bug.
|
|
955
996
|
class Call:
|
|
956
997
|
def __new__(cls, name, callable: Callable) -> Any:
|
|
957
|
-
|
|
998
|
+
"""
|
|
958
999
|
Prepare a callable for use in a Symbol instance.
|
|
959
1000
|
|
|
960
1001
|
Args:
|
|
@@ -962,15 +1003,17 @@ class Call:
|
|
|
962
1003
|
|
|
963
1004
|
Returns:
|
|
964
1005
|
Callable: The prepared callable.
|
|
965
|
-
|
|
1006
|
+
"""
|
|
1007
|
+
|
|
966
1008
|
def _func(obj):
|
|
967
1009
|
return lambda *args, **kwargs: callable(obj, *args, **kwargs)
|
|
1010
|
+
|
|
968
1011
|
return (name, _func)
|
|
969
1012
|
|
|
970
1013
|
|
|
971
1014
|
class GlobalSymbolPrimitive:
|
|
972
1015
|
def __new__(cls, name, callable: Callable) -> Any:
|
|
973
|
-
|
|
1016
|
+
"""
|
|
974
1017
|
Prepare a callable for use in a Symbol instance.
|
|
975
1018
|
|
|
976
1019
|
Args:
|
|
@@ -978,7 +1021,7 @@ class GlobalSymbolPrimitive:
|
|
|
978
1021
|
|
|
979
1022
|
Returns:
|
|
980
1023
|
Callable: The prepared callable.
|
|
981
|
-
|
|
1024
|
+
"""
|
|
982
1025
|
Symbol._global_primitive(name, callable)
|
|
983
1026
|
|
|
984
1027
|
|
|
@@ -990,9 +1033,8 @@ class ExpressionEncoder(JSONEncoder):
|
|
|
990
1033
|
|
|
991
1034
|
|
|
992
1035
|
class Expression(Symbol):
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
'''
|
|
1036
|
+
def __init__(self, value=None, *args, **kwargs):
|
|
1037
|
+
"""
|
|
996
1038
|
Create an Expression object that will be evaluated lazily using the forward method.
|
|
997
1039
|
|
|
998
1040
|
Args:
|
|
@@ -1000,12 +1042,12 @@ class Expression(Symbol):
|
|
|
1000
1042
|
is computed using the forward method when called. Defaults to None.
|
|
1001
1043
|
*args: Variable length argument list.
|
|
1002
1044
|
**kwargs: Arbitrary keyword arguments.
|
|
1003
|
-
|
|
1045
|
+
"""
|
|
1004
1046
|
super().__init__(value, *args, **kwargs)
|
|
1005
1047
|
self._sym_return_type = type(self)
|
|
1006
1048
|
|
|
1007
1049
|
def __call__(self, *args, **kwargs) -> Any:
|
|
1008
|
-
|
|
1050
|
+
"""
|
|
1009
1051
|
Evaluate the expression using the forward method and assign the result to the value attribute.
|
|
1010
1052
|
|
|
1011
1053
|
Args:
|
|
@@ -1014,7 +1056,7 @@ class Expression(Symbol):
|
|
|
1014
1056
|
|
|
1015
1057
|
Returns:
|
|
1016
1058
|
Any: The result of the forward method.
|
|
1017
|
-
|
|
1059
|
+
"""
|
|
1018
1060
|
# evaluate the expression
|
|
1019
1061
|
res = self.forward(*args, **kwargs)
|
|
1020
1062
|
# store the result in the root node and link it to the previous result
|
|
@@ -1023,7 +1065,7 @@ class Expression(Symbol):
|
|
|
1023
1065
|
|
|
1024
1066
|
def __getstate__(self):
|
|
1025
1067
|
state = super().__getstate__().copy()
|
|
1026
|
-
state.pop(
|
|
1068
|
+
state.pop("_sym_return_type", None)
|
|
1027
1069
|
return state
|
|
1028
1070
|
|
|
1029
1071
|
def __setstate__(self, state):
|
|
@@ -1031,16 +1073,16 @@ class Expression(Symbol):
|
|
|
1031
1073
|
self._sym_return_type = type(self)
|
|
1032
1074
|
|
|
1033
1075
|
def __json__(self):
|
|
1034
|
-
|
|
1076
|
+
"""
|
|
1035
1077
|
Get the json-serializable dictionary representation of the Expression instance.
|
|
1036
1078
|
|
|
1037
1079
|
Returns:
|
|
1038
1080
|
dict: The json-serializable dictionary representation of the Expression instance.
|
|
1039
|
-
|
|
1081
|
+
"""
|
|
1040
1082
|
return self.__getstate__()
|
|
1041
1083
|
|
|
1042
1084
|
def serialize(self):
|
|
1043
|
-
|
|
1085
|
+
"""
|
|
1044
1086
|
Encode an Expression instance into its dictionary representation.
|
|
1045
1087
|
|
|
1046
1088
|
Args:
|
|
@@ -1048,31 +1090,33 @@ class Expression(Symbol):
|
|
|
1048
1090
|
|
|
1049
1091
|
Returns:
|
|
1050
1092
|
dict: The dictionary representation of the Expression instance.
|
|
1051
|
-
|
|
1093
|
+
"""
|
|
1052
1094
|
return json.dumps(self, cls=ExpressionEncoder)
|
|
1053
1095
|
|
|
1054
1096
|
@property
|
|
1055
1097
|
def sym_return_type(self) -> type:
|
|
1056
|
-
|
|
1098
|
+
"""
|
|
1057
1099
|
Returns the casting type of this expression.
|
|
1058
1100
|
|
|
1059
1101
|
Returns:
|
|
1060
1102
|
Type: The casting type of this expression. Defaults to the current Expression-type.
|
|
1061
|
-
|
|
1103
|
+
"""
|
|
1062
1104
|
return self._sym_return_type
|
|
1063
1105
|
|
|
1064
1106
|
@sym_return_type.setter
|
|
1065
1107
|
def sym_return_type(self, type: type) -> None:
|
|
1066
|
-
|
|
1108
|
+
"""
|
|
1067
1109
|
Sets the casting type of this expression.
|
|
1068
1110
|
|
|
1069
1111
|
Args:
|
|
1070
1112
|
type (Type): The casting type of this expression.
|
|
1071
|
-
|
|
1113
|
+
"""
|
|
1072
1114
|
self._sym_return_type = type
|
|
1073
1115
|
|
|
1074
|
-
def forward(
|
|
1075
|
-
|
|
1116
|
+
def forward(
|
|
1117
|
+
self, *args, **kwargs
|
|
1118
|
+
) -> Symbol: # TODO make reserved kwargs with underscore: __<cmd>__
|
|
1119
|
+
"""
|
|
1076
1120
|
Needs to be implemented by subclasses to specify the behavior of the expression during evaluation.
|
|
1077
1121
|
|
|
1078
1122
|
Args:
|
|
@@ -1081,12 +1125,12 @@ class Expression(Symbol):
|
|
|
1081
1125
|
|
|
1082
1126
|
Returns:
|
|
1083
1127
|
Symbol: The evaluated result of the implemented forward method.
|
|
1084
|
-
|
|
1128
|
+
"""
|
|
1085
1129
|
raise NotImplementedError
|
|
1086
1130
|
|
|
1087
1131
|
@staticmethod
|
|
1088
|
-
def command(engines: list[str] | None = None, **kwargs) ->
|
|
1089
|
-
|
|
1132
|
+
def command(engines: list[str] | None = None, **kwargs) -> "Symbol":
|
|
1133
|
+
"""
|
|
1090
1134
|
Execute command(s) on engines.
|
|
1091
1135
|
|
|
1092
1136
|
Args:
|
|
@@ -1095,18 +1139,19 @@ class Expression(Symbol):
|
|
|
1095
1139
|
|
|
1096
1140
|
Returns:
|
|
1097
1141
|
Symbol: An Expression object representing the command execution result.
|
|
1098
|
-
|
|
1142
|
+
"""
|
|
1099
1143
|
if engines is None:
|
|
1100
|
-
engines = [
|
|
1144
|
+
engines = ["all"]
|
|
1101
1145
|
|
|
1102
1146
|
@core.command(engines=engines, **kwargs)
|
|
1103
1147
|
def _func(_):
|
|
1104
1148
|
pass
|
|
1149
|
+
|
|
1105
1150
|
return Expression(_func(Expression()))
|
|
1106
1151
|
|
|
1107
1152
|
@staticmethod
|
|
1108
|
-
def register(engines: dict[str, Any], **kwargs) ->
|
|
1109
|
-
|
|
1153
|
+
def register(engines: dict[str, Any], **kwargs) -> "Symbol":
|
|
1154
|
+
"""
|
|
1110
1155
|
Configure multiple engines.
|
|
1111
1156
|
|
|
1112
1157
|
Args:
|
|
@@ -1115,24 +1160,26 @@ class Expression(Symbol):
|
|
|
1115
1160
|
|
|
1116
1161
|
Returns:
|
|
1117
1162
|
Symbol: An Expression object representing the register result.
|
|
1118
|
-
|
|
1163
|
+
"""
|
|
1164
|
+
|
|
1119
1165
|
@core.register(engines=engines, **kwargs)
|
|
1120
1166
|
def _func(_):
|
|
1121
1167
|
pass
|
|
1168
|
+
|
|
1122
1169
|
return Expression(_func(Expression()))
|
|
1123
1170
|
|
|
1124
1171
|
def copy(self) -> Any:
|
|
1125
|
-
|
|
1172
|
+
"""
|
|
1126
1173
|
Returns a deep copy of the own object.
|
|
1127
1174
|
|
|
1128
1175
|
Returns:
|
|
1129
1176
|
Any: A deep copy of the own object.
|
|
1130
|
-
|
|
1177
|
+
"""
|
|
1131
1178
|
return copy.deepcopy(self)
|
|
1132
1179
|
|
|
1133
1180
|
@staticmethod
|
|
1134
|
-
def prompt(message: str, **kwargs) ->
|
|
1135
|
-
|
|
1181
|
+
def prompt(message: str, **kwargs) -> "Symbol":
|
|
1182
|
+
"""
|
|
1136
1183
|
General raw input prompt method.
|
|
1137
1184
|
|
|
1138
1185
|
Args:
|
|
@@ -1141,16 +1188,18 @@ class Expression(Symbol):
|
|
|
1141
1188
|
|
|
1142
1189
|
Returns:
|
|
1143
1190
|
Symbol: An Expression object representing the prompt result.
|
|
1144
|
-
|
|
1191
|
+
"""
|
|
1192
|
+
|
|
1145
1193
|
@core.prompt(message=message, **kwargs)
|
|
1146
1194
|
def _func(_):
|
|
1147
1195
|
pass
|
|
1196
|
+
|
|
1148
1197
|
return Expression(_func(None))
|
|
1149
1198
|
|
|
1150
1199
|
|
|
1151
1200
|
class Result(Expression):
|
|
1152
|
-
def __init__(self, value
|
|
1153
|
-
|
|
1201
|
+
def __init__(self, value=None, *_args, **kwargs):
|
|
1202
|
+
"""
|
|
1154
1203
|
Create a Result object that stores the results operations, including the raw result, value and metadata, if any.
|
|
1155
1204
|
|
|
1156
1205
|
Args:
|
|
@@ -1158,8 +1207,10 @@ class Result(Expression):
|
|
|
1158
1207
|
is computed using the forward method when called. Defaults to None.
|
|
1159
1208
|
*args: Variable length argument list.
|
|
1160
1209
|
**kwargs: Arbitrary keyword arguments.
|
|
1161
|
-
|
|
1162
|
-
super().__init__(
|
|
1210
|
+
"""
|
|
1211
|
+
super().__init__(
|
|
1212
|
+
value, **kwargs
|
|
1213
|
+
) # value is the same as raw when initialized, however, it can be changed later
|
|
1163
1214
|
self._sym_return_type = type(self)
|
|
1164
1215
|
try:
|
|
1165
1216
|
# try to make the values easily accessible
|
|
@@ -1170,20 +1221,20 @@ class Result(Expression):
|
|
|
1170
1221
|
|
|
1171
1222
|
@property
|
|
1172
1223
|
def value(self) -> Any:
|
|
1173
|
-
|
|
1224
|
+
"""
|
|
1174
1225
|
Get the value of the symbol.
|
|
1175
1226
|
|
|
1176
1227
|
Returns:
|
|
1177
1228
|
Any: The value of the symbol.
|
|
1178
|
-
|
|
1229
|
+
"""
|
|
1179
1230
|
return self._value
|
|
1180
1231
|
|
|
1181
1232
|
@value.setter
|
|
1182
1233
|
def value(self, value: Any) -> None:
|
|
1183
|
-
|
|
1234
|
+
"""
|
|
1184
1235
|
Set the value of the Result object.
|
|
1185
1236
|
|
|
1186
1237
|
Args:
|
|
1187
1238
|
value (Any): The value to set the Result object to.
|
|
1188
|
-
|
|
1239
|
+
"""
|
|
1189
1240
|
self._value = value
|