symbolicai 0.21.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 +269 -173
- symai/backend/base.py +123 -110
- symai/backend/engines/drawing/engine_bfl.py +45 -44
- symai/backend/engines/drawing/engine_gpt_image.py +112 -97
- symai/backend/engines/embedding/engine_llama_cpp.py +63 -52
- symai/backend/engines/embedding/engine_openai.py +25 -21
- symai/backend/engines/execute/engine_python.py +19 -18
- symai/backend/engines/files/engine_io.py +104 -95
- symai/backend/engines/imagecaptioning/engine_blip2.py +28 -24
- symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +102 -79
- symai/backend/engines/index/engine_pinecone.py +124 -97
- symai/backend/engines/index/engine_qdrant.py +1011 -0
- symai/backend/engines/index/engine_vectordb.py +84 -56
- symai/backend/engines/lean/engine_lean4.py +96 -52
- symai/backend/engines/neurosymbolic/__init__.py +41 -13
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +330 -248
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +329 -264
- symai/backend/engines/neurosymbolic/engine_cerebras.py +328 -0
- symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +118 -88
- symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +344 -299
- symai/backend/engines/neurosymbolic/engine_groq.py +173 -115
- symai/backend/engines/neurosymbolic/engine_huggingface.py +114 -84
- symai/backend/engines/neurosymbolic/engine_llama_cpp.py +144 -118
- symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +415 -307
- symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +394 -231
- symai/backend/engines/ocr/engine_apilayer.py +23 -27
- symai/backend/engines/output/engine_stdout.py +10 -13
- symai/backend/engines/{webscraping → scrape}/engine_requests.py +101 -54
- symai/backend/engines/search/engine_openai.py +100 -88
- symai/backend/engines/search/engine_parallel.py +665 -0
- symai/backend/engines/search/engine_perplexity.py +44 -45
- symai/backend/engines/search/engine_serpapi.py +37 -34
- symai/backend/engines/speech_to_text/engine_local_whisper.py +54 -51
- symai/backend/engines/symbolic/engine_wolframalpha.py +15 -9
- symai/backend/engines/text_to_speech/engine_openai.py +20 -26
- symai/backend/engines/text_vision/engine_clip.py +39 -37
- symai/backend/engines/userinput/engine_console.py +5 -6
- symai/backend/mixin/__init__.py +13 -0
- symai/backend/mixin/anthropic.py +48 -38
- symai/backend/mixin/deepseek.py +6 -5
- symai/backend/mixin/google.py +7 -4
- symai/backend/mixin/groq.py +2 -4
- symai/backend/mixin/openai.py +140 -110
- symai/backend/settings.py +87 -20
- symai/chat.py +216 -123
- symai/collect/__init__.py +7 -1
- symai/collect/dynamic.py +80 -70
- symai/collect/pipeline.py +67 -51
- symai/collect/stats.py +161 -109
- symai/components.py +707 -360
- symai/constraints.py +24 -12
- symai/core.py +1857 -1233
- symai/core_ext.py +83 -80
- symai/endpoints/api.py +166 -104
- symai/extended/.DS_Store +0 -0
- symai/extended/__init__.py +46 -12
- symai/extended/api_builder.py +29 -21
- symai/extended/arxiv_pdf_parser.py +23 -14
- symai/extended/bibtex_parser.py +9 -6
- symai/extended/conversation.py +156 -126
- symai/extended/document.py +50 -30
- symai/extended/file_merger.py +57 -14
- symai/extended/graph.py +51 -32
- symai/extended/html_style_template.py +18 -14
- symai/extended/interfaces/blip_2.py +2 -3
- symai/extended/interfaces/clip.py +4 -3
- symai/extended/interfaces/console.py +9 -1
- symai/extended/interfaces/dall_e.py +4 -2
- symai/extended/interfaces/file.py +2 -0
- symai/extended/interfaces/flux.py +4 -2
- symai/extended/interfaces/gpt_image.py +16 -7
- symai/extended/interfaces/input.py +2 -1
- symai/extended/interfaces/llava.py +1 -2
- symai/extended/interfaces/{naive_webscraping.py → naive_scrape.py} +4 -3
- symai/extended/interfaces/naive_vectordb.py +9 -10
- symai/extended/interfaces/ocr.py +5 -3
- 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 +12 -9
- symai/extended/interfaces/python.py +2 -0
- symai/extended/interfaces/serpapi.py +3 -1
- symai/extended/interfaces/terminal.py +2 -4
- symai/extended/interfaces/tts.py +3 -2
- symai/extended/interfaces/whisper.py +3 -2
- symai/extended/interfaces/wolframalpha.py +2 -1
- symai/extended/metrics/__init__.py +11 -1
- symai/extended/metrics/similarity.py +14 -13
- symai/extended/os_command.py +39 -29
- symai/extended/packages/__init__.py +29 -3
- symai/extended/packages/symdev.py +51 -43
- symai/extended/packages/sympkg.py +41 -35
- symai/extended/packages/symrun.py +63 -50
- symai/extended/repo_cloner.py +14 -12
- symai/extended/seo_query_optimizer.py +15 -13
- symai/extended/solver.py +116 -91
- symai/extended/summarizer.py +12 -10
- symai/extended/taypan_interpreter.py +17 -18
- symai/extended/vectordb.py +122 -92
- symai/formatter/__init__.py +9 -1
- symai/formatter/formatter.py +51 -47
- symai/formatter/regex.py +70 -69
- symai/functional.py +325 -176
- symai/imports.py +190 -147
- symai/interfaces.py +57 -28
- symai/memory.py +45 -35
- symai/menu/screen.py +28 -19
- symai/misc/console.py +66 -56
- symai/misc/loader.py +8 -5
- symai/models/__init__.py +17 -1
- symai/models/base.py +395 -236
- symai/models/errors.py +1 -2
- symai/ops/__init__.py +32 -22
- symai/ops/measures.py +24 -25
- symai/ops/primitives.py +1149 -731
- symai/post_processors.py +58 -50
- symai/pre_processors.py +86 -82
- symai/processor.py +21 -13
- symai/prompts.py +764 -685
- symai/server/huggingface_server.py +135 -49
- symai/server/llama_cpp_server.py +21 -11
- symai/server/qdrant_server.py +206 -0
- symai/shell.py +100 -42
- symai/shellsv.py +700 -492
- symai/strategy.py +630 -346
- symai/symbol.py +368 -322
- symai/utils.py +100 -78
- {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/METADATA +22 -10
- symbolicai-1.1.0.dist-info/RECORD +168 -0
- symbolicai-0.21.0.dist-info/RECORD +0 -162
- {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/WHEEL +0 -0
- {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/entry_points.txt +0 -0
- {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/top_level.txt +0 -0
symai/collect/dynamic.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import re
|
|
2
1
|
import ast
|
|
2
|
+
import re
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class DynamicClass:
|
|
@@ -20,7 +20,7 @@ def create_dynamic_class(class_name, **kwargs):
|
|
|
20
20
|
|
|
21
21
|
def parse_custom_class_instances(s):
|
|
22
22
|
pattern = r"(\w+)\((.*?)\)"
|
|
23
|
-
if
|
|
23
|
+
if not isinstance(s, str):
|
|
24
24
|
return s
|
|
25
25
|
matches = re.finditer(pattern, s)
|
|
26
26
|
|
|
@@ -28,80 +28,90 @@ def parse_custom_class_instances(s):
|
|
|
28
28
|
class_name = match.group(1)
|
|
29
29
|
class_args = match.group(2)
|
|
30
30
|
try:
|
|
31
|
-
parsed_args = ast.literal_eval(f
|
|
32
|
-
except:
|
|
31
|
+
parsed_args = ast.literal_eval(f"{{{class_args}}}")
|
|
32
|
+
except (ValueError, SyntaxError):
|
|
33
33
|
parsed_args = create_object_from_string(class_args)
|
|
34
34
|
class_instance = create_dynamic_class(class_name, **parsed_args)
|
|
35
35
|
s = s.replace(match.group(0), repr(class_instance))
|
|
36
36
|
|
|
37
37
|
return s
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if value.startswith('"') and value.endswith('"'):
|
|
59
|
-
value = value.strip('"')
|
|
60
|
-
|
|
61
|
-
if value.startswith('[') and value.endswith(']'):
|
|
62
|
-
value = parse_value(value)
|
|
63
|
-
dir(value)
|
|
64
|
-
if hasattr(value, '__dict__'):
|
|
65
|
-
for k in value.__dict__.keys():
|
|
66
|
-
v = getattr(value, k)
|
|
67
|
-
if type(v) == str:
|
|
68
|
-
value[k.strip("'")] = v.strip("'")
|
|
69
|
-
elif value.startswith('{') and value.endswith('}'):
|
|
70
|
-
value = parse_value(value)
|
|
71
|
-
new_value = {}
|
|
72
|
-
for k in value.keys():
|
|
73
|
-
v = value[k]
|
|
74
|
-
if type(v) == str:
|
|
75
|
-
v = v.strip("'")
|
|
76
|
-
new_value[k.strip("'")] = v
|
|
77
|
-
value = new_value
|
|
78
|
-
updated_attributes.append((key, value))
|
|
79
|
-
return updated_attributes
|
|
80
|
-
|
|
81
|
-
def parse_value(value):
|
|
82
|
-
try:
|
|
83
|
-
value = parse_custom_class_instances(value)
|
|
84
|
-
if type(value) != str:
|
|
85
|
-
return value
|
|
86
|
-
if value.startswith('['):
|
|
87
|
-
value = value[1:-1]
|
|
88
|
-
values = value.split(',')
|
|
89
|
-
return [parse_value(v.strip()) for v in values]
|
|
90
|
-
elif value.startswith('{'):
|
|
91
|
-
value = value[1:-1]
|
|
92
|
-
values = value.split(',')
|
|
93
|
-
return {k.strip(): parse_value(v.strip()) for k, v in [v.split(':', 1) for v in values]}
|
|
94
|
-
res = ast.literal_eval(value)
|
|
95
|
-
if isinstance(res, dict):
|
|
96
|
-
return {k: parse_value(v) for k, v in res.items()}
|
|
97
|
-
elif isinstance(res, list) or isinstance(res, tuple) or isinstance(res, set):
|
|
98
|
-
return [parse_value(v) for v in res]
|
|
99
|
-
else:
|
|
100
|
-
return res
|
|
101
|
-
except:
|
|
39
|
+
|
|
40
|
+
def _strip_quotes(text):
|
|
41
|
+
if not isinstance(text, str):
|
|
42
|
+
return text
|
|
43
|
+
if text.startswith("'") and text.endswith("'"):
|
|
44
|
+
return text.strip("'")
|
|
45
|
+
if text.startswith('"') and text.endswith('"'):
|
|
46
|
+
return text.strip('"')
|
|
47
|
+
return text
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _extract_content(str_class):
|
|
51
|
+
return str_class.split("ChatCompletionMessage(content=")[-1].split(", role=")[0][1:-1]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _parse_value(value):
|
|
55
|
+
try:
|
|
56
|
+
value = parse_custom_class_instances(value)
|
|
57
|
+
if not isinstance(value, str):
|
|
102
58
|
return value
|
|
59
|
+
if value.startswith("["):
|
|
60
|
+
inner_values = value[1:-1]
|
|
61
|
+
values = inner_values.split(",")
|
|
62
|
+
return [_parse_value(v.strip()) for v in values]
|
|
63
|
+
if value.startswith("{"):
|
|
64
|
+
inner_values = value[1:-1]
|
|
65
|
+
values = inner_values.split(",")
|
|
66
|
+
return {
|
|
67
|
+
k.strip(): _parse_value(v.strip()) for k, v in [v.split(":", 1) for v in values]
|
|
68
|
+
}
|
|
69
|
+
result = ast.literal_eval(value)
|
|
70
|
+
if isinstance(result, dict):
|
|
71
|
+
return {k: _parse_value(v) for k, v in result.items()}
|
|
72
|
+
if isinstance(result, (list, tuple, set)):
|
|
73
|
+
return [_parse_value(v) for v in result]
|
|
74
|
+
return result
|
|
75
|
+
except (ValueError, SyntaxError):
|
|
76
|
+
return value
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _process_list_value(raw_value):
|
|
80
|
+
parsed_value = _parse_value(raw_value)
|
|
81
|
+
dir(parsed_value)
|
|
82
|
+
if hasattr(parsed_value, "__dict__"):
|
|
83
|
+
for key in parsed_value.__dict__:
|
|
84
|
+
value = getattr(parsed_value, key)
|
|
85
|
+
if isinstance(value, str):
|
|
86
|
+
parsed_value[key.strip("'")] = value.strip("'")
|
|
87
|
+
return parsed_value
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _process_dict_value(raw_value):
|
|
91
|
+
parsed_value = _parse_value(raw_value)
|
|
92
|
+
new_value = {}
|
|
93
|
+
for key, value in parsed_value.items():
|
|
94
|
+
stripped_value = value.strip("'") if isinstance(value, str) else value
|
|
95
|
+
new_value[key.strip("'")] = stripped_value
|
|
96
|
+
return new_value
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _collect_attributes(str_class):
|
|
100
|
+
attr_pattern = r"(\w+)=(\[.*?\]|\{.*?\}|'.*?'|None|\w+)"
|
|
101
|
+
attributes = re.findall(attr_pattern, str_class)
|
|
102
|
+
updated_attributes = [("content", _extract_content(str_class))]
|
|
103
|
+
for key, raw_value in attributes:
|
|
104
|
+
attr_key = _strip_quotes(key)
|
|
105
|
+
attr_value = _strip_quotes(raw_value)
|
|
106
|
+
if attr_value.startswith("[") and attr_value.endswith("]"):
|
|
107
|
+
attr_value = _process_list_value(attr_value)
|
|
108
|
+
elif attr_value.startswith("{") and attr_value.endswith("}"):
|
|
109
|
+
attr_value = _process_dict_value(attr_value)
|
|
110
|
+
updated_attributes.append((attr_key, attr_value))
|
|
111
|
+
return updated_attributes
|
|
103
112
|
|
|
104
|
-
updated_attributes = updated_attributes_process(str_class)
|
|
105
|
-
obj = DynamicClass(**{key: parse_value(value) for key, value in updated_attributes})
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
# TODO: fix to properly parse nested lists and dicts
|
|
115
|
+
def create_object_from_string(str_class):
|
|
116
|
+
updated_attributes = _collect_attributes(str_class)
|
|
117
|
+
return DynamicClass(**{key: _parse_value(value) for key, value in updated_attributes})
|
symai/collect/pipeline.py
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import json
|
|
2
4
|
import logging
|
|
3
5
|
from datetime import datetime
|
|
4
|
-
from typing import
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
5
7
|
|
|
6
8
|
from bson.objectid import ObjectId
|
|
7
|
-
from pymongo.collection import Collection
|
|
8
|
-
from pymongo.database import Database
|
|
9
9
|
from pymongo.mongo_client import MongoClient
|
|
10
10
|
|
|
11
11
|
from ..backend.settings import SYMAI_CONFIG
|
|
12
|
+
from ..utils import UserMessage
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from pymongo.collection import Collection
|
|
16
|
+
from pymongo.database import Database
|
|
17
|
+
else:
|
|
18
|
+
Collection = Database = Any
|
|
12
19
|
|
|
13
20
|
logger = logging.getLogger(__name__)
|
|
14
21
|
|
|
@@ -24,35 +31,36 @@ def rec_serialize(obj):
|
|
|
24
31
|
if isinstance(obj, (int, float, bool)):
|
|
25
32
|
# For simple types, return the string representation directly.
|
|
26
33
|
return obj
|
|
27
|
-
|
|
34
|
+
if isinstance(obj, dict):
|
|
28
35
|
# For dictionaries, serialize each value. Keep keys as strings.
|
|
29
36
|
return {str(key): rec_serialize(value) for key, value in obj.items()}
|
|
30
|
-
|
|
37
|
+
if isinstance(obj, (list, tuple, set)):
|
|
31
38
|
# For lists, tuples, and sets, serialize each element.
|
|
32
39
|
return [rec_serialize(elem) for elem in obj]
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return str(obj)
|
|
40
|
+
# Attempt JSON serialization first, then fall back to str(...)
|
|
41
|
+
try:
|
|
42
|
+
return json.dumps(obj)
|
|
43
|
+
except TypeError:
|
|
44
|
+
return str(obj)
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
class CollectionRepository:
|
|
42
48
|
def __init__(self) -> None:
|
|
43
|
-
self.support_community: bool
|
|
44
|
-
self.uri: str
|
|
45
|
-
self.db_name: str
|
|
46
|
-
self.collection_name: str
|
|
47
|
-
self.client:
|
|
48
|
-
self.db:
|
|
49
|
-
self.collection:
|
|
50
|
-
|
|
51
|
-
def __enter__(self) ->
|
|
49
|
+
self.support_community: bool = SYMAI_CONFIG["SUPPORT_COMMUNITY"]
|
|
50
|
+
self.uri: str = SYMAI_CONFIG["COLLECTION_URI"]
|
|
51
|
+
self.db_name: str = SYMAI_CONFIG["COLLECTION_DB"]
|
|
52
|
+
self.collection_name: str = SYMAI_CONFIG["COLLECTION_STORAGE"]
|
|
53
|
+
self.client: MongoClient | None = None
|
|
54
|
+
self.db: Database | None = None
|
|
55
|
+
self.collection: Collection | None = None
|
|
56
|
+
|
|
57
|
+
def __enter__(self) -> CollectionRepository:
|
|
52
58
|
self.connect()
|
|
53
59
|
return self
|
|
54
60
|
|
|
55
|
-
def __exit__(
|
|
61
|
+
def __exit__(
|
|
62
|
+
self, exc_type: type | None, exc_val: Exception | None, exc_tb: Any | None
|
|
63
|
+
) -> None:
|
|
56
64
|
self.close()
|
|
57
65
|
|
|
58
66
|
def ping(self) -> bool:
|
|
@@ -60,62 +68,70 @@ class CollectionRepository:
|
|
|
60
68
|
return False
|
|
61
69
|
# Send a ping to confirm a successful connection
|
|
62
70
|
try:
|
|
63
|
-
self.client.admin.command(
|
|
71
|
+
self.client.admin.command("ping")
|
|
64
72
|
return True
|
|
65
73
|
except Exception as e:
|
|
66
|
-
|
|
74
|
+
UserMessage(f"Connection failed: {e}")
|
|
67
75
|
return False
|
|
68
76
|
|
|
69
|
-
def add(self, forward: Any, engine: Any, metadata:
|
|
77
|
+
def add(self, forward: Any, engine: Any, metadata: dict[str, Any] | None = None) -> Any:
|
|
78
|
+
if metadata is None:
|
|
79
|
+
metadata = {}
|
|
70
80
|
if not self.support_community:
|
|
71
81
|
return None
|
|
72
82
|
record = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
"forward": forward,
|
|
84
|
+
"engine": engine,
|
|
85
|
+
"metadata": metadata,
|
|
86
|
+
"created_at": datetime.now(),
|
|
87
|
+
"updated_at": datetime.now(),
|
|
78
88
|
}
|
|
79
|
-
try:
|
|
89
|
+
try: # assure that adding a record does never cause a system error
|
|
80
90
|
return self.collection.insert_one(record).inserted_id if self.collection else None
|
|
81
|
-
except Exception
|
|
91
|
+
except Exception:
|
|
82
92
|
return None
|
|
83
93
|
|
|
84
|
-
def get(self, record_id: str) ->
|
|
94
|
+
def get(self, record_id: str) -> dict[str, Any] | None:
|
|
85
95
|
if not self.support_community:
|
|
86
96
|
return None
|
|
87
|
-
return self.collection.find_one({
|
|
88
|
-
|
|
89
|
-
def update(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
return self.collection.find_one({"_id": ObjectId(record_id)}) if self.collection else None
|
|
98
|
+
|
|
99
|
+
def update(
|
|
100
|
+
self,
|
|
101
|
+
record_id: str,
|
|
102
|
+
forward: Any | None = None,
|
|
103
|
+
engine: str | None = None,
|
|
104
|
+
metadata: dict[str, Any] | None = None,
|
|
105
|
+
) -> Any:
|
|
94
106
|
if not self.support_community:
|
|
95
107
|
return None
|
|
96
|
-
updates:
|
|
108
|
+
updates: dict[str, Any] = {"updated_at": datetime.now()}
|
|
97
109
|
if forward is not None:
|
|
98
|
-
updates[
|
|
110
|
+
updates["forward"] = forward
|
|
99
111
|
if engine is not None:
|
|
100
|
-
updates[
|
|
112
|
+
updates["engine"] = engine
|
|
101
113
|
if metadata is not None:
|
|
102
|
-
updates[
|
|
114
|
+
updates["metadata"] = metadata
|
|
103
115
|
|
|
104
|
-
return
|
|
116
|
+
return (
|
|
117
|
+
self.collection.update_one({"_id": ObjectId(record_id)}, {"$set": updates})
|
|
118
|
+
if self.collection
|
|
119
|
+
else None
|
|
120
|
+
)
|
|
105
121
|
|
|
106
122
|
def delete(self, record_id: str) -> Any:
|
|
107
123
|
if not self.support_community:
|
|
108
124
|
return None
|
|
109
|
-
return self.collection.delete_one({
|
|
125
|
+
return self.collection.delete_one({"_id": ObjectId(record_id)}) if self.collection else None
|
|
110
126
|
|
|
111
|
-
def list(self, filters:
|
|
127
|
+
def list(self, filters: dict[str, Any] | None = None, limit: int = 0) -> list[dict[str, Any]]:
|
|
112
128
|
if not self.support_community:
|
|
113
129
|
return None
|
|
114
130
|
if filters is None:
|
|
115
131
|
filters = {}
|
|
116
132
|
return list(self.collection.find(filters).limit(limit)) if self.collection else []
|
|
117
133
|
|
|
118
|
-
def count(self, filters:
|
|
134
|
+
def count(self, filters: dict[str, Any] | None = None) -> int:
|
|
119
135
|
if not self.support_community:
|
|
120
136
|
return None
|
|
121
137
|
if filters is None:
|
|
@@ -126,14 +142,14 @@ class CollectionRepository:
|
|
|
126
142
|
try:
|
|
127
143
|
if self.client is None and self.support_community:
|
|
128
144
|
self.client = MongoClient(self.uri)
|
|
129
|
-
self.db
|
|
145
|
+
self.db = self.client[self.db_name]
|
|
130
146
|
self.collection = self.db[self.collection_name]
|
|
131
147
|
except Exception as e:
|
|
132
148
|
# disable retries
|
|
133
|
-
self.client
|
|
134
|
-
self.db
|
|
149
|
+
self.client = False
|
|
150
|
+
self.db = None
|
|
135
151
|
self.collection = None
|
|
136
|
-
|
|
152
|
+
UserMessage(f"[WARN] MongoClient: Connection failed: {e}")
|
|
137
153
|
|
|
138
154
|
def close(self) -> None:
|
|
139
155
|
if self.client is not None:
|