atomicshop 2.16.17__py3-none-any.whl → 2.16.19__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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/filesystem.py +74 -29
- atomicshop/mitm/recs_files.py +1 -1
- atomicshop/wrappers/loggingw/reading.py +1 -2
- atomicshop/wrappers/mongodbw/mongo_infra.py +8 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +576 -29
- {atomicshop-2.16.17.dist-info → atomicshop-2.16.19.dist-info}/METADATA +1 -1
- {atomicshop-2.16.17.dist-info → atomicshop-2.16.19.dist-info}/RECORD +11 -11
- {atomicshop-2.16.17.dist-info → atomicshop-2.16.19.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.16.17.dist-info → atomicshop-2.16.19.dist-info}/WHEEL +0 -0
- {atomicshop-2.16.17.dist-info → atomicshop-2.16.19.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/filesystem.py
CHANGED
|
@@ -422,17 +422,33 @@ def temporary_change_working_directory(new_working_directory: str) -> None:
|
|
|
422
422
|
os.chdir(original_working_directory)
|
|
423
423
|
|
|
424
424
|
|
|
425
|
-
def move_file(source_file_path: str,
|
|
425
|
+
def move_file(source_file_path: str, target_directory: str, overwrite: bool = True) -> None:
|
|
426
426
|
"""
|
|
427
427
|
The function moves file from source to target.
|
|
428
428
|
|
|
429
429
|
:param source_file_path: string, full path to source file.
|
|
430
|
-
:param
|
|
430
|
+
:param target_directory: string, full path to target directory.
|
|
431
431
|
:param overwrite: boolean, if 'False', then the function will not overwrite the file if it exists.
|
|
432
432
|
|
|
433
|
+
Example:
|
|
434
|
+
Before move:
|
|
435
|
+
Source file = 'C:/Users/user1/Downloads/file-to-move.txt'
|
|
436
|
+
Move to directory = 'C:/Users/user1/Documents'
|
|
437
|
+
|
|
438
|
+
Move:
|
|
439
|
+
source_file_path = 'C:/Users/user1/Downloads/file-to-move.txt'
|
|
440
|
+
target_directory = 'C:/Users/user1/Documents'
|
|
441
|
+
move_file(source_file_path, target_file_path)
|
|
442
|
+
|
|
443
|
+
After move:
|
|
444
|
+
'C:/Users/user1/Downloads'
|
|
445
|
+
'C:/Users/user1/Documents/file-to-move.txt'
|
|
446
|
+
|
|
433
447
|
:return: None
|
|
434
448
|
"""
|
|
435
449
|
|
|
450
|
+
target_file_path = target_directory + os.sep + Path(source_file_path).name
|
|
451
|
+
|
|
436
452
|
# Check if 'no_overwrite' is set to 'True' and if the file exists.
|
|
437
453
|
if not overwrite:
|
|
438
454
|
if is_file_exists(target_file_path):
|
|
@@ -455,12 +471,17 @@ def move_folder(source_directory: str, target_directory: str, overwrite: bool =
|
|
|
455
471
|
------------------------------
|
|
456
472
|
|
|
457
473
|
Example:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
474
|
+
Before move:
|
|
475
|
+
Source folder = 'C:/Users/user1/Downloads/folder-to-move'
|
|
476
|
+
Move to directory = 'C:/Users/user1/Documents'
|
|
477
|
+
|
|
478
|
+
Move:
|
|
479
|
+
source_directory = 'C:/Users/user1/Downloads/folder-to-move'
|
|
480
|
+
target_directory = 'C:/Users/user1/Documents'
|
|
481
|
+
move_folder(source_directory, target_directory)
|
|
461
482
|
|
|
462
|
-
|
|
463
|
-
|
|
483
|
+
Result path of the 'folder-to-move' will be:
|
|
484
|
+
'C:/Users/user1/Documents/folder-to-move'
|
|
464
485
|
|
|
465
486
|
"""
|
|
466
487
|
|
|
@@ -473,14 +494,14 @@ def move_folder(source_directory: str, target_directory: str, overwrite: bool =
|
|
|
473
494
|
shutil.move(source_directory, target_directory)
|
|
474
495
|
|
|
475
496
|
|
|
476
|
-
def
|
|
497
|
+
def move_top_level_files_from_folder_to_folder(
|
|
477
498
|
source_directory: str,
|
|
478
499
|
target_directory: str,
|
|
479
500
|
overwrite: bool = True
|
|
480
501
|
):
|
|
481
502
|
"""
|
|
482
|
-
The function is
|
|
483
|
-
|
|
503
|
+
The function is non-recursive to move only top level files from source directory to target directory
|
|
504
|
+
overwriting existing files.
|
|
484
505
|
|
|
485
506
|
:param source_directory: string, full path to source directory.
|
|
486
507
|
:param target_directory: string, full path to target directory.
|
|
@@ -488,26 +509,50 @@ def move_files_from_folder_to_folder(
|
|
|
488
509
|
"""
|
|
489
510
|
|
|
490
511
|
# Iterate over each item in the source directory
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
source_item = os.path.join(source_directory, item)
|
|
494
|
-
destination_item = os.path.join(target_directory, item)
|
|
512
|
+
top_level_files: list[str] = get_paths_from_directory(
|
|
513
|
+
directory_path=source_directory, get_file=True, recursive=False, simple_list=True)
|
|
495
514
|
|
|
515
|
+
for source_item in top_level_files:
|
|
496
516
|
# Move each item to the destination directory
|
|
497
|
-
move_file(source_file_path=source_item,
|
|
517
|
+
move_file(source_file_path=source_item, target_directory=target_directory, overwrite=overwrite)
|
|
498
518
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
519
|
+
|
|
520
|
+
def move_folder_contents_to_folder(
|
|
521
|
+
source_directory: str,
|
|
522
|
+
target_directory: str,
|
|
523
|
+
overwrite: bool = True
|
|
524
|
+
):
|
|
525
|
+
"""
|
|
526
|
+
The function moves all the contents of the source directory to the target directory.
|
|
527
|
+
If target directory is inside the source directory, this folder will be skipped.
|
|
528
|
+
|
|
529
|
+
:param source_directory: string, full path to source directory.
|
|
530
|
+
:param target_directory: string, full path to target directory.
|
|
531
|
+
:param overwrite: boolean, if 'True', then the function will overwrite the files if they exist.
|
|
532
|
+
"""
|
|
533
|
+
|
|
534
|
+
# Make sure the destination directory exists, if not create it
|
|
535
|
+
os.makedirs(target_directory, exist_ok=True)
|
|
536
|
+
|
|
537
|
+
# Move contents of the source directory to the destination directory
|
|
538
|
+
for item in os.listdir(source_directory):
|
|
539
|
+
s = os.path.join(source_directory, item)
|
|
540
|
+
d = os.path.join(target_directory, item)
|
|
541
|
+
|
|
542
|
+
# if the target directory is inside the source directory, skip it
|
|
543
|
+
if os.path.abspath(target_directory).startswith(os.path.abspath(s)):
|
|
544
|
+
continue
|
|
545
|
+
|
|
546
|
+
if os.path.isdir(s):
|
|
547
|
+
if os.path.exists(d) and not overwrite:
|
|
548
|
+
print(f"Directory {d} already exists. Skipping due to overwrite=False.")
|
|
549
|
+
else:
|
|
550
|
+
shutil.move(s, d)
|
|
551
|
+
else:
|
|
552
|
+
if os.path.exists(d) and not overwrite:
|
|
553
|
+
print(f"File {d} already exists. Skipping due to overwrite=False.")
|
|
554
|
+
else:
|
|
555
|
+
shutil.move(s, d)
|
|
511
556
|
|
|
512
557
|
|
|
513
558
|
def copy_file(
|
|
@@ -681,7 +726,7 @@ def get_paths_from_directory(
|
|
|
681
726
|
sort_by_last_modified_time: bool = False,
|
|
682
727
|
add_file_binary: bool = False,
|
|
683
728
|
add_file_hash: bool = False,
|
|
684
|
-
) -> list[AtomicPath]:
|
|
729
|
+
) -> Union[list[AtomicPath], list[str]]:
|
|
685
730
|
"""
|
|
686
731
|
Recursive, by option.
|
|
687
732
|
The function receives a filesystem directory as string, scans it recursively for files and returns list of
|
|
@@ -1524,7 +1569,7 @@ def backup_file(
|
|
|
1524
1569
|
else:
|
|
1525
1570
|
file_name: str = f"{file_name_no_extension}_{timestamp}{file_extension}"
|
|
1526
1571
|
backup_file_path: str = str(Path(backup_directory) / file_name)
|
|
1527
|
-
move_file(file_path,
|
|
1572
|
+
move_file(file_path, backup_directory)
|
|
1528
1573
|
|
|
1529
1574
|
return backup_file_path
|
|
1530
1575
|
else:
|
atomicshop/mitm/recs_files.py
CHANGED
|
@@ -51,7 +51,7 @@ def recs_archiver(recs_directory: str) -> list:
|
|
|
51
51
|
target_directory_path: str = f"{directory_path.path}{os.sep}{recs_atomic_path.datetime_string}"
|
|
52
52
|
filesystem.create_directory(target_directory_path)
|
|
53
53
|
filesystem.move_file(
|
|
54
|
-
recs_atomic_path.path,
|
|
54
|
+
recs_atomic_path.path, target_directory_path)
|
|
55
55
|
|
|
56
56
|
# Archive directories.
|
|
57
57
|
archive_directories: list = filesystem.get_paths_from_directory(
|
|
@@ -207,8 +207,7 @@ def get_all_log_files_into_list(
|
|
|
207
207
|
filesystem.create_directory(move_to_path_with_timestamp)
|
|
208
208
|
# Move the statistics files.
|
|
209
209
|
for single_file in logs_files:
|
|
210
|
-
|
|
211
|
-
filesystem.move_file(single_file.path, move_to_path_with_file)
|
|
210
|
+
filesystem.move_file(single_file.path, move_to_path_with_timestamp)
|
|
212
211
|
|
|
213
212
|
return logs_content
|
|
214
213
|
|
|
@@ -23,6 +23,14 @@ def test_connection(
|
|
|
23
23
|
uri: str = MONGODB_DEFAULT_URI,
|
|
24
24
|
raise_exception: bool = False
|
|
25
25
|
) -> bool:
|
|
26
|
+
"""
|
|
27
|
+
Test the connection to the MongoDB server.
|
|
28
|
+
|
|
29
|
+
:param uri: str, URI to the MongoDB server.
|
|
30
|
+
:param raise_exception: bool, True to raise an exception if the connection fails, False otherwise (just return
|
|
31
|
+
False).
|
|
32
|
+
:return: bool, True if the connection is successful, False otherwise.
|
|
33
|
+
"""
|
|
26
34
|
try:
|
|
27
35
|
client = MongoClient(uri)
|
|
28
36
|
client.admin.command('ping')
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
from typing import Union
|
|
1
|
+
from typing import Union, Literal
|
|
2
2
|
import datetime
|
|
3
|
+
import json
|
|
3
4
|
|
|
5
|
+
# noinspection PyPackageRequirements
|
|
4
6
|
import pymongo
|
|
7
|
+
# noinspection PyPackageRequirements
|
|
8
|
+
import pymongo.database
|
|
5
9
|
|
|
6
10
|
from ...basics import dicts
|
|
7
11
|
|
|
@@ -14,6 +18,253 @@ These are good examples to get you started, but can't really cover all the use c
|
|
|
14
18
|
"""
|
|
15
19
|
|
|
16
20
|
|
|
21
|
+
class MongoDBWrapper:
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
db_name: str,
|
|
25
|
+
uri: str = mongo_infra.MONGODB_DEFAULT_URI
|
|
26
|
+
):
|
|
27
|
+
self.db_name: str = db_name
|
|
28
|
+
self.uri: str = uri
|
|
29
|
+
|
|
30
|
+
# noinspection PyTypeChecker
|
|
31
|
+
self.client: pymongo.MongoClient = None
|
|
32
|
+
# noinspection PyTypeChecker
|
|
33
|
+
self.db: pymongo.database.Database = None
|
|
34
|
+
|
|
35
|
+
def connect(self):
|
|
36
|
+
"""
|
|
37
|
+
Connect to a MongoDB database.
|
|
38
|
+
:return: pymongo.MongoClient, the client object.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
if not self.client:
|
|
42
|
+
self.client = connect(uri=self.uri)
|
|
43
|
+
self.db = get_db(database=self.db_name, mongo_client=self.client)
|
|
44
|
+
|
|
45
|
+
def disconnect(self):
|
|
46
|
+
"""
|
|
47
|
+
Disconnect from a MongoDB database.
|
|
48
|
+
:return: None
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
if self.client:
|
|
52
|
+
self.client.close()
|
|
53
|
+
self.client = None
|
|
54
|
+
|
|
55
|
+
def index(
|
|
56
|
+
self,
|
|
57
|
+
object_instance: Union[list[dict], dict],
|
|
58
|
+
collection_name: str,
|
|
59
|
+
add_timestamp: bool = False,
|
|
60
|
+
convert_mixed_lists_to_strings: bool = False
|
|
61
|
+
):
|
|
62
|
+
"""
|
|
63
|
+
Add a dictionary or list dictionaries to a MongoDB collection.
|
|
64
|
+
:param object_instance: list of dictionaries or dictionary to add to the collection.
|
|
65
|
+
:param collection_name: str, the name of the collection.
|
|
66
|
+
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
67
|
+
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are
|
|
68
|
+
strings and integers, the integers will be converted to strings.
|
|
69
|
+
|
|
70
|
+
:return: None
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
self.connect()
|
|
74
|
+
|
|
75
|
+
index(
|
|
76
|
+
object_instance=object_instance,
|
|
77
|
+
database=self.db, collection_name=collection_name,
|
|
78
|
+
add_timestamp=add_timestamp, convert_mixed_lists_to_strings=convert_mixed_lists_to_strings,
|
|
79
|
+
mongo_client=self.client, close_client=False)
|
|
80
|
+
|
|
81
|
+
def delete(
|
|
82
|
+
self,
|
|
83
|
+
object_instance: Union[list[dict], dict],
|
|
84
|
+
collection_name: str
|
|
85
|
+
):
|
|
86
|
+
"""
|
|
87
|
+
Remove a list of dictionaries or a dictionary from a MongoDB collection.
|
|
88
|
+
|
|
89
|
+
:param object_instance: list of dictionaries, the list of dictionaries to remove from the collection.
|
|
90
|
+
:param collection_name: str, the name of the collection.
|
|
91
|
+
|
|
92
|
+
:return: None
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
self.connect()
|
|
96
|
+
|
|
97
|
+
delete(
|
|
98
|
+
object_instance=object_instance,
|
|
99
|
+
database=self.db, collection_name=collection_name,
|
|
100
|
+
mongo_client=self.client, close_client=False)
|
|
101
|
+
|
|
102
|
+
def find(
|
|
103
|
+
self,
|
|
104
|
+
collection_name: str,
|
|
105
|
+
query: dict = None,
|
|
106
|
+
page: int = None,
|
|
107
|
+
items: int = None,
|
|
108
|
+
sorting: dict[str, Literal[
|
|
109
|
+
'asc', 'desc',
|
|
110
|
+
1, -1]] = None,
|
|
111
|
+
convert_object_id_to_str: bool = False,
|
|
112
|
+
keys_convert_to_dict: list[str] = None
|
|
113
|
+
) -> list[dict]:
|
|
114
|
+
"""
|
|
115
|
+
Find entries in a MongoDB collection by query.
|
|
116
|
+
:param collection_name: str, the name of the collection.
|
|
117
|
+
:param query: dict, the query to search for.
|
|
118
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
119
|
+
query = {'name': 'John'}
|
|
120
|
+
Example, return all entries from collection:
|
|
121
|
+
query = None
|
|
122
|
+
|
|
123
|
+
CHECK MORE EXAMPLES IN THE DOCSTRING OF THE FUNCTION 'find' BELOW which is not in this class.
|
|
124
|
+
:param page: int, the page number (Optional).
|
|
125
|
+
The results are filtered after results are fetched from db.
|
|
126
|
+
:param items: int, the number of results per page (Optional).
|
|
127
|
+
The results are filtered after results are fetched from db.
|
|
128
|
+
:param sorting: dict, the name of the field and the order to sort the containers by.
|
|
129
|
+
You can use several fields to sort the containers by several fields.
|
|
130
|
+
In this case the containers will be sorted by the first field, then by the second field, etc.
|
|
131
|
+
You can also use only singular field to sort the containers by only one field.
|
|
132
|
+
Usage:
|
|
133
|
+
{
|
|
134
|
+
field_name: order
|
|
135
|
+
}
|
|
136
|
+
Example:
|
|
137
|
+
{
|
|
138
|
+
'vendor': 'asc',
|
|
139
|
+
'model': 'desc'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Or example using integers:
|
|
143
|
+
{
|
|
144
|
+
'vendor': 1,
|
|
145
|
+
'model': -1
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
:param convert_object_id_to_str: bool, if True, the '_id' field will be converted to a string.
|
|
149
|
+
The '_id' field is an ObjectId type, which is a complex object, it can be converted to a string for simpler
|
|
150
|
+
processing.
|
|
151
|
+
:param keys_convert_to_dict: list, the keys of the documents that should be converted from string to dict.
|
|
152
|
+
Recursively searches for keys in specified list in a nested dictionary in result entries list,
|
|
153
|
+
and converts their values using 'json.loads' if found.
|
|
154
|
+
:return: list of dictionaries, the list of entries that match the query.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
self.connect()
|
|
158
|
+
|
|
159
|
+
entries: list[dict] = find(
|
|
160
|
+
database=self.db, collection_name=collection_name,
|
|
161
|
+
query=query, page=page, items=items, sorting=sorting,
|
|
162
|
+
convert_object_id_to_str=convert_object_id_to_str, key_convert_to_dict=keys_convert_to_dict,
|
|
163
|
+
mongo_client=self.client, close_client=False)
|
|
164
|
+
|
|
165
|
+
return entries
|
|
166
|
+
|
|
167
|
+
def distinct(
|
|
168
|
+
self,
|
|
169
|
+
collection_name: str,
|
|
170
|
+
field_name: str,
|
|
171
|
+
query: dict = None
|
|
172
|
+
) -> list:
|
|
173
|
+
"""
|
|
174
|
+
Get distinct values of a field from a MongoDB collection.
|
|
175
|
+
Example:
|
|
176
|
+
Example database:
|
|
177
|
+
{
|
|
178
|
+
'users': [
|
|
179
|
+
{'name': 'John', 'age': 25},
|
|
180
|
+
{'name': 'John', 'age': 30},
|
|
181
|
+
{'name': 'Alice', 'age': 25}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
Get distinct values of the field 'name' from the collection 'users':
|
|
186
|
+
distinct('users', 'name')
|
|
187
|
+
|
|
188
|
+
Output:
|
|
189
|
+
['John', 'Alice']
|
|
190
|
+
|
|
191
|
+
:param collection_name: str, the name of the collection.
|
|
192
|
+
:param field_name: str, the name of the field.
|
|
193
|
+
:param query: dict, the query to search for. If None, the query will not be executed.
|
|
194
|
+
|
|
195
|
+
:return: list, the list of distinct values.
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
self.connect()
|
|
199
|
+
|
|
200
|
+
distinct_values = distinct(
|
|
201
|
+
database=self.db, collection_name=collection_name,
|
|
202
|
+
field_name=field_name, query=query, mongo_client=self.client, close_client=False)
|
|
203
|
+
|
|
204
|
+
return distinct_values
|
|
205
|
+
|
|
206
|
+
def count_entries_in_collection(
|
|
207
|
+
self,
|
|
208
|
+
collection_name: str,
|
|
209
|
+
query: dict = None
|
|
210
|
+
) -> int:
|
|
211
|
+
"""
|
|
212
|
+
Count entries in a MongoDB collection by query.
|
|
213
|
+
|
|
214
|
+
:param collection_name: str, the name of the collection.
|
|
215
|
+
:param query: dict, the query to search for.
|
|
216
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
217
|
+
query = {'name': 'John'}
|
|
218
|
+
Example, return all entries from collection:
|
|
219
|
+
query = None
|
|
220
|
+
|
|
221
|
+
:return: int, the number of entries that match the query.
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
self.connect()
|
|
225
|
+
|
|
226
|
+
count = count_entries_in_collection(
|
|
227
|
+
database=self.db, collection_name=collection_name,
|
|
228
|
+
query=query, mongo_client=self.client, close_client=False)
|
|
229
|
+
|
|
230
|
+
return count
|
|
231
|
+
|
|
232
|
+
def get_client(self):
|
|
233
|
+
return self.client
|
|
234
|
+
|
|
235
|
+
def get_stats_db(
|
|
236
|
+
self
|
|
237
|
+
):
|
|
238
|
+
"""
|
|
239
|
+
Get the stats of a MongoDB database.
|
|
240
|
+
|
|
241
|
+
:return: dict, the stats of the collection.
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
self.connect()
|
|
245
|
+
|
|
246
|
+
stats = get_stats_db(
|
|
247
|
+
database=self.db, mongo_client=self.client, close_client=False)
|
|
248
|
+
|
|
249
|
+
return stats
|
|
250
|
+
|
|
251
|
+
def get_stats_db_size(
|
|
252
|
+
self
|
|
253
|
+
):
|
|
254
|
+
"""
|
|
255
|
+
Get the size of a MongoDB database in bytes.
|
|
256
|
+
|
|
257
|
+
:return: int, the size of the database in bytes.
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
self.connect()
|
|
261
|
+
|
|
262
|
+
size = get_stats_db_size(
|
|
263
|
+
database=self.db, mongo_client=self.client, close_client=False)
|
|
264
|
+
|
|
265
|
+
return size
|
|
266
|
+
|
|
267
|
+
|
|
17
268
|
def connect(uri: str = mongo_infra.MONGODB_DEFAULT_URI):
|
|
18
269
|
"""
|
|
19
270
|
Connect to a MongoDB database.
|
|
@@ -23,9 +274,27 @@ def connect(uri: str = mongo_infra.MONGODB_DEFAULT_URI):
|
|
|
23
274
|
return pymongo.MongoClient(uri)
|
|
24
275
|
|
|
25
276
|
|
|
277
|
+
def get_db(
|
|
278
|
+
database: str,
|
|
279
|
+
mongo_client: pymongo.MongoClient = None
|
|
280
|
+
) -> pymongo.database.Database:
|
|
281
|
+
"""
|
|
282
|
+
Get a MongoDB database object.
|
|
283
|
+
:param database: String, the name of the database.
|
|
284
|
+
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
285
|
+
If None, a new connection will be created to default URI.
|
|
286
|
+
:return: pymongo.database.Database, the database object.
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
if not mongo_client:
|
|
290
|
+
mongo_client = connect()
|
|
291
|
+
|
|
292
|
+
return mongo_client[database]
|
|
293
|
+
|
|
294
|
+
|
|
26
295
|
def index(
|
|
27
296
|
object_instance: Union[list[dict], dict],
|
|
28
|
-
|
|
297
|
+
database: Union[str, pymongo.database.Database],
|
|
29
298
|
collection_name: str,
|
|
30
299
|
add_timestamp: bool = False,
|
|
31
300
|
convert_mixed_lists_to_strings: bool = False,
|
|
@@ -35,7 +304,9 @@ def index(
|
|
|
35
304
|
"""
|
|
36
305
|
Add a dictionary or list dictionaries to a MongoDB collection.
|
|
37
306
|
:param object_instance: list of dictionaries or dictionary to add to the collection.
|
|
38
|
-
:param
|
|
307
|
+
:param database: String or the database object.
|
|
308
|
+
str - the name of the database. In this case the database object will be created.
|
|
309
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
39
310
|
:param collection_name: str, the name of the collection.
|
|
40
311
|
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
41
312
|
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are strings and integers,
|
|
@@ -53,7 +324,7 @@ def index(
|
|
|
53
324
|
mongo_client = connect()
|
|
54
325
|
close_client = True
|
|
55
326
|
|
|
56
|
-
db = mongo_client
|
|
327
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
57
328
|
collection = db[collection_name]
|
|
58
329
|
|
|
59
330
|
if convert_mixed_lists_to_strings:
|
|
@@ -78,7 +349,7 @@ def index(
|
|
|
78
349
|
|
|
79
350
|
def delete(
|
|
80
351
|
object_instance: Union[list[dict], dict],
|
|
81
|
-
|
|
352
|
+
database: Union[str, pymongo.database.Database],
|
|
82
353
|
collection_name: str,
|
|
83
354
|
mongo_client: pymongo.MongoClient = None,
|
|
84
355
|
close_client: bool = False
|
|
@@ -87,7 +358,9 @@ def delete(
|
|
|
87
358
|
Remove a list of dictionaries or a dictionary from a MongoDB collection.
|
|
88
359
|
|
|
89
360
|
:param object_instance: list of dictionaries, the list of dictionaries to remove from the collection.
|
|
90
|
-
:param
|
|
361
|
+
:param database: String or the database object.
|
|
362
|
+
str - the name of the database. In this case the database object will be created.
|
|
363
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
91
364
|
:param collection_name: str, the name of the collection.
|
|
92
365
|
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
93
366
|
If None, a new connection will be created to default URI.
|
|
@@ -102,7 +375,7 @@ def delete(
|
|
|
102
375
|
mongo_client = connect()
|
|
103
376
|
close_client = True
|
|
104
377
|
|
|
105
|
-
db = mongo_client
|
|
378
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
106
379
|
collection = db[collection_name]
|
|
107
380
|
|
|
108
381
|
if isinstance(object_instance, dict):
|
|
@@ -116,21 +389,91 @@ def delete(
|
|
|
116
389
|
|
|
117
390
|
|
|
118
391
|
def find(
|
|
119
|
-
|
|
392
|
+
database: Union[str, pymongo.database.Database],
|
|
120
393
|
collection_name: str,
|
|
121
394
|
query: dict = None,
|
|
395
|
+
page: int = None,
|
|
396
|
+
items: int = None,
|
|
397
|
+
sorting: dict[str, Literal[
|
|
398
|
+
'asc', 'desc',
|
|
399
|
+
1, -1]] = None,
|
|
400
|
+
convert_object_id_to_str: bool = False,
|
|
401
|
+
key_convert_to_dict: list[str] = None,
|
|
122
402
|
mongo_client: pymongo.MongoClient = None,
|
|
123
403
|
close_client: bool = False
|
|
124
|
-
):
|
|
404
|
+
) -> list[dict]:
|
|
125
405
|
"""
|
|
126
406
|
Find entries in a MongoDB collection by query.
|
|
127
|
-
:param
|
|
407
|
+
:param database: String or the database object.
|
|
408
|
+
str - the name of the database. In this case the database object will be created.
|
|
409
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
128
410
|
:param collection_name: str, the name of the collection.
|
|
129
411
|
:param query: dict, the query to search for.
|
|
130
|
-
Example, search for all entries with column name 'name' equal to 'John':
|
|
131
|
-
query = {'name': 'John'}
|
|
132
412
|
Example, return all entries from collection:
|
|
133
413
|
query = None
|
|
414
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
415
|
+
query = {'name': 'John'}
|
|
416
|
+
|
|
417
|
+
Additional parameters to use in the value of the query:
|
|
418
|
+
$regex: Will search for a regex pattern in the field.
|
|
419
|
+
Example for searching for a value that contains 'test':
|
|
420
|
+
query = {'field_name': {'$regex': 'test'}}
|
|
421
|
+
This will return all entries where the field 'field_name' contains the word 'test':
|
|
422
|
+
'test', 'test1', '2test', etc.
|
|
423
|
+
|
|
424
|
+
Example for searching for a value that starts with 'test':
|
|
425
|
+
query = {'field_name': {'$regex': '^test'}}
|
|
426
|
+
$options: The options for the regex search.
|
|
427
|
+
'i': case-insensitive search.
|
|
428
|
+
Example for case-insensitive search:
|
|
429
|
+
query = {'field_name': {'$regex': 'test', '$options': 'i'}}
|
|
430
|
+
$and: Will search for entries that match all the conditions.
|
|
431
|
+
Example for searching for entries that match all the conditions:
|
|
432
|
+
query = {'$and': [
|
|
433
|
+
{'field_name1': 'value1'},
|
|
434
|
+
{'field_name2': 'value2'}
|
|
435
|
+
]}
|
|
436
|
+
$or: Will search for entries that match at least one of the conditions.
|
|
437
|
+
Example for searching for entries that match at least one of the conditions:
|
|
438
|
+
query = {'$or': [
|
|
439
|
+
{'field_name1': 'value1'},
|
|
440
|
+
{'field_name2': 'value2'}
|
|
441
|
+
]}
|
|
442
|
+
$in: Will search for a value in a list of values.
|
|
443
|
+
Example for searching for a value that is in a list of values:
|
|
444
|
+
query = {'field_name': {'$in': ['value1', 'value2', 'value3']}}
|
|
445
|
+
$nin: Will search for a value not in a list of values.
|
|
446
|
+
Example for searching for a value that is not in a list of values:
|
|
447
|
+
query = {'field_name': {'$nin': ['value1', 'value2', 'value3']}}
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
:param page: int, the page number (Optional).
|
|
451
|
+
:param items: int, the number of results per page (Optional).
|
|
452
|
+
:param sorting: dict, the name of the field and the order to sort the containers by.
|
|
453
|
+
You can use several fields to sort the containers by several fields.
|
|
454
|
+
In this case the containers will be sorted by the first field, then by the second field, etc.
|
|
455
|
+
You can also use only singular field to sort the containers by only one field.
|
|
456
|
+
Usage:
|
|
457
|
+
{
|
|
458
|
+
field_name: order
|
|
459
|
+
}
|
|
460
|
+
Example:
|
|
461
|
+
{
|
|
462
|
+
'vendor': 'asc',
|
|
463
|
+
'model': 'desc'
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
Or example using integers:
|
|
467
|
+
{
|
|
468
|
+
'vendor': 1,
|
|
469
|
+
'model': -1
|
|
470
|
+
}
|
|
471
|
+
:param convert_object_id_to_str: bool, if True, the '_id' field will be converted to a string.
|
|
472
|
+
The '_id' field is an ObjectId type, which is a complex object, it can be converted to a string for simpler
|
|
473
|
+
processing.
|
|
474
|
+
:param key_convert_to_dict: list, the keys of the documents that should be converted from string to dict.
|
|
475
|
+
Recursively searches for keys in specified list in a nested dictionary in result entries list,
|
|
476
|
+
and converts their values using 'json.loads' if found.
|
|
134
477
|
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
135
478
|
If None, a new connection will be created to default URI.
|
|
136
479
|
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
@@ -138,17 +481,58 @@ def find(
|
|
|
138
481
|
:return: list of dictionaries, the list of entries that match the query.
|
|
139
482
|
"""
|
|
140
483
|
|
|
484
|
+
if page and not items:
|
|
485
|
+
raise ValueError("If 'page' is provided, 'items' must be provided as well.")
|
|
486
|
+
elif items and not page:
|
|
487
|
+
page = 1
|
|
488
|
+
|
|
489
|
+
if sorting:
|
|
490
|
+
for key_to_sort_by, order in sorting.items():
|
|
491
|
+
if order not in ['asc', 'desc', 1, -1]:
|
|
492
|
+
raise ValueError("The order must be 'asc', 'desc', 1 or -1.")
|
|
493
|
+
|
|
141
494
|
if not mongo_client:
|
|
142
495
|
mongo_client = connect()
|
|
143
496
|
close_client = True
|
|
144
497
|
|
|
145
|
-
db = mongo_client
|
|
498
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
146
499
|
collection = db[collection_name]
|
|
147
500
|
|
|
148
501
|
if query is None:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
502
|
+
query = {}
|
|
503
|
+
|
|
504
|
+
# Calculate the number of documents to skip
|
|
505
|
+
skip_items = 0
|
|
506
|
+
if page and items:
|
|
507
|
+
skip_items = (page - 1) * items
|
|
508
|
+
|
|
509
|
+
collection_items = collection.find(query)
|
|
510
|
+
|
|
511
|
+
if sorting:
|
|
512
|
+
sorting_list_of_tuples: list[tuple[str, int]] = []
|
|
513
|
+
for key_to_sort_by, order in sorting.items():
|
|
514
|
+
if order == 'asc':
|
|
515
|
+
order = pymongo.ASCENDING
|
|
516
|
+
elif order == 'desc':
|
|
517
|
+
order = pymongo.DESCENDING
|
|
518
|
+
|
|
519
|
+
sorting_list_of_tuples.append((key_to_sort_by, order))
|
|
520
|
+
|
|
521
|
+
collection_items = collection_items.sort(sorting_list_of_tuples)
|
|
522
|
+
|
|
523
|
+
# 'skip_items' can be 0, if we ask for the first page, so we still need to cut the number of items.
|
|
524
|
+
# In this case checking if 'items' is not None is enough.
|
|
525
|
+
if items:
|
|
526
|
+
collection_items = collection_items.skip(skip_items).limit(items)
|
|
527
|
+
|
|
528
|
+
entries: list[dict] = list(collection_items)
|
|
529
|
+
|
|
530
|
+
if convert_object_id_to_str:
|
|
531
|
+
for entry_index, entry in enumerate(entries):
|
|
532
|
+
entries[entry_index]['_id'] = str(entry['_id'])
|
|
533
|
+
|
|
534
|
+
if key_convert_to_dict and entries:
|
|
535
|
+
entries = _convert_key_values_to_objects(keys_convert_to_dict=key_convert_to_dict, returned_data=entries)
|
|
152
536
|
|
|
153
537
|
if close_client:
|
|
154
538
|
mongo_client.close()
|
|
@@ -156,15 +540,116 @@ def find(
|
|
|
156
540
|
return entries
|
|
157
541
|
|
|
158
542
|
|
|
543
|
+
def distinct(
|
|
544
|
+
database: Union[str, pymongo.database.Database],
|
|
545
|
+
collection_name: str,
|
|
546
|
+
field_name: str,
|
|
547
|
+
query: dict = None,
|
|
548
|
+
mongo_client: pymongo.MongoClient = None,
|
|
549
|
+
close_client: bool = False
|
|
550
|
+
) -> list:
|
|
551
|
+
"""
|
|
552
|
+
Get distinct values of a field from a MongoDB collection.
|
|
553
|
+
Example:
|
|
554
|
+
Example database:
|
|
555
|
+
{
|
|
556
|
+
'users': [
|
|
557
|
+
{'name': 'John', 'age': 25},
|
|
558
|
+
{'name': 'John', 'age': 30},
|
|
559
|
+
{'name': 'Alice', 'age': 25}
|
|
560
|
+
]
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
Get distinct values of the field 'name' from the collection 'users':
|
|
564
|
+
distinct('my_db', 'users', 'name')
|
|
565
|
+
|
|
566
|
+
Output:
|
|
567
|
+
['John', 'Alice']
|
|
568
|
+
|
|
569
|
+
:param database: String or the database object.
|
|
570
|
+
str - the name of the database. In this case the database object will be created.
|
|
571
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
572
|
+
:param collection_name: str, the name of the collection.
|
|
573
|
+
:param field_name: str, the name of the field.
|
|
574
|
+
:param query: dict, the query to search for.
|
|
575
|
+
If None, the query will not be executed.
|
|
576
|
+
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
577
|
+
If None, a new connection will be created to default URI.
|
|
578
|
+
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
579
|
+
|
|
580
|
+
:return: list, the list of distinct values.
|
|
581
|
+
"""
|
|
582
|
+
|
|
583
|
+
if not mongo_client:
|
|
584
|
+
mongo_client = connect()
|
|
585
|
+
close_client = True
|
|
586
|
+
|
|
587
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
588
|
+
collection = db[collection_name]
|
|
589
|
+
|
|
590
|
+
distinct_values = collection.distinct(field_name, query)
|
|
591
|
+
|
|
592
|
+
if close_client:
|
|
593
|
+
mongo_client.close()
|
|
594
|
+
|
|
595
|
+
return distinct_values
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
def count_entries_in_collection(
|
|
599
|
+
database: Union[str, pymongo.database.Database],
|
|
600
|
+
collection_name: str,
|
|
601
|
+
query: dict = None,
|
|
602
|
+
mongo_client: pymongo.MongoClient = None,
|
|
603
|
+
close_client: bool = False
|
|
604
|
+
) -> int:
|
|
605
|
+
"""
|
|
606
|
+
Count entries in a MongoDB collection by query.
|
|
607
|
+
|
|
608
|
+
:param database: String or the database object.
|
|
609
|
+
str - the name of the database. In this case the database object will be created.
|
|
610
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
611
|
+
:param collection_name: str, the name of the collection.
|
|
612
|
+
:param query: dict, the query to search for.
|
|
613
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
614
|
+
query = {'name': 'John'}
|
|
615
|
+
Example, return all entries from collection:
|
|
616
|
+
query = None
|
|
617
|
+
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
618
|
+
If None, a new connection will be created to default URI.
|
|
619
|
+
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
620
|
+
|
|
621
|
+
:return: int, the number of entries that match the query.
|
|
622
|
+
"""
|
|
623
|
+
|
|
624
|
+
if not mongo_client:
|
|
625
|
+
mongo_client = connect()
|
|
626
|
+
close_client = True
|
|
627
|
+
|
|
628
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
629
|
+
collection = db[collection_name]
|
|
630
|
+
|
|
631
|
+
if query is None:
|
|
632
|
+
query = {}
|
|
633
|
+
|
|
634
|
+
count = collection.count_documents(query)
|
|
635
|
+
|
|
636
|
+
if close_client:
|
|
637
|
+
mongo_client.close()
|
|
638
|
+
|
|
639
|
+
return count
|
|
640
|
+
|
|
641
|
+
|
|
159
642
|
def delete_all_entries_from_collection(
|
|
160
|
-
|
|
643
|
+
database: Union[str, pymongo.database.Database],
|
|
161
644
|
collection_name: str,
|
|
162
645
|
mongo_client: pymongo.MongoClient = None,
|
|
163
646
|
close_client: bool = False
|
|
164
647
|
):
|
|
165
648
|
"""
|
|
166
649
|
Remove all entries from a MongoDB collection.
|
|
167
|
-
:param
|
|
650
|
+
:param database: String or the database object.
|
|
651
|
+
str - the name of the database. In this case the database object will be created.
|
|
652
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
168
653
|
:param collection_name: str, the name of the collection.
|
|
169
654
|
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
170
655
|
If None, a new connection will be created to default URI.
|
|
@@ -177,7 +662,7 @@ def delete_all_entries_from_collection(
|
|
|
177
662
|
mongo_client = connect()
|
|
178
663
|
close_client = True
|
|
179
664
|
|
|
180
|
-
db = mongo_client
|
|
665
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
181
666
|
collection = db[collection_name]
|
|
182
667
|
|
|
183
668
|
collection.delete_many({})
|
|
@@ -188,7 +673,7 @@ def delete_all_entries_from_collection(
|
|
|
188
673
|
|
|
189
674
|
def overwrite_collection(
|
|
190
675
|
object_instance: list,
|
|
191
|
-
|
|
676
|
+
database: Union[str, pymongo.database.Database],
|
|
192
677
|
collection_name: str,
|
|
193
678
|
add_timestamp: bool = False,
|
|
194
679
|
convert_mixed_lists_to_strings: bool = False,
|
|
@@ -198,7 +683,9 @@ def overwrite_collection(
|
|
|
198
683
|
"""
|
|
199
684
|
Overwrite a MongoDB collection with list of dicts or a dict.
|
|
200
685
|
:param object_instance: list of dictionaries, the list of dictionaries to overwrite in the collection.
|
|
201
|
-
:param
|
|
686
|
+
:param database: String or the database object.
|
|
687
|
+
str - the name of the database. In this case the database object will be created.
|
|
688
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
202
689
|
:param collection_name: str, the name of the collection.
|
|
203
690
|
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
204
691
|
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are strings and integers,
|
|
@@ -217,13 +704,13 @@ def overwrite_collection(
|
|
|
217
704
|
close_client = True
|
|
218
705
|
|
|
219
706
|
delete_all_entries_from_collection(
|
|
220
|
-
|
|
707
|
+
database=database, collection_name=collection_name,
|
|
221
708
|
mongo_client=mongo_client
|
|
222
709
|
)
|
|
223
710
|
|
|
224
711
|
index(
|
|
225
712
|
object_instance=object_instance,
|
|
226
|
-
|
|
713
|
+
database=database, collection_name=collection_name,
|
|
227
714
|
add_timestamp=add_timestamp, convert_mixed_lists_to_strings=convert_mixed_lists_to_strings,
|
|
228
715
|
mongo_client=mongo_client, close_client=close_client)
|
|
229
716
|
|
|
@@ -242,15 +729,39 @@ def _is_object_list_of_dicts_or_dict(
|
|
|
242
729
|
raise ValueError("Object must be a dictionary or a list of dictionaries.")
|
|
243
730
|
|
|
244
731
|
|
|
732
|
+
def _get_pymongo_db_from_string_or_pymongo_db(
|
|
733
|
+
database: Union[str, pymongo.database.Database],
|
|
734
|
+
mongo_client: pymongo.MongoClient
|
|
735
|
+
) -> pymongo.database.Database:
|
|
736
|
+
"""
|
|
737
|
+
Get a pymongo.database.Database object from a string or a pymongo.database.Database object.
|
|
738
|
+
|
|
739
|
+
:param database: Union[str, pymongo.database.Database], the database object or the name of the database.
|
|
740
|
+
If the database is a string, the database object will be created.
|
|
741
|
+
If the database is a pymongo.database.Database object, it will be returned as is.
|
|
742
|
+
:param mongo_client: mongodb.MongoClient, the connection object.
|
|
743
|
+
:return: pymongo.database.Database, the database object.
|
|
744
|
+
"""
|
|
745
|
+
|
|
746
|
+
if isinstance(database, str):
|
|
747
|
+
return mongo_client[database]
|
|
748
|
+
elif isinstance(database, pymongo.database.Database):
|
|
749
|
+
return database
|
|
750
|
+
else:
|
|
751
|
+
raise ValueError("Database must be a string (database name) or a pymongo.database.Database object.")
|
|
752
|
+
|
|
753
|
+
|
|
245
754
|
def get_stats_db(
|
|
246
|
-
|
|
755
|
+
database: Union[str, pymongo.database.Database],
|
|
247
756
|
mongo_client: pymongo.MongoClient = None,
|
|
248
757
|
close_client: bool = False
|
|
249
758
|
):
|
|
250
759
|
"""
|
|
251
760
|
Get the stats of a MongoDB database.
|
|
252
761
|
|
|
253
|
-
:param
|
|
762
|
+
:param database: String or the database object.
|
|
763
|
+
str - the name of the database. In this case the database object will be created.
|
|
764
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
254
765
|
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
255
766
|
If None, a new connection will be created to default URI.
|
|
256
767
|
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
@@ -262,7 +773,7 @@ def get_stats_db(
|
|
|
262
773
|
mongo_client = connect()
|
|
263
774
|
close_client = True
|
|
264
775
|
|
|
265
|
-
db = mongo_client
|
|
776
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
266
777
|
|
|
267
778
|
stats = db.command("dbStats")
|
|
268
779
|
|
|
@@ -273,14 +784,16 @@ def get_stats_db(
|
|
|
273
784
|
|
|
274
785
|
|
|
275
786
|
def get_stats_db_size(
|
|
276
|
-
|
|
787
|
+
database: Union[str, pymongo.database.Database],
|
|
277
788
|
mongo_client: pymongo.MongoClient = None,
|
|
278
789
|
close_client: bool = False
|
|
279
790
|
):
|
|
280
791
|
"""
|
|
281
792
|
Get the size of a MongoDB database in bytes.
|
|
282
793
|
|
|
283
|
-
:param
|
|
794
|
+
:param database: String or the database object.
|
|
795
|
+
str - the name of the database. In this case the database object will be created.
|
|
796
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
284
797
|
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
285
798
|
If None, a new connection will be created to default URI.
|
|
286
799
|
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
@@ -289,6 +802,40 @@ def get_stats_db_size(
|
|
|
289
802
|
"""
|
|
290
803
|
|
|
291
804
|
stats = get_stats_db(
|
|
292
|
-
|
|
805
|
+
database=database, mongo_client=mongo_client, close_client=close_client)
|
|
293
806
|
|
|
294
807
|
return stats['dataSize']
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
def _convert_key_values_to_objects(
|
|
811
|
+
keys_convert_to_dict: list[str],
|
|
812
|
+
returned_data: Union[dict, list]
|
|
813
|
+
) -> Union[dict, list]:
|
|
814
|
+
"""
|
|
815
|
+
Recursively searches for provided keys from the 'keys_convert_to_dict' list like 'test1' and 'test2'
|
|
816
|
+
in a nested dictionary 'returned_data' and converts their values using "json.loads" if found.
|
|
817
|
+
|
|
818
|
+
:param keys_convert_to_dict: list, the keys of the documents that should be converted from string to dict.
|
|
819
|
+
:param returned_data: The nested dictionary to search through.
|
|
820
|
+
:type returned_data: dict
|
|
821
|
+
"""
|
|
822
|
+
|
|
823
|
+
if isinstance(returned_data, dict):
|
|
824
|
+
for key, value in returned_data.items():
|
|
825
|
+
if key in keys_convert_to_dict:
|
|
826
|
+
# Can be that the value is None, so we don't need to convert it.
|
|
827
|
+
if value is None:
|
|
828
|
+
continue
|
|
829
|
+
|
|
830
|
+
try:
|
|
831
|
+
returned_data[key] = json.loads(value)
|
|
832
|
+
except (ValueError, TypeError):
|
|
833
|
+
# This is needed only to know the possible exception types.
|
|
834
|
+
raise
|
|
835
|
+
else:
|
|
836
|
+
_convert_key_values_to_objects(keys_convert_to_dict, value)
|
|
837
|
+
elif isinstance(returned_data, list):
|
|
838
|
+
for i, item in enumerate(returned_data):
|
|
839
|
+
returned_data[i] = _convert_key_values_to_objects(keys_convert_to_dict, item)
|
|
840
|
+
|
|
841
|
+
return returned_data
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=ZX5xejuYVvRch1tJs02jeNOwNajL4QyvDzPyQpk4C7s,124
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
@@ -14,7 +14,7 @@ atomicshop/dns.py,sha256=J4yX6vCaRdL0McYWnlJ9arCDKW-yRui7Y5WyL5BoD6M,6391
|
|
|
14
14
|
atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
|
|
15
15
|
atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
|
|
16
16
|
atomicshop/file_types.py,sha256=-0jzQMRlmU1AP9DARjk-HJm1tVE22E6ngP2mRblyEjY,763
|
|
17
|
-
atomicshop/filesystem.py,sha256=
|
|
17
|
+
atomicshop/filesystem.py,sha256=XPrOjqxQRP3fa01QztDvuDUpiFjCYtpPUC0KhaGHxqs,60222
|
|
18
18
|
atomicshop/functions.py,sha256=pK8hoCE9z61PtWCxQJsda7YAphrLH1wxU5x-1QJP-sY,499
|
|
19
19
|
atomicshop/get_process_list.py,sha256=8cxb7gKe9sl4R6H2yMi8J6oe-RkonTvCdKjRFqi-Fs4,6075
|
|
20
20
|
atomicshop/get_process_name_cmd_dll.py,sha256=CtaSp3mgxxJKCCVW8BLx6BJNx4giCklU_T7USiCEwfc,5162
|
|
@@ -129,7 +129,7 @@ atomicshop/mitm/import_config.py,sha256=_nu8mgA-M4s6dZ8_QWx3x0aVb75upvsCuX_PIUg4
|
|
|
129
129
|
atomicshop/mitm/initialize_engines.py,sha256=kBG8TBnyFuwlJ1uKaWDzc5AiZNpwdvouq2pr-PYrdEA,8349
|
|
130
130
|
atomicshop/mitm/message.py,sha256=d_sm3O_aoZf87dDQP44xOMNEG-uZBN1ZecQgMCacbZs,1814
|
|
131
131
|
atomicshop/mitm/mitm_main.py,sha256=CdCv4nYt_jwd23AI14v6lC2H8SZeIZqsXjFhwq61UtM,21285
|
|
132
|
-
atomicshop/mitm/recs_files.py,sha256=
|
|
132
|
+
atomicshop/mitm/recs_files.py,sha256=B8fSuvYXlh50LWfwLRw_bYswreTjmdZLuHJzbDC5Gss,2930
|
|
133
133
|
atomicshop/mitm/shared_functions.py,sha256=hplm98tz8pgJ4WHUVI9sf_oVqUM2KJ1Y2pD6EFSb8P0,1879
|
|
134
134
|
atomicshop/mitm/statistic_analyzer.py,sha256=AzL9rQhg0tLJj33gZfxdwWghmbXGLh_HyMBDpzuBmsQ,24709
|
|
135
135
|
atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -250,11 +250,11 @@ atomicshop/wrappers/loggingw/formatters.py,sha256=7XUJvlB0CK4DCkEp8NTL0S0dkyrZD0
|
|
|
250
250
|
atomicshop/wrappers/loggingw/handlers.py,sha256=hAPFJQ-wFoNO8QzGrJRSvyuP09Q1F0Dl9_w7zzlgcW0,18155
|
|
251
251
|
atomicshop/wrappers/loggingw/loggers.py,sha256=QH5QainlGLyrDpsDu4T1C8-WQQau3JW2OS5RgC-kXpM,2677
|
|
252
252
|
atomicshop/wrappers/loggingw/loggingw.py,sha256=6HUn2z4ZW8PgakPscosKx23qYwHlBQcLiZGw-VZHi-k,12374
|
|
253
|
-
atomicshop/wrappers/loggingw/reading.py,sha256=
|
|
253
|
+
atomicshop/wrappers/loggingw/reading.py,sha256=ERBSiQbEksySKpXpu2E_6k9dZ6MPH95ZIsmdjWW9MUE,16436
|
|
254
254
|
atomicshop/wrappers/mongodbw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
255
255
|
atomicshop/wrappers/mongodbw/install_mongodb.py,sha256=3ZPqrXxj3lC-PnAKGXclylLuOqsbyXYeUpb5iGjdeUU,6626
|
|
256
|
-
atomicshop/wrappers/mongodbw/mongo_infra.py,sha256=
|
|
257
|
-
atomicshop/wrappers/mongodbw/mongodbw.py,sha256=
|
|
256
|
+
atomicshop/wrappers/mongodbw/mongo_infra.py,sha256=IjEF0jPzQz866MpTm7rnksnyyWQeUT_B2h2DA9ryAio,2034
|
|
257
|
+
atomicshop/wrappers/mongodbw/mongodbw.py,sha256=v_5YYgbgT0F-k2I-hDHQCMPhpry8OonsPclubJk2NG0,31509
|
|
258
258
|
atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
259
259
|
atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=QZg-R2iTQt7kFb8wNtnTmwraSGwvUs34JIasdbNa7ZU,5154
|
|
260
260
|
atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -309,8 +309,8 @@ atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0L
|
|
|
309
309
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=V_m1D0KpizQox3IEWp2AUcncwWy5kG25hbFrc-mBSJE,3029
|
|
310
310
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
311
311
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=bQ8Jql8bVGBJ0dt3VQ56lga_1LBOMLI3Km_otvvbU6c,7138
|
|
312
|
-
atomicshop-2.16.
|
|
313
|
-
atomicshop-2.16.
|
|
314
|
-
atomicshop-2.16.
|
|
315
|
-
atomicshop-2.16.
|
|
316
|
-
atomicshop-2.16.
|
|
312
|
+
atomicshop-2.16.19.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
313
|
+
atomicshop-2.16.19.dist-info/METADATA,sha256=rjqYESm2qP69gn_SoSyX0Ki4mxg4z4cvCJfuxC2xEcY,10473
|
|
314
|
+
atomicshop-2.16.19.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
315
|
+
atomicshop-2.16.19.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
316
|
+
atomicshop-2.16.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|