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
@@ -1,4 +1,3 @@
1
- from typing import List
2
1
 
3
2
  from ... import core
4
3
  from ...symbol import Expression
@@ -9,7 +8,7 @@ class blip_2(Expression):
9
8
  super().__init__(*args, **kwargs)
10
9
  self.name = self.__class__.__name__
11
10
 
12
- def __call__(self, image: str = None, query: str = None, **kwargs) -> "blip_2":
11
+ def __call__(self, image: str | None = None, query: str | None = None, **kwargs) -> "blip_2":
13
12
  @core.caption(image=image, prompt=query, **kwargs)
14
13
  def _func(_) -> str:
15
14
  pass
@@ -1,4 +1,3 @@
1
- from typing import List, Union
2
1
 
3
2
  import numpy as np
4
3
 
@@ -11,7 +10,7 @@ class clip(Expression):
11
10
  super().__init__(*args, **kwargs)
12
11
  self.name = self.__class__.__name__
13
12
 
14
- def __call__(self, image: str | bytes = None, text: List[str] = None, **kwargs) -> "clip":
13
+ def __call__(self, image: str | bytes | None = None, text: list[str] | None = None, **kwargs) -> "clip":
15
14
  @core.text_vision(image=image, text=text, **kwargs)
16
15
  def _func(_) -> np.ndarray:
17
16
  pass
@@ -1,5 +1,6 @@
1
1
  from ... import core
2
2
  from ...symbol import Expression
3
+ from ...utils import UserMessage
3
4
 
4
5
 
5
6
  class console(Expression):
@@ -8,7 +9,12 @@ class console(Expression):
8
9
  self.name = self.__class__.__name__
9
10
 
10
11
  def __call__(self, *args, **kwargs) -> "console":
11
- kwargs['handler'] = lambda x: print(*x['args'])
12
+ def _handler(payload):
13
+ args_ = payload.get('args', ())
14
+ message = ' '.join(str(arg) for arg in args_)
15
+ UserMessage(message)
16
+
17
+ kwargs['handler'] = _handler
12
18
  @core.output(**kwargs)
13
19
  def _func(_, *args):
14
20
  pass
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression, Symbol
3
2
  from ...backend.engines.drawing.engine_gpt_image import GPTImageResult
3
+ from ...symbol import Expression, Symbol
4
4
 
5
5
 
6
6
  class dall_e(Expression):
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression, Symbol
3
2
  from ...backend.engines.drawing.engine_bfl import FluxResult
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class flux(Expression):
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
2
  from ...backend.engines.drawing.engine_gpt_image import GPTImageResult
3
- from ...symbol import Expression, Symbol
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class gpt_image(Expression):
@@ -2,7 +2,7 @@ from ... import core
2
2
  from ...symbol import Expression
3
3
 
4
4
 
5
- class input(Expression):
5
+ class input(Expression): # noqa
6
6
  def __init__(self, *args, **kwargs):
7
7
  super().__init__(*args, **kwargs)
8
8
  self.name = self.__class__.__name__
@@ -1,4 +1,3 @@
1
- from typing import List
2
1
 
3
2
  from ... import core
4
3
  from ...symbol import Expression
@@ -1,8 +1,6 @@
1
- from ... import core
2
- from ...backend.engines.index.engine_vectordb import (VectorDBIndexEngine,
3
- VectorDBResult)
1
+ from ...backend.engines.index.engine_vectordb import VectorDBIndexEngine, VectorDBResult
4
2
  from ...symbol import Expression
5
- from ...utils import CustomUserWarning
3
+ from ...utils import UserMessage
6
4
 
7
5
 
8
6
  class naive_vectordb(Expression):
@@ -26,10 +24,11 @@ class naive_vectordb(Expression):
26
24
  if isinstance(query, list):
27
25
  for q in query:
28
26
  self.add(doc=[q], index_name=index, **kwargs)
29
- return
27
+ return None
30
28
  self.add(doc=[query], index_name=index, **kwargs)
31
- return
29
+ return None
32
30
  if operation == "config":
33
31
  self.config(path=query, index_name=index, storage_file=storage_file, **kwargs)
34
- return
35
- CustomUserWarning(f"Operation not supported: {operation}", raise_with=NotImplementedError)
32
+ return None
33
+ UserMessage(f"Operation not supported: {operation}", raise_with=NotImplementedError)
34
+ return None
@@ -10,7 +10,7 @@ class naive_webscraping(Expression):
10
10
 
11
11
  def __call__(self, url: str, **kwargs) -> RequestsResult:
