symbolicai 0.20.2__py3-none-any.whl → 1.0.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.
Files changed (123) hide show
  1. symai/__init__.py +96 -64
  2. symai/backend/base.py +93 -80
  3. symai/backend/engines/drawing/engine_bfl.py +12 -11
  4. symai/backend/engines/drawing/engine_gpt_image.py +108 -87
  5. symai/backend/engines/embedding/engine_llama_cpp.py +25 -28
  6. symai/backend/engines/embedding/engine_openai.py +3 -5
  7. symai/backend/engines/execute/engine_python.py +6 -5
  8. symai/backend/engines/files/engine_io.py +74 -67
  9. symai/backend/engines/imagecaptioning/engine_blip2.py +3 -3
  10. symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +54 -38
  11. symai/backend/engines/index/engine_pinecone.py +23 -24
  12. symai/backend/engines/index/engine_vectordb.py +16 -14
  13. symai/backend/engines/lean/engine_lean4.py +38 -34
  14. symai/backend/engines/neurosymbolic/__init__.py +41 -13
  15. symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +262 -182
  16. symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +263 -191
  17. symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +53 -49
  18. symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +212 -211
  19. symai/backend/engines/neurosymbolic/engine_groq.py +87 -63
  20. symai/backend/engines/neurosymbolic/engine_huggingface.py +21 -24
  21. symai/backend/engines/neurosymbolic/engine_llama_cpp.py +117 -48
  22. symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +256 -229
  23. symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +270 -150
  24. symai/backend/engines/ocr/engine_apilayer.py +6 -8
  25. symai/backend/engines/output/engine_stdout.py +1 -4
  26. symai/backend/engines/search/engine_openai.py +7 -7
  27. symai/backend/engines/search/engine_perplexity.py +5 -5
  28. symai/backend/engines/search/engine_serpapi.py +12 -14
  29. symai/backend/engines/speech_to_text/engine_local_whisper.py +20 -27
  30. symai/backend/engines/symbolic/engine_wolframalpha.py +3 -3
  31. symai/backend/engines/text_to_speech/engine_openai.py +5 -7
  32. symai/backend/engines/text_vision/engine_clip.py +7 -11
  33. symai/backend/engines/userinput/engine_console.py +3 -3
  34. symai/backend/engines/webscraping/engine_requests.py +81 -48
  35. symai/backend/mixin/__init__.py +13 -0
  36. symai/backend/mixin/anthropic.py +4 -2
  37. symai/backend/mixin/deepseek.py +2 -0
  38. symai/backend/mixin/google.py +2 -0
  39. symai/backend/mixin/openai.py +11 -3
  40. symai/backend/settings.py +83 -16
  41. symai/chat.py +101 -78
  42. symai/collect/__init__.py +7 -1
  43. symai/collect/dynamic.py +77 -69
  44. symai/collect/pipeline.py +35 -27
  45. symai/collect/stats.py +75 -63
  46. symai/components.py +198 -169
  47. symai/constraints.py +15 -12
  48. symai/core.py +698 -359
  49. symai/core_ext.py +32 -34
  50. symai/endpoints/api.py +80 -73
  51. symai/extended/.DS_Store +0 -0
  52. symai/extended/__init__.py +46 -12
  53. symai/extended/api_builder.py +11 -8
  54. symai/extended/arxiv_pdf_parser.py +13 -12
  55. symai/extended/bibtex_parser.py +2 -3
  56. symai/extended/conversation.py +101 -90
  57. symai/extended/document.py +17 -10
  58. symai/extended/file_merger.py +18 -13
  59. symai/extended/graph.py +18 -13
  60. symai/extended/html_style_template.py +2 -4
  61. symai/extended/interfaces/blip_2.py +1 -2
  62. symai/extended/interfaces/clip.py +1 -2
  63. symai/extended/interfaces/console.py +7 -1
  64. symai/extended/interfaces/dall_e.py +1 -1
  65. symai/extended/interfaces/flux.py +1 -1
  66. symai/extended/interfaces/gpt_image.py +1 -1
  67. symai/extended/interfaces/input.py +1 -1
  68. symai/extended/interfaces/llava.py +0 -1
  69. symai/extended/interfaces/naive_vectordb.py +7 -8
  70. symai/extended/interfaces/naive_webscraping.py +1 -1
  71. symai/extended/interfaces/ocr.py +1 -1
  72. symai/extended/interfaces/pinecone.py +6 -5
  73. symai/extended/interfaces/serpapi.py +1 -1
  74. symai/extended/interfaces/terminal.py +2 -3
  75. symai/extended/interfaces/tts.py +1 -1
  76. symai/extended/interfaces/whisper.py +1 -1
  77. symai/extended/interfaces/wolframalpha.py +1 -1
  78. symai/extended/metrics/__init__.py +11 -1
  79. symai/extended/metrics/similarity.py +11 -13
  80. symai/extended/os_command.py +17 -16
  81. symai/extended/packages/__init__.py +29 -3
  82. symai/extended/packages/symdev.py +19 -16
  83. symai/extended/packages/sympkg.py +12 -9
  84. symai/extended/packages/symrun.py +21 -19
  85. symai/extended/repo_cloner.py +11 -10
  86. symai/extended/seo_query_optimizer.py +1 -2
  87. symai/extended/solver.py +20 -23
  88. symai/extended/summarizer.py +4 -3
  89. symai/extended/taypan_interpreter.py +10 -12
  90. symai/extended/vectordb.py +99 -82
  91. symai/formatter/__init__.py +9 -1
  92. symai/formatter/formatter.py +12 -16
  93. symai/formatter/regex.py +62 -63
  94. symai/functional.py +176 -122
  95. symai/imports.py +136 -127
  96. symai/interfaces.py +56 -27
  97. symai/memory.py +14 -13
  98. symai/misc/console.py +49 -39
  99. symai/misc/loader.py +5 -3
  100. symai/models/__init__.py +17 -1
  101. symai/models/base.py +269 -181
  102. symai/models/errors.py +0 -1
  103. symai/ops/__init__.py +32 -22
  104. symai/ops/measures.py +11 -15
  105. symai/ops/primitives.py +348 -228
  106. symai/post_processors.py +32 -28
  107. symai/pre_processors.py +39 -41
  108. symai/processor.py +6 -4
  109. symai/prompts.py +59 -45
  110. symai/server/huggingface_server.py +23 -20
  111. symai/server/llama_cpp_server.py +7 -5
  112. symai/shell.py +3 -4
  113. symai/shellsv.py +499 -375
  114. symai/strategy.py +517 -287
  115. symai/symbol.py +111 -116
  116. symai/utils.py +42 -36
  117. {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/METADATA +4 -2
  118. symbolicai-1.0.0.dist-info/RECORD +163 -0
  119. symbolicai-0.20.2.dist-info/RECORD +0 -162
  120. {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/WHEEL +0 -0
  121. {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/entry_points.txt +0 -0
  122. {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/licenses/LICENSE +0 -0
  123. {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/top_level.txt +0 -0
symai/symbol.py CHANGED
@@ -1,9 +1,9 @@
1
1
  import copy
2
2
  import html
3
3
  import json
4
+ from collections.abc import Callable, Iterator
4
5
  from json import JSONEncoder
5
- from typing import (Any, Callable, Dict, Generic, Iterator, List, Optional,
6
- Tuple, Type, TypeVar)
6
+ from typing import Any, ClassVar
7
7
 
8
8
  import numpy as np
9
9
  from box import Box
@@ -11,8 +11,6 @@ from box import Box
11
11
  from . import core
12
12
  from .ops import SYMBOL_PRIMITIVES
13
13
 
14
- T = TypeVar('T')
15
-
16
14
 
17
15
  class SymbolEncoder(JSONEncoder):
18
16
  def default(self, o):
@@ -30,7 +28,7 @@ class SymbolEncoder(JSONEncoder):
30
28
  return JSONEncoder.default(self, o)
31
29
 
32
30
 
33
- class Metadata(object):
31
+ class Metadata:
34
32
  # create a method that allow to dynamically assign a attribute if not in __dict__
35
33
  # example: metadata = Metadata()
36
34
  # metadata.some_new_attribute = 'some_value'
@@ -111,7 +109,7 @@ class Metadata(object):
111
109
  _val = ''
112
110
  if self.value is not None:
113
111
  _val += str(self.value)
114
- return _val + f"Properties({str({k: str(v) for k, v in self.__dict__.items() if not k.startswith('_')})})"
112
+ return _val + f"Properties({ {k: str(v) for k, v in self.__dict__.items() if not k.startswith('_')}!s})"
115
113
 
116
114
  def __repr__(self) -> str:
117
115
  '''
@@ -128,7 +126,7 @@ class Metadata(object):
128
126
 
129
127
 
130
128
  class Linker(Metadata):
131
- def keys(self) -> List[str]:
129
+ def keys(self) -> list[str]:
132
130
  '''
133
131
  Get all keys of the linker.
134
132
 
@@ -137,7 +135,7 @@ class Linker(Metadata):
137
135
  '''
138
136
  return list(self.results.keys())
139
137
 
140
- def values(self) -> List[Any]:
138
+ def values(self) -> list[Any]:
141
139
  '''
142
140
  Get all values of the linker.
143
141
 
@@ -160,15 +158,19 @@ class Linker(Metadata):
160
158
  '''
161
159
  # search all results and return the first one that matches the name
162
160
  res = []
161
+ def match_(key, search_name):
162
+ if strict:
163
+ return str(search_name) == str(key)
164
+ return str(search_name).lower() in str(key).lower()
165
+
163
166
  for k in list(self.results.keys()):
164
- match_ = lambda k, name: str(name).lower() in str(k).lower() if not strict else str(name) == str(k)
165
167
  if match_(k, name):
166
168
  res.append(self.results[k])
167
169
  if single:
168
170
  assert len(res) == 1, f'Found {len(res)} results for name {name}. Expected 1.'
169
171
  if len(res) == 0:
170
172
  return None
171
- elif len(res) == 1:
173
+ if len(res) == 1:
172
174
  return res[0]
173
175
  return res
174
176
 
@@ -207,15 +209,16 @@ class SymbolMeta(type):
207
209
  return cls
208
210
 
209
211
 
210
- class Symbol(Generic[T], metaclass=SymbolMeta):
211
- _mixin = True
212
- _primitives = SYMBOL_PRIMITIVES
213
- _metadata = Metadata()
214
- _metadata._primitives = {}
215
- _dynamic_context: Dict[str, List[str]] = {}
216
- _RESERVED_PROPERTIES = {'graph', 'linker', 'parent', 'children', 'metadata', 'value', 'root', 'nodes', 'edges', 'global_context', 'static_context', 'dynamic_context', 'shape'}
212
+ class Symbol(metaclass=SymbolMeta):
213
+ _mixin: ClassVar[bool] = True
214
+ _primitives: ClassVar[dict[str, type]] = SYMBOL_PRIMITIVES
215
+ _metadata: ClassVar[Metadata] = Metadata()
216
+ _metadata_primitives: ClassVar[dict[str, Callable]] = {}
217
+ _metadata._primitives = _metadata_primitives
218
+ _dynamic_context: ClassVar[dict[str, list[str]]] = {}
219
+ _RESERVED_PROPERTIES: ClassVar[set[str]] = {'graph', 'linker', 'parent', 'children', 'metadata', 'value', 'root', 'nodes', 'edges', 'global_context', 'static_context', 'dynamic_context', 'shape'}
217
220
 
218
- def __init__(self, *value, static_context: Optional[str] = '', dynamic_context: Optional[str] = None, **kwargs) -> None:
221
+ def __init__(self, *value, static_context: str | None = '', dynamic_context: str | None = None, **kwargs) -> None:
219
222
  '''
220
223
  Initialize a Symbol instance with a specified value. Unwraps nested symbols.
221
224
 
@@ -252,11 +255,11 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
252
255
  '''
253
256
  def _func(k, v):
254
257
  # check if property is of type Symbol and not private and a class variable (not a function)
255
- if isinstance(v, Symbol) and not k.startswith('_') and not v is self:
258
+ if isinstance(v, Symbol) and not k.startswith('_') and v is not self:
256
259
  v._parent = self
257
260
  self._children.append(v)
258
261
  # else if iterable, check if it contains symbols
259
- elif (isinstance(v, list) or isinstance(v, tuple)) and not k.startswith('_'):
262
+ elif isinstance(v, (list, tuple)) and not k.startswith('_'):
260
263
  for i in v:
261
264
  _func(k, i)
262
265
 
@@ -267,45 +270,33 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
267
270
  def _unwrap_symbols_args(self, *args, nested: bool = False) -> Any:
268
271
  if len(args) == 0:
269
272
  return None
270
- # check if args is a single value
271
- elif len(args) == 1:
272
- # get the first args value
273
- value = args[0]
274
-
275
- # if the value is a primitive, store it as is
276
- if isinstance(value, str) or isinstance(value, int) or isinstance(value, float) or isinstance(value, bool):
277
- pass
278
-
279
- # if the value is a symbol, unwrap it
280
- elif isinstance(value, Symbol):
281
- # if not nested, copy the symbol's value, metadata, parent, and children
282
- if not nested:
283
- self._metadata = value.metadata
284
- self._static_context = value.static_context
285
- self._kwargs = value._kwargs
286
- # unwrap the symbol's value
287
- value = value.value
288
-
289
- # if the value is a list, tuple, dict, or set, unwrap all nested symbols
290
- elif isinstance(value, list) or isinstance(value, dict) or \
291
- isinstance(value, set) or isinstance(value, tuple):
292
-
293
- if isinstance(value, list):
294
- value = [self._unwrap_symbols_args(v, nested=True) for v in value]
295
-
296
- elif isinstance(value, dict):
297
- value = {self._unwrap_symbols_args(k, nested=True): self._unwrap_symbols_args(v, nested=True) for k, v in value.items()}
298
-
299
- elif isinstance(value, set):
300
- value = {self._unwrap_symbols_args(v, nested=True) for v in value}
301
-
302
- elif isinstance(value, tuple):
303
- value = tuple([self._unwrap_symbols_args(v, nested=True) for v in value])
273
+ if len(args) == 1:
274
+ return self._unwrap_single_symbol_arg(args[0], nested=nested)
275
+ if len(args) > 1:
276
+ return [self._unwrap_symbols_args(a, nested=True) if isinstance(a, Symbol) else a for a in args]
277
+ return None
304
278
 
279
+ def _unwrap_single_symbol_arg(self, value: Any, *, nested: bool) -> Any:
280
+ if isinstance(value, (str, int, float, bool)):
305
281
  return value
306
-
307
- elif len(args) > 1:
308
- return [self._unwrap_symbols_args(a, nested=True) if isinstance(a, Symbol) else a for a in args]
282
+ if isinstance(value, Symbol):
283
+ if not nested:
284
+ self._metadata = value.metadata
285
+ self._static_context = value.static_context
286
+ self._kwargs = value._kwargs
287
+ return value.value
288
+ if isinstance(value, list):
289
+ return [self._unwrap_symbols_args(v, nested=True) for v in value]
290
+ if isinstance(value, dict):
291
+ return {
292
+ self._unwrap_symbols_args(k, nested=True): self._unwrap_symbols_args(v, nested=True)
293
+ for k, v in value.items()
294
+ }
295
+ if isinstance(value, set):
296
+ return {self._unwrap_symbols_args(v, nested=True) for v in value}
297
+ if isinstance(value, tuple):
298
+ return tuple(self._unwrap_symbols_args(v, nested=True) for v in value)
299
+ return value
309
300
 
310
301
  def _construct_dependency_graph(self, *value):
311
302
  '''
@@ -316,16 +307,16 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
316
307
  '''
317
308
  # for each value
318
309
  for v in value:
319
- if isinstance(v, Symbol) and not v is self:
310
+ if isinstance(v, Symbol) and v is not self:
320
311
  # new instance becomes child of previous instance
321
312
  v._parent = self
322
313
  # add new instance to children of previous instance
323
314
  self._children.append(v)
324
315
 
325
- def __new__(cls, *args,
326
- mixin: Optional[bool] = None,
327
- primitives: Optional[List[Type]] = None,
328
- callables: Optional[List[Tuple[str, Callable]]] = None,
316
+ def __new__(cls, *_args,
317
+ mixin: bool | None = None,
318
+ primitives: list[type] | None = None,
319
+ callables: list[tuple[str, Callable]] | None = None,
329
320
  semantic: bool = False,
330
321
  **kwargs) -> "Symbol":
331
322
  '''
@@ -348,10 +339,11 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
348
339
  if not isinstance(primitives, list):
349
340
  primitives = [primitives]
350
341
  # Initialize instance as a combination of Symbol and the mixin primitive types
342
+ target_cls = cls
351
343
  if use_mixin:
352
344
  # create a new cls type that inherits from Symbol and the mixin primitive types
353
- cls = SymbolMeta(cls.__name__, (cls,) + tuple(primitives), {})
354
- obj = super().__new__(cls)
345
+ target_cls = SymbolMeta(cls.__name__, (cls, *tuple(primitives)), {})
346
+ obj = super().__new__(target_cls)
355
347
  # store to inherit when creating new instances
356
348
  obj._kwargs = {
357
349
  'mixin': use_mixin,
@@ -361,10 +353,9 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
361
353
  **kwargs
362
354
  }
363
355
  # configure standard primitives
364
- if use_mixin and standard_primitives:
356
+ if use_mixin and standard_primitives and semantic:
365
357
  # allow to iterate over iterables for neuro-symbolic values
366
- if semantic:
367
- obj.__semantic__ = True
358
+ obj.__semantic__ = True
368
359
  # If metatype has additional runtime primitives, add them to the instance
369
360
  if Symbol._metadata._primitives is not None:
370
361
  for prim_name in list(Symbol._metadata._primitives.keys()):
@@ -411,7 +402,8 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
411
402
  value = self.value if self.value is not None else None
412
403
  if isinstance(value, Exception):
413
404
  raise value
414
- raise AttributeError(f'<class \'{self.__class__.__name__}\'> or nested value of {str(type(value))} have no attribute \'{name}\'')
405
+ msg = f"<class '{self.__class__.__name__}'> or nested value of {type(value)!s} have no attribute '{name}'"
406
+ raise AttributeError(msg)
415
407
  except AttributeError as ex:
416
408
  # if has attribute and is public function
417
409
  if hasattr(self.value, name) and not name.startswith('_'):
@@ -440,7 +432,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
440
432
  return memoryview(self.embedding)
441
433
 
442
434
  @staticmethod
443
- def symbols(*values) -> List["Symbol"]:
435
+ def symbols(*values) -> list["Symbol"]:
444
436
  '''
445
437
  Create a list of Symbol instances from a list of values.
446
438
 
@@ -458,7 +450,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
458
450
  It returns a tuple that contains:
459
451
  - A callable object that when called produces a new object (e.g., the class of the object)
460
452
  - A tuple of arguments for the callable object
461
- - Optionally, the state which will be passed to the objects `__setstate__` method
453
+ - Optionally, the state which will be passed to the object's `__setstate__` method
462
454
 
463
455
  Returns:
464
456
  tuple: A tuple containing the callable object, the arguments for the callable object, and the state of the object.
@@ -476,7 +468,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
476
468
  # The __reduce__ method returns:
477
469
  # - A callable object that when called produces a new object (e.g., the class of the object)
478
470
  # - A tuple of arguments for the callable object
479
- # - Optionally, the state which will be passed to the objects `__setstate__` method
471
+ # - Optionally, the state which will be passed to the object's `__setstate__` method
480
472
  return (self._reconstruct_class, (base_cls, self._mixin, primitives), state)
481
473
 
482
474
  def __reduce_ex__(self, protocol):
@@ -500,12 +492,11 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
500
492
  # Convert primitive info tuples back to types
501
493
  primitives = [primitive for primitive, name in primitives_info]
502
494
  # Create new cls with UnifiedMeta metaclass
503
- cls = SymbolMeta(base_cls.__name__, (base_cls,) + tuple(primitives), {})
504
- obj = cls()
505
- return obj
495
+ cls = SymbolMeta(base_cls.__name__, (base_cls, *tuple(primitives)), {})
496
+ return cls()
506
497
  return base_cls()
507
498
 
508
- def __getstate__(self) -> Dict[str, Any]:
499
+ def __getstate__(self) -> dict[str, Any]:
509
500
  '''
510
501
  Get the state of the symbol for serialization.
511
502
 
@@ -532,7 +523,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
532
523
  self._parent = None
533
524
  self._children = []
534
525
 
535
- def json(self) -> Dict[str, Any]:
526
+ def json(self) -> dict[str, Any]:
536
527
  '''
537
528
  Get the json-serializable dictionary representation of the Symbol instance.
538
529
 
@@ -568,8 +559,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
568
559
  return value
569
560
  # inherit kwargs for new symbol instance
570
561
  kwargs = {**self._kwargs, **kwargs}
571
- sym = type_(value, **kwargs)
572
- return sym
562
+ return type_(value, **kwargs)
573
563
 
574
564
  def _to_type(self, value: Any, **kwargs) -> "Symbol":
575
565
  '''
@@ -586,8 +576,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
586
576
  return value
587
577
  # inherit kwargs for new symbol instance
588
578
  kwargs = {**self._kwargs, **kwargs}
589
- sym = type_(value, **kwargs)
590
- return sym
579
+ return type_(value, **kwargs)
591
580
 
592
581
  @property
593
582
  def _symbol_type(self) -> "Symbol":
@@ -609,7 +598,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
609
598
  return str(self.value).__hash__()
610
599
 
611
600
  @property
612
- def metadata(self) -> Dict[str, Any]:
601
+ def metadata(self) -> dict[str, Any]:
613
602
  '''
614
603
  Get the metadata associated with the symbol.
615
604
 
@@ -692,7 +681,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
692
681
  return root
693
682
 
694
683
  @property
695
- def nodes(self) -> List["Symbol"]:
684
+ def nodes(self) -> list["Symbol"]:
696
685
  '''
697
686
  Get all nodes descending recursively from the symbol.
698
687
 
@@ -709,7 +698,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
709
698
  return nodes
710
699
 
711
700
  @property
712
- def edges(self) -> List[tuple]:
701
+ def edges(self) -> list[tuple]:
713
702
  '''
714
703
  Get all edges descending recursively from the symbol.
715
704
 
@@ -726,7 +715,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
726
715
  return edges
727
716
 
728
717
  @property
729
- def graph(self) -> (List["Symbol"], List[tuple]):
718
+ def graph(self) -> (list["Symbol"], list[tuple]):
730
719
  '''
731
720
  Get the graph representation of the symbol.
732
721
 
@@ -736,7 +725,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
736
725
  return self.nodes, self.edges
737
726
 
738
727
  @property
739
- def linker(self) -> List["Symbol"]:
728
+ def linker(self) -> list["Symbol"]:
740
729
  '''
741
730
  Returns the link object metadata by descending recursively from the root of the symbol to the root_link object.
742
731
 
@@ -756,7 +745,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
756
745
  return self._parent
757
746
 
758
747
  @property
759
- def children(self) -> List["Symbol"]:
748
+ def children(self) -> list["Symbol"]:
760
749
  '''
761
750
  Get the children of the symbol.
762
751
 
@@ -765,7 +754,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
765
754
  '''
766
755
  return self._children
767
756
 
768
- def _root_link(self, sym: Any, **kwargs) -> Any:
757
+ def _root_link(self, sym: Any, **_kwargs) -> Any:
769
758
  '''
770
759
  Call the forward method and assign the result to the graph value attribute.
771
760
 
@@ -777,7 +766,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
777
766
  Any: The result of the forward method.
778
767
  '''
779
768
  # transport results to the root node for global access
780
- if not self is self.root and not self.metadata.detach:
769
+ if self is not self.root and not self.metadata.detach:
781
770
  ref = self.root.metadata
782
771
  if ref.root_link is None:
783
772
  ref.root_link = Linker()
@@ -788,12 +777,12 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
788
777
  prev = list(ref.root_link.results.values())[-1] # get previous result
789
778
  # create new symbol to avoid circular references
790
779
  res_ = Symbol(sym)
791
- if prev is not None and not prev is res_.root:
780
+ if prev is not None and prev is not res_.root:
792
781
  prev.children.append(res_.root)
793
782
  res_.root._parent = prev
794
783
  ref.root_link.results[self.__repr__()] = res_
795
784
 
796
- def adapt(self, context: str, types: List[Type] = []) -> None:
785
+ def adapt(self, context: str, types: list[type] | None = None) -> None:
797
786
  '''
798
787
  Update the dynamic context with a given runtime context.
799
788
 
@@ -802,34 +791,38 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
802
791
  type (Type): The type used to update the dynamic context
803
792
 
804
793
  '''
794
+ if types is None:
795
+ types = []
805
796
  if not isinstance(types, list):
806
797
  types = [types]
807
798
  if len(types) == 0:
808
799
  types = [type(self)]
809
800
 
810
801
  for type_ in types:
811
- type_ = str(type_)
812
- if type_ not in Symbol._dynamic_context:
813
- Symbol._dynamic_context[type_] = []
802
+ type_key = str(type_)
803
+ if type_key not in Symbol._dynamic_context:
804
+ Symbol._dynamic_context[type_key] = []
814
805
 
815
- Symbol._dynamic_context[type_].append(str(context))
806
+ Symbol._dynamic_context[type_key].append(str(context))
816
807
 
817
- def clear(self, types: List[Type] = []) -> None:
808
+ def clear(self, types: list[type] | None = None) -> None:
818
809
  '''
819
810
  Clear the dynamic context associated with this symbol type.
820
811
  '''
812
+ if types is None:
813
+ types = []
821
814
  if not isinstance(types, list):
822
815
  types = [types]
823
816
  if len(types) == 0:
824
817
  types = [type(self)]
825
818
 
826
819
  for type_ in types:
827
- type_ = str(type_)
828
- if type_ not in Symbol._dynamic_context:
829
- Symbol._dynamic_context[type_] = []
820
+ type_key = str(type_)
821
+ if type_key not in Symbol._dynamic_context:
822
+ Symbol._dynamic_context[type_key] = []
830
823
  return
831
824
 
832
- Symbol._dynamic_context[type_].clear()
825
+ Symbol._dynamic_context[type_key].clear()
833
826
 
834
827
  def __len__(self) -> int:
835
828
  '''
@@ -859,14 +852,13 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
859
852
  '''
860
853
  if self.value is None:
861
854
  return ''
862
- elif isinstance(self.value, list) or isinstance(self.value, np.ndarray) or isinstance(self.value, tuple):
855
+ if isinstance(self.value, (list, np.ndarray, tuple)):
863
856
  return str([str(v) for v in self.value])
864
- elif isinstance(self.value, dict):
857
+ if isinstance(self.value, dict):
865
858
  return str({k: str(v) for k, v in self.value.items()})
866
- elif isinstance(self.value, set):
859
+ if isinstance(self.value, set):
867
860
  return str({str(v) for v in self.value})
868
- else:
869
- return str(self.value)
861
+ return str(self.value)
870
862
 
871
863
  def __repr__(self, simplified: bool = False) -> str:
872
864
  '''
@@ -901,7 +893,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
901
893
  Returns:
902
894
  Iterator: An iterator for the Symbol's value.
903
895
  '''
904
- if isinstance(self.value, list) or isinstance(self.value, tuple) or isinstance(self.value, np.ndarray):
896
+ if isinstance(self.value, (list, tuple, np.ndarray)):
905
897
  return iter(self.value)
906
898
 
907
899
  return self.list('item').value.__iter__()
@@ -960,8 +952,8 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
960
952
  # TODO: Workaround for Python bug to enable runtime assignment of lambda function to new Symbol objects.
961
953
  # Currently creating multiple lambda functions within class __new__ definition only links last lambda function to all new Symbol attribute assignments.
962
954
  # Need to contact Python developers to fix this bug.
963
- class Call(object):
964
- def __new__(self, name, callable: Callable) -> Any:
955
+ class Call:
956
+ def __new__(cls, name, callable: Callable) -> Any:
965
957
  '''
966
958
  Prepare a callable for use in a Symbol instance.
967
959
 
@@ -976,8 +968,8 @@ class Call(object):
976
968
  return (name, _func)
977
969
 
978
970
 
979
- class GlobalSymbolPrimitive(object):
980
- def __new__(self, name, callable: Callable) -> Any:
971
+ class GlobalSymbolPrimitive:
972
+ def __new__(cls, name, callable: Callable) -> Any:
981
973
  '''
982
974
  Prepare a callable for use in a Symbol instance.
983
975
 
@@ -1060,7 +1052,7 @@ class Expression(Symbol):
1060
1052
  return json.dumps(self, cls=ExpressionEncoder)
1061
1053
 
1062
1054
  @property
1063
- def sym_return_type(self) -> Type:
1055
+ def sym_return_type(self) -> type:
1064
1056
  '''
1065
1057
  Returns the casting type of this expression.
1066
1058
 
@@ -1070,7 +1062,7 @@ class Expression(Symbol):
1070
1062
  return self._sym_return_type
1071
1063
 
1072
1064
  @sym_return_type.setter
1073
- def sym_return_type(self, type: Type) -> None:
1065
+ def sym_return_type(self, type: type) -> None:
1074
1066
  '''
1075
1067
  Sets the casting type of this expression.
1076
1068
 
@@ -1090,10 +1082,10 @@ class Expression(Symbol):
1090
1082
  Returns:
1091
1083
  Symbol: The evaluated result of the implemented forward method.
1092
1084
  '''
1093
- raise NotImplementedError()
1085
+ raise NotImplementedError
1094
1086
 
1095
1087
  @staticmethod
1096
- def command(engines: List[str] = ['all'], **kwargs) -> 'Symbol':
1088
+ def command(engines: list[str] | None = None, **kwargs) -> 'Symbol':
1097
1089
  '''
1098
1090
  Execute command(s) on engines.
1099
1091
 
@@ -1104,13 +1096,16 @@ class Expression(Symbol):
1104
1096
  Returns:
1105
1097
  Symbol: An Expression object representing the command execution result.
1106
1098
  '''
1099
+ if engines is None:
1100
+ engines = ['all']
1101
+
1107
1102
  @core.command(engines=engines, **kwargs)
1108
1103
  def _func(_):
1109
1104
  pass
1110
1105
  return Expression(_func(Expression()))
1111
1106
 
1112
1107
  @staticmethod
1113
- def register(engines: Dict[str, Any], **kwargs) -> 'Symbol':
1108
+ def register(engines: dict[str, Any], **kwargs) -> 'Symbol':
1114
1109
  '''
1115
1110
  Configure multiple engines.
1116
1111
 
@@ -1154,7 +1149,7 @@ class Expression(Symbol):
1154
1149
 
1155
1150
 
1156
1151
  class Result(Expression):
1157
- def __init__(self, value = None, *args, **kwargs):
1152
+ def __init__(self, value = None, *_args, **kwargs):
1158
1153
  '''
1159
1154
  Create a Result object that stores the results operations, including the raw result, value and metadata, if any.
1160
1155
 
@@ -1169,7 +1164,7 @@ class Result(Expression):
1169
1164
  try:
1170
1165
  # try to make the values easily accessible
1171
1166
  self.raw = Box(value)
1172
- except:
1167
+ except Exception:
1173
1168
  # otherwise, store the unprocessed view
1174
1169
  self.raw = value
1175
1170