12
12
  @core.scrape(url=url, **kwargs)
13
- def _func(_, *args, **inner_kwargs) -> RequestsResult:
13
+ def _func(_, *_args, **_inner_kwargs) -> RequestsResult:
14
14
  # The fallback path may inject debugging kwargs like `error`/`stack_trace`;
15
15
  # accept and ignore them so EngineRepository can surface structured failures.
16
16
  return None
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression
3
2
  from ...backend.engines.ocr.engine_apilayer import ApiLayerResult
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class ocr(Expression):
@@ -1,6 +1,6 @@
1
- from ... import core
1
+ from ...backend.engines.index.engine_pinecone import PineconeIndexEngine, PineconeResult
2
2
  from ...symbol import Expression
3
- from ...backend.engines.index.engine_pinecone import PineconeResult, PineconeIndexEngine
3
+ from ...utils import UserMessage
4
4
 
5
5
 
6
6
  class pinecone(Expression):
@@ -14,8 +14,9 @@ class pinecone(Expression):
14
14
  index = self.index_name if index_name is None else index_name
15
15
  if operation == "search":
16
16
  return self.get(query=stmt.embedding, index_name=index, ori_query=stmt.value, **kwargs)
17
- elif operation == "add":
17
+ if operation == "add":
18
18
  return self.add(doc=stmt.zip(), index_name=index, **kwargs)
19
- elif operation == "config":
19
+ if operation == "config":
20
20
  return self.index(path=stmt.value, index_name=index, **kwargs)
21
- raise NotImplementedError("Operation not supported")
21
+ UserMessage("Operation not supported", raise_with=NotImplementedError)
22
+ return None
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression, Symbol
3
2
  from ...backend.engines.search.engine_serpapi import SearchResult
3
+ from ...symbol import Expression, Symbol
4
4
 
5
5
 
6
6
  class serpapi(Expression):
@@ -1,7 +1,6 @@
1
- from typing import List
2
1
 
3
- from ...symbol import Expression
4
2
  from ...shellsv import process_command
3
+ from ...symbol import Expression
5
4
 
6
5
 
7
6
  class terminal(Expression):
@@ -9,5 +8,5 @@ class terminal(Expression):
9
8
  super().__init__(*args, **kwargs)
10
9
  self.name = self.__class__.__name__
11
10
 
12
- def __call__(self, command: str = None, **kwargs) -> "terminal":
11
+ def __call__(self, command: str | None = None, **kwargs) -> "terminal":
13
12
  return self.sym_return_type(process_command(command, **kwargs))
@@ -1,5 +1,5 @@
1
1
  from ... import core
2
- from ...symbol import Expression, Symbol, Result
2
+ from ...symbol import Expression, Result, Symbol
3
3
 
4
4
 
5
5
  class tts(Expression):
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression
3
2
  from ...backend.engines.speech_to_text.engine_local_whisper import WhisperResult
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class whisper(Expression):
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression
3
2
  from ...backend.engines.symbolic.engine_wolframalpha import WolframResult
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class wolframalpha(Expression):
@@ -1 +1,11 @@
1
- from .similarity import *
1
+ from . import similarity as _similarity
2
+
3
+ __all__ = getattr(_similarity, "__all__", None) # noqa
4
+ if __all__ is None:
5
+ __all__ = [name for name in dir(_similarity) if not name.startswith("_")]
6
+
7
+ for _name in __all__:
8
+ globals()[_name] = getattr(_similarity, _name)
9
+
10
+ del _name
11
+ del _similarity
@@ -1,3 +1,6 @@
1
+ '''
2
+ @TODO: This must go away. As soon as we have Qdrant, everything related to vectordb must be cleaned up.
3
+ '''
1
4
  import random
2
5
 
3
6
  import numpy as np
@@ -11,8 +14,7 @@ def get_norm_vector(vector):
11
14
  """
12
15
  if len(vector.shape) == 1:
13
16
  return vector / np.linalg.norm(vector)
14
- else:
15
- return vector / np.linalg.norm(vector, axis=1)[:, np.newaxis]
17
+ return vector / np.linalg.norm(vector, axis=1)[:, np.newaxis]
16
18
 
17
19
 
18
20
  def dot_product(vectors, query_vector):
@@ -22,8 +24,7 @@ def dot_product(vectors, query_vector):
22
24
  :param query_vector: vector
23
25
  :return: dot product between the vector and the matrix of vectors
24
26
  """
25
- similarities = np.dot(vectors, query_vector.T)
26
- return similarities
27
+ return np.dot(vectors, query_vector.T)
27
28
 
28
29
 
29
30
  def cosine_similarity(vectors, query_vector):
@@ -35,8 +36,7 @@ def cosine_similarity(vectors, query_vector):
35
36
  """
36
37
  norm_vectors = get_norm_vector(vectors)
37
38
  norm_query_vector = get_norm_vector(query_vector)
38
- similarities = np.dot(norm_vectors, norm_query_vector.T)
39
- return similarities
39
+ return np.dot(norm_vectors, norm_query_vector.T)
40
40
 
41
41
 
42
42
  def euclidean_metric(vectors, query_vector, get_similarity_score=True):
@@ -49,7 +49,7 @@ def euclidean_metric(vectors, query_vector, get_similarity_score=True):
49
49
  """
50
50
  similarities = np.linalg.norm(vectors - query_vector, axis=1)
51
51
  if get_similarity_score:
52
- similarities = 1 / (1 + similarities)
52
+ return 1 / (1 + similarities)
53
53
  return similarities
54
54
 
55
55
 
@@ -64,8 +64,7 @@ def derridaean_similarity(vectors, query_vector):
64
64
  return value + random.uniform(-0.2, 0.2)
65
65
 
66
66
  similarities = cosine_similarity(vectors, query_vector)
67
- derrida_similarities = np.vectorize(random_change)(similarities)
68
- return derrida_similarities
67
+ return np.vectorize(random_change)(similarities)
69
68
 
70
69
 
71
70
  def adams_similarity(vectors, query_vector):
@@ -75,12 +74,11 @@ def adams_similarity(vectors, query_vector):
75
74
  :param query_vector: vector
76
75
  :return: adams similarity between the vector and the matrix of vectors
77
76
  """
78
- def adams_change(value):
77
+ def adams_change(_value):
79
78
  return 0.42
80
79
 
81
80
  similarities = cosine_similarity(vectors, query_vector)
82
- adams_similarities = np.vectorize(adams_change)(similarities)
83
- return adams_similarities
81
+ return np.vectorize(adams_change)(similarities)
84
82
 
85
83
 
86
84
  def ranking_algorithm_sort(vectors, query_vector, top_k=5, metric=cosine_similarity):
@@ -94,4 +92,4 @@ def ranking_algorithm_sort(vectors, query_vector, top_k=5, metric=cosine_similar
94
92
  """
95
93
  similarities = metric(vectors, query_vector)
96
94
  top_indices = np.argsort(similarities, axis=0)[-top_k:][::-1]
97
- return top_indices.flatten(), similarities[top_indices].flatten()
95
+ return top_indices.flatten(), similarities[top_indices].flatten()
@@ -1,10 +1,9 @@
1
1
  import platform
2
2
  import subprocess
3
3
 
4
- from typing import Dict, List
5
-
6
4
  from ..post_processors import CodeExtractPostProcessor
7
5
  from ..symbol import Expression, Symbol
6
+ from ..utils import UserMessage
8
7
 
9
8
  Context = """[DESCRIPTION]:
10
9
  Adapt the user query to an OS patform command (commands must be executable in terminal, shell, bash or powershell)!
@@ -62,33 +61,35 @@ Write an executable command that starts a process according to the user query, p
62
61
 
63
62
 
64
63
  class OSCommand(Expression):
65
- def __init__(self, programs: List[str],
66
- metadata: Dict[str, str] = {},
64
+ def __init__(self, programs: list[str],
65
+ metadata: dict[str, str] | None = None,
67
66
  verbose: bool = False,
68
67
  os_platform: str = 'auto',
69
68
  **kwargs):
69
+ if metadata is None:
70
+ metadata = {}
70
71
  super().__init__(**kwargs)
71
72
  self.verbose: bool = verbose
72
73
  self.os_platform: str = os_platform
73
- self.programs: List[str] = programs
74
- self.meta: Dict[str, str] = metadata
74
+ self.programs: list[str] = programs
75
+ self.meta: dict[str, str] = metadata
75
76
 
76
77
  if self.os_platform == 'auto':
77
78
  self.os_platform = platform.platform()
78
79
  if len(programs) == 0:
79
- raise Exception('No programs specified!')
80
+ UserMessage('No programs specified!', raise_with=Exception)
80
81
 
81
- def execute_os_command(self, *args, **kwargs):
82
+ def execute_os_command(self, *args, **_kwargs):
82
83
  command = args[0]
83
- print(f'Executing {self.os_platform} command: {command}')
84
+ UserMessage(f'Executing {self.os_platform} command: {command}')
84
85
  if 'linux' in self.os_platform.lower():
85
- return [subprocess.run(["bash", "-c", str(command)])]
86
- elif 'windows' in self.os_platform.lower():
87
- return [subprocess.run(["powershell", "-Command", str(command)])]
88
- elif 'mac' in self.os_platform.lower():
89
- return [subprocess.run(["bash", "-c", str(command)])]
90
- else:
91
- raise Exception('Unsupported platform!')
86
+ return [subprocess.run(["bash", "-c", str(command)], check=False)]
87
+ if 'windows' in self.os_platform.lower():
88
+ return [subprocess.run(["powershell", "-Command", str(command)], check=False)]
89
+ if 'mac' in self.os_platform.lower():
90
+ return [subprocess.run(["bash", "-c", str(command)], check=False)]
91
+ UserMessage('Unsupported platform!', raise_with=Exception)
92
+ return []
92
93
 
93
94
  def forward(self, sym: Symbol, **kwargs) -> Expression:
94
95
  sym = self._to_symbol(sym)
@@ -1,3 +1,29 @@
1
- from .symdev import *
2
- from .sympkg import *
3
- from .symrun import *
1
+ from . import symdev as _symdev
2
+ from . import sympkg as _sympkg
3
+ from . import symrun as _symrun
4
+
5
+ __all__ = []
6
+ _seen_names = set()
7
+
8
+
9
+ def _export_module(module, seen_names: set[str] = _seen_names) -> None:
10
+ public_names = getattr(module, "__all__", None)
11
+ if public_names is None:
12
+ public_names = [name for name in dir(module) if not name.startswith("_")]
13
+ for name in public_names:
14
+ globals()[name] = getattr(module, name)
15
+ if name not in seen_names:
16
+ __all__.append(name)
17
+ seen_names.add(name)
18
+
19
+
20
+ for _module in (_symdev, _sympkg, _symrun):
21
+ _export_module(_module)
22
+
23
+
24
+ del _export_module
25
+ del _module
26
+ del _seen_names
27
+ del _symdev
28
+ del _sympkg
29
+ del _symrun
@@ -9,12 +9,12 @@ from loguru import logger
9
9
  from ... import config_manager
10
10
 
11
11
 
12
- class PackageInitializer():
12
+ class PackageInitializer:
13
13
  def __init__(self):
14
14
  self.package_dir = Path(config_manager.config_dir) / 'packages'
15
15
 
16
- if not os.path.exists(self.package_dir):
17
- os.makedirs(self.package_dir)
16
+ if not self.package_dir.exists():
17
+ self.package_dir.mkdir(parents=True)
18
18
 
19
19
  os.chdir(self.package_dir)
20
20
 
@@ -30,7 +30,7 @@ class PackageInitializer():
30
30
  parser.add_argument('command', help='Subcommand to run')
31
31
  args = parser.parse_args(sys.argv[1:2])
32
32
  if len(args.command) > 1 and not hasattr(self, args.command):
33
- setattr(args, 'package', args.command)
33
+ args.package = args.command
34
34
  self.c(args)
35
35
  elif len(args.command) == 1 and not hasattr(self, args.command):
36
36
  logger.error('Unrecognized command')
@@ -51,27 +51,30 @@ class PackageInitializer():
51
51
  try:
52
52
  username = vals[0]
53
53
  package_name = vals[1]
54
- except:
54
+ except IndexError:
55
55
  logger.error('Invalid package name: {git_username}/{package_name}')
56
56
  parser.print_help()
57
57
  exit(1)
58
58
 
59
- package_path = os.path.join(self.package_dir, username, package_name)
60
- if os.path.exists(package_path):
59
+ package_path = self.package_dir / username / package_name
60
+ if package_path.exists():
61
61
  logger.info('Package already exists')
62
62
  exit(1)
63
63
 
64
64
  logger.info('Creating package...')
65
- os.makedirs(package_path)
66
- os.makedirs(os.path.join(package_path, 'src'))
65
+ package_path.mkdir(parents=True)
66
+ src_path = package_path / 'src'
67
+ src_path.mkdir(parents=True)
67
68
 
68
- with open(os.path.join(package_path, '.gitignore'), 'w'): pass
69
- with open(os.path.join(package_path, 'LICENSE'), 'w') as f:
69
+ with (package_path / '.gitignore').open('w'):
70
+ pass
71
+ with (package_path / 'LICENSE').open('w') as f:
70
72
  f.write('MIT License')
71
- with open(os.path.join(package_path, 'README.md'), 'w') as f:
73
+ with (package_path / 'README.md').open('w') as f:
72
74
  f.write('# ' + package_name + '\n## <Project Description>')
73
- with open(os.path.join(package_path, 'requirements.txt'), 'w'): pass
74
- with open(os.path.join(package_path, 'package.json'), 'w') as f:
75
+ with (package_path / 'requirements.txt').open('w'):
76
+ pass
77
+ with (package_path / 'package.json').open('w') as f:
75
78
  json.dump({
76
79
  'version': '0.0.1',
77
80
  'name': username+'/'+package_name,
@@ -80,7 +83,7 @@ class PackageInitializer():
80
83
  'run': {'module': 'src/func', 'type': 'MyExpression'},
81
84
  'dependencies': []
82
85
  }, f, indent=4)
83
- with open(os.path.join(package_path, 'src', 'func.py'), 'w') as f:
86
+ with (src_path / 'func.py').open('w') as f:
84
87
  f.write("""from symai import Expression, Function
85
88
 
86
89
 
@@ -99,7 +102,7 @@ class MyExpression(Expression):
99
102
  data = self._to_symbol(data)
100
103
  self.fn.format(template=template)
101
104
  return self.fn(data, *args, **kwargs)""")
102
- logger.success('Package created successfully at: ' + package_path)
105
+ logger.success('Package created successfully at: ' + str(package_path))
103
106
 
104
107
 
105
108
  def run() -> None:
@@ -8,14 +8,15 @@ from loguru import logger
8
8
 
9
9
  from ... import config_manager
10
10
  from ...imports import Import
11
+ from ...utils import UserMessage
11
12
 
12
13
 
13
- class PackageHandler():
14
+ class PackageHandler:
14
15
  def __init__(self):
15
16
  self.package_dir = Path(config_manager.config_dir) / 'packages'
16
17
 
17
- if not os.path.exists(self.package_dir):
18
- os.makedirs(self.package_dir)
18
+ if not self.package_dir.exists():
19
+ self.package_dir.mkdir(parents=True)
19
20
 
20
21
  os.chdir(self.package_dir)
21
22
 
@@ -36,15 +37,17 @@ class PackageHandler():
36
37
 
37
38
  parser.add_argument('command', help='Subcommand to run')
38
39
  args = parser.parse_args(sys.argv[1:2])
39
- if len(args.command) > 1 and not hasattr(self, args.command):
40
- setattr(args, 'package', args.command)
40
+ command_aliases = {'l': 'list_packages'}
41
+ command = command_aliases.get(args.command, args.command)
42
+ if len(command) > 1 and not hasattr(self, command):
43
+ args.package = args.command
41
44
  self.i(args)
42
- elif len(args.command) == 1 and not hasattr(self, args.command):
45
+ elif len(command) == 1 and not hasattr(self, command):
43
46
  logger.error('Unrecognized command')
44
47
  parser.print_help()
45
48
  exit(1)
46
49
  else:
47
- getattr(self, args.command)()
50
+ getattr(self, command)()
48
51
 
49
52
  def i(self, args = None):
50
53
  parser = argparse.ArgumentParser(
@@ -69,8 +72,8 @@ class PackageHandler():
69
72
  args = parser.parse_args(sys.argv[2:])
70
73
  Import.remove(args.package)
71
74
 
72
- def l(self):
73
- pprint.pprint(Import.list_installed())
75
+ def list_packages(self):
76
+ UserMessage(pprint.pformat(Import.list_installed()))
74
77
 
75
78
  def u(self):
76
79
  parser = argparse.ArgumentParser(
@@ -3,7 +3,6 @@ import json
3
3
  import os
4
4
  import sys
5
5
  from pathlib import Path
6
- from typing import Optional
7
6
 
8
7
  from loguru import logger
9
8
 
@@ -13,13 +12,13 @@ from ...misc.console import ConsoleStyle
13
12
  from ...misc.loader import Loader
14
13
 
15
14
 
16
- class PackageRunner():
15
+ class PackageRunner:
17
16
  def __init__(self):
18
17
  self.package_dir = Path(config_manager.config_dir) / 'packages'
19
18
  self.aliases_file = self.package_dir / 'aliases.json'
20
19
 
21
- if not os.path.exists(self.package_dir):
22
- os.makedirs(self.package_dir)
20
+ if not self.package_dir.exists():
21
+ self.package_dir.mkdir(parents=True)
23
22
 
24
23
  os.chdir(self.package_dir)
25
24
 
@@ -38,8 +37,10 @@ class PackageRunner():
38
37
 
39
38
  parser.add_argument('command', help='Subcommand to run')
40
39
  args = parser.parse_args(sys.argv[1:2])
41
- getattr(self, args.command)()
42
- except:
40
+ command_aliases = {'l': 'list_aliases'}
41
+ command = command_aliases.get(args.command, args.command)
42
+ getattr(self, command)()
43
+ except Exception:
43
44
  if len(sys.argv) > 1:
44
45
  self.run_alias()
45
46
  else:
@@ -47,17 +48,17 @@ class PackageRunner():
47
48
  exit(1)
48
49
 
49
50
  def load_aliases(self):
50
- if not os.path.exists(self.aliases_file):
51
+ if not self.aliases_file.exists():
51
52
  return {}
52
53
 
53
- with open(self.aliases_file, 'r') as f:
54
+ with self.aliases_file.open() as f:
54
55
  return json.load(f)
55
56
 
56
57
  def save_aliases(self, aliases):
57
- with open(self.aliases_file, 'w') as f:
58
+ with self.aliases_file.open('w') as f:
58
59
  json.dump(aliases, f)
59
60
 
60
- def console(self, header: str, output: Optional[object] = None):
61
+ def console(self, header: str, output: object | None = None):
61
62
  with ConsoleStyle('success'):
62
63
  logger.success(header)
63
64
  if output is not None:
@@ -83,9 +84,9 @@ class PackageRunner():
83
84
 
84
85
  if package is None:
85
86
  with ConsoleStyle('error'):
86
- logger.error("Alias run of `{}` not found. Please check your command {}".format(args.alias, args))
87
+ logger.error(f"Alias run of `{args.alias}` not found. Please check your command {args}")
87
88
  parser.print_help()
88
- return
89
+ return None
89
90
 
90
91
  arg_values = [arg for arg in args.params if '=' not in arg]
91
92
  kwargs = {arg.split('=')[0]: arg.split('=')[1] for arg in args.params if '=' in arg}
@@ -96,7 +97,8 @@ class PackageRunner():
96
97
  kwargs['submodules'] = True
97
98
 
98
99
  # Check if package is a local path
99
- if os.path.exists(package) and os.path.isdir(package):
100
+ package_path = Path(package)
101
+ if package_path.exists() and package_path.is_dir():
100
102
  # Local path - pass directly
101
103
  expr = Import(package, **kwargs)
102
104
  else:
@@ -104,9 +106,9 @@ class PackageRunner():
104
106
  expr = Import(package, **kwargs)
105
107
  except Exception as e:
106
108
  with ConsoleStyle('error'):
107
- logger.error("Error: {} in package `{}`.\nPlease check your command {} or if package is available.".format(str(e), package, args))
109
+ logger.error(f"Error: {e!s} in package `{package}`.\nPlease check your command {args} or if package is available.")
108
110
  parser.print_help()
109
- return
111
+ return None
110
112
 
111
113
  if '--disable-pbar' not in arg_values:
112
114
  with Loader(desc="Inference ...", end=""):
@@ -117,7 +119,7 @@ class PackageRunner():
117
119
  if result is not None:
118
120
  self.console(result)
119
121
  else:
120
- self.console("Execution of {} => {} completed successfully.".format(args.alias, package))
122
+ self.console(f"Execution of {args.alias} => {package} completed successfully.")
121
123
 
122
124
  return result
123
125
 
@@ -133,9 +135,9 @@ class PackageRunner():
133
135
  aliases = self.load_aliases()
134
136
  aliases[args.alias] = args.package
135
137
  self.save_aliases(aliases)
136
- self.console("Alias {} => {} created successfully.".format(args.alias, args.package))
138
+ self.console(f"Alias {args.alias} => {args.package} created successfully.")
137
139
 
138
- def l(self):
140
+ def list_aliases(self):
139
141
  aliases = self.load_aliases()
140
142
  # format the aliases output as a table of key value pairs
141
143
  self.console("Aliases:\n------------------")
@@ -155,7 +157,7 @@ class PackageRunner():
155
157
  if args.alias in aliases:
156
158
  del aliases[args.alias]
157
159
  self.save_aliases(aliases)
158
- self.console("Alias {} removed successfully.".format(args.alias))
160
+ self.console(f"Alias {args.alias} removed successfully.")
159
161
 
160
162
 
161
163
  def run() -> None: