atomicshop 2.16.33__py3-none-any.whl → 2.16.35__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/a_installs/ubuntu/mongodb.py +12 -0
- atomicshop/a_installs/ubuntu/pycharm.py +1 -0
- atomicshop/a_installs/win/mongodb.py +2 -2
- atomicshop/print_api.py +1 -1
- atomicshop/wrappers/loggingw/loggingw.py +23 -31
- atomicshop/wrappers/mongodbw/install_mongodb_ubuntu.py +100 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +297 -13
- atomicshop/wrappers/socketw/get_process.py +1 -9
- {atomicshop-2.16.33.dist-info → atomicshop-2.16.35.dist-info}/METADATA +1 -1
- {atomicshop-2.16.33.dist-info → atomicshop-2.16.35.dist-info}/RECORD +15 -13
- /atomicshop/wrappers/mongodbw/{install_mongodb.py → install_mongodb_win.py} +0 -0
- {atomicshop-2.16.33.dist-info → atomicshop-2.16.35.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.16.33.dist-info → atomicshop-2.16.35.dist-info}/WHEEL +0 -0
- {atomicshop-2.16.33.dist-info → atomicshop-2.16.35.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from atomicshop.wrappers.mongodbw import
|
|
1
|
+
from atomicshop.wrappers.mongodbw import install_mongodb_win
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def main():
|
|
5
|
-
|
|
5
|
+
install_mongodb_win.download_install_latest_main()
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
if __name__ == "__main__":
|
atomicshop/print_api.py
CHANGED
|
@@ -128,7 +128,7 @@ def print_api(
|
|
|
128
128
|
if print_end == '\n':
|
|
129
129
|
if stdcolor and color is not None:
|
|
130
130
|
# Use logger to output message.
|
|
131
|
-
with loggingw.
|
|
131
|
+
with loggingw.temporary_change_logger_stream_record_color(logger, color):
|
|
132
132
|
getattr(logger, logger_method)(message)
|
|
133
133
|
else:
|
|
134
134
|
# Use logger to output message.
|
|
@@ -5,7 +5,7 @@ import datetime
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import threading
|
|
7
7
|
|
|
8
|
-
from . import loggers, handlers
|
|
8
|
+
from . import loggers, handlers, filters
|
|
9
9
|
from ...file_io import csvs
|
|
10
10
|
from ...basics import tracebacks, ansi_escape_codes
|
|
11
11
|
from ... import print_api
|
|
@@ -308,10 +308,10 @@ def find_the_parent_logger_with_stream_handler(logger: logging.Logger) -> loggin
|
|
|
308
308
|
@contextlib.contextmanager
|
|
309
309
|
def _temporary_change_logger_stream_handler_color(logger: logging.Logger, color: str):
|
|
310
310
|
"""
|
|
311
|
-
THIS IS ONLY FOR REFERENCE
|
|
311
|
+
THIS IS ONLY FOR REFERENCE.
|
|
312
|
+
Better use 'temporary_change_logger_stream_record_color', since it is thread safe.
|
|
312
313
|
If there are several threads that use this logger, there could be a problem, since unwanted messages
|
|
313
|
-
could be colored with the color of the other thread.
|
|
314
|
-
safe and will color only the messages from the current thread.
|
|
314
|
+
could be colored with the color of the other thread.
|
|
315
315
|
|
|
316
316
|
Context manager to temporarily change the color of the logger's StreamHandler formatter.
|
|
317
317
|
|
|
@@ -351,13 +351,16 @@ def _temporary_change_logger_stream_handler_color(logger: logging.Logger, color:
|
|
|
351
351
|
# found_stream_handler.removeFilter(color_filter)
|
|
352
352
|
|
|
353
353
|
|
|
354
|
-
# Thread-local storage to store color codes per thread
|
|
355
|
-
thread_local = threading.local()
|
|
356
|
-
|
|
357
|
-
|
|
358
354
|
@contextlib.contextmanager
|
|
359
|
-
def
|
|
360
|
-
"""
|
|
355
|
+
def temporary_change_logger_stream_record_color(logger: logging.Logger, color: str):
|
|
356
|
+
"""
|
|
357
|
+
This function will temporarily change the color of the logger's StreamHandler record message.
|
|
358
|
+
|
|
359
|
+
Example:
|
|
360
|
+
with temporary_change_logger_stream_record_color(logger, "red"):
|
|
361
|
+
# Do something with the temporary color.
|
|
362
|
+
logger.error("This message will be colored with the 'red'.")
|
|
363
|
+
"""
|
|
361
364
|
|
|
362
365
|
# Find the current or the topmost logger's StreamHandler.
|
|
363
366
|
# Could be that it is a child logger inherits its handlers from the parent.
|
|
@@ -369,32 +372,21 @@ def temporary_change_logger_stream_handler_emit_color(logger: logging.Logger, co
|
|
|
369
372
|
found_stream_handler = handler
|
|
370
373
|
break
|
|
371
374
|
|
|
372
|
-
# Save the original
|
|
373
|
-
|
|
375
|
+
# Save the original state of the handler
|
|
376
|
+
# original_filters = found_stream_handler.filters.copy() # To restore the original filters
|
|
374
377
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if getattr(thread_local, 'color', None):
|
|
379
|
-
record.msg = (
|
|
380
|
-
ansi_escape_codes.get_colors_basic_dict(color) + original_msg +
|
|
381
|
-
ansi_escape_codes.ColorsBasic.END)
|
|
382
|
-
original_emit(record) # Call the original emit method
|
|
383
|
-
record.msg = original_msg # Restore the original message for other handlers
|
|
378
|
+
# Create a thread-specific color filter
|
|
379
|
+
thread_id = threading.get_ident()
|
|
380
|
+
color_filter = filters.ThreadColorLogFilter(color, thread_id)
|
|
384
381
|
|
|
385
|
-
#
|
|
386
|
-
found_stream_handler.
|
|
387
|
-
|
|
388
|
-
# Set the color code in thread-local storage for this thread
|
|
389
|
-
thread_local.color = color
|
|
382
|
+
# Add the filter to the handler
|
|
383
|
+
found_stream_handler.addFilter(color_filter)
|
|
390
384
|
|
|
391
385
|
try:
|
|
392
|
-
yield
|
|
386
|
+
yield # Do the logging within the context
|
|
393
387
|
finally:
|
|
394
|
-
# Restore the original
|
|
395
|
-
found_stream_handler.
|
|
396
|
-
# Clear the color code from thread-local storage
|
|
397
|
-
thread_local.color = None
|
|
388
|
+
# Restore the original filters, ensuring thread safety
|
|
389
|
+
found_stream_handler.removeFilter(color_filter)
|
|
398
390
|
|
|
399
391
|
|
|
400
392
|
class ExceptionCsvLogger:
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from ... import print_api, web
|
|
7
|
+
from .. import ubuntu_terminal
|
|
8
|
+
from ...permissions import ubuntu_permissions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
COMPASS_INSTALLATION_SCRIPT_URL: str = \
|
|
12
|
+
'https://raw.githubusercontent.com/mongodb/mongo/master/src/mongo/installer/compass/install_compass'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def run_command(command):
|
|
16
|
+
"""Run a system command and exit if the command fails."""
|
|
17
|
+
try:
|
|
18
|
+
subprocess.run(command, check=True, shell=True)
|
|
19
|
+
except subprocess.CalledProcessError as e:
|
|
20
|
+
print_api.print_api(f"Error: {e}", color='red')
|
|
21
|
+
sys.exit(1)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def install_mongodb(version):
|
|
25
|
+
"""Install the specified major version of MongoDB on Ubuntu."""
|
|
26
|
+
|
|
27
|
+
if not version.endswith(".0"):
|
|
28
|
+
version = f"{version}.0"
|
|
29
|
+
|
|
30
|
+
print_api.print_api(f"Installing MongoDB {version} on Ubuntu...")
|
|
31
|
+
print_api.print_api(f"Installing Prerequisites...")
|
|
32
|
+
ubuntu_terminal.update_system_packages()
|
|
33
|
+
ubuntu_terminal.install_packages(["wget", "curl", "gnupg"])
|
|
34
|
+
|
|
35
|
+
# Step 1: Import the MongoDB public GPG key
|
|
36
|
+
print_api.print_api("Step 1: Importing the MongoDB public GPG key...")
|
|
37
|
+
run_command(f"curl -fsSL https://pgp.mongodb.com/server-{version}.asc | "
|
|
38
|
+
f"sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-{version}.gpg")
|
|
39
|
+
|
|
40
|
+
# Step 2: Create the MongoDB list file for APT
|
|
41
|
+
print_api.print_api("Step 2: Creating MongoDB APT list file...")
|
|
42
|
+
distro_version = subprocess.check_output("lsb_release -sc", shell=True).decode('utf-8').strip()
|
|
43
|
+
run_command(
|
|
44
|
+
f"echo 'deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-{version}.gpg ] "
|
|
45
|
+
f"https://repo.mongodb.org/apt/ubuntu {distro_version}/mongodb-org/{version} multiverse' | "
|
|
46
|
+
f"sudo tee /etc/apt/sources.list.d/mongodb-org-{version}.list")
|
|
47
|
+
|
|
48
|
+
# Step 3: Update the APT package index
|
|
49
|
+
print_api.print_api("Step 3: Updating the APT package index...")
|
|
50
|
+
ubuntu_terminal.update_system_packages()
|
|
51
|
+
|
|
52
|
+
# Step 4: Install the latest version of MongoDB for the specified major version
|
|
53
|
+
print_api.print_api(f"Step 4: Installing MongoDB version {version}...")
|
|
54
|
+
ubuntu_terminal.install_packages(["mongodb-org"])
|
|
55
|
+
|
|
56
|
+
# Step 5: Start MongoDB service and enable it on startup
|
|
57
|
+
print_api.print_api("Step 5: Starting MongoDB service and enabling it on startup...")
|
|
58
|
+
ubuntu_terminal.start_enable_service_check_availability("mongod")
|
|
59
|
+
|
|
60
|
+
print_api.print_api(f"MongoDB {version} installation complete!", color='green')
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def install_main(
|
|
64
|
+
compass: bool = False,
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
Install the latest minor version of MongoDB Community Server on Ubuntu by providing the major version.
|
|
68
|
+
:param compass: bool, if True, MongoDB Compass will be installed.
|
|
69
|
+
:return:
|
|
70
|
+
"""
|
|
71
|
+
# Ensure the user provides a MongoDB major version as an argument.
|
|
72
|
+
if len(sys.argv) != 2:
|
|
73
|
+
message: str = ("Usage: python install_mongodb.py <mongo_major_version>\n"
|
|
74
|
+
"Example: python install_mongodb.py 7")
|
|
75
|
+
print_api.print_api(message, color='red')
|
|
76
|
+
return 1
|
|
77
|
+
|
|
78
|
+
mongo_version = sys.argv[1]
|
|
79
|
+
|
|
80
|
+
# Call the 'install' function with the major version.
|
|
81
|
+
install_mongodb(mongo_version)
|
|
82
|
+
|
|
83
|
+
if not compass:
|
|
84
|
+
return 0
|
|
85
|
+
|
|
86
|
+
# It doesn't matter what you do with the MSI it will not install Compass, only if you run it manually.
|
|
87
|
+
# So we will use installation script from their GitHub.
|
|
88
|
+
print_api.print_api("Downloading MongoDB Compass installation script...")
|
|
89
|
+
compass_script_path: str = web.download(COMPASS_INSTALLATION_SCRIPT_URL)
|
|
90
|
+
|
|
91
|
+
print_api.print_api("Installing MongoDB Compass from script...")
|
|
92
|
+
ubuntu_permissions.set_executable(compass_script_path)
|
|
93
|
+
run_command(f'sudo -E python3 {compass_script_path}')
|
|
94
|
+
|
|
95
|
+
# Clean up the installer file
|
|
96
|
+
if os.path.exists(compass_script_path):
|
|
97
|
+
os.remove(compass_script_path)
|
|
98
|
+
print_api.print_api("Cleaned up the Compass installer file.")
|
|
99
|
+
|
|
100
|
+
return 0
|
|
@@ -18,6 +18,18 @@ These are good examples to get you started, but can't really cover all the use c
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class MongoDBReplaceOneError(Exception):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MongoDBUpdateOneError(Exception):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class MongoDBUpdateManyError(Exception):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
21
33
|
class MongoDBWrapper:
|
|
22
34
|
def __init__(
|
|
23
35
|
self,
|
|
@@ -80,13 +92,15 @@ class MongoDBWrapper:
|
|
|
80
92
|
|
|
81
93
|
def delete(
|
|
82
94
|
self,
|
|
83
|
-
|
|
95
|
+
query_instance: Union[list[dict], dict],
|
|
84
96
|
collection_name: str
|
|
85
97
|
):
|
|
86
98
|
"""
|
|
87
|
-
Remove a list of dictionaries or a dictionary from a MongoDB collection.
|
|
99
|
+
Remove a dict or list of dictionaries or a dictionary from a MongoDB collection.
|
|
100
|
+
For pure mongo, this is the list of queries to remove.
|
|
101
|
+
Each query for a single item.
|
|
88
102
|
|
|
89
|
-
:param
|
|
103
|
+
:param query_instance: dict or list of dictionaries, the list of queries to remove from the collection.
|
|
90
104
|
:param collection_name: str, the name of the collection.
|
|
91
105
|
|
|
92
106
|
:return: None
|
|
@@ -95,7 +109,30 @@ class MongoDBWrapper:
|
|
|
95
109
|
self.connect()
|
|
96
110
|
|
|
97
111
|
delete(
|
|
98
|
-
|
|
112
|
+
query_instance=query_instance,
|
|
113
|
+
database=self.db, collection_name=collection_name,
|
|
114
|
+
mongo_client=self.client, close_client=False)
|
|
115
|
+
|
|
116
|
+
def delete_many(
|
|
117
|
+
self,
|
|
118
|
+
query: dict,
|
|
119
|
+
collection_name: str
|
|
120
|
+
):
|
|
121
|
+
"""
|
|
122
|
+
Remove all entries that match the query from a MongoDB collection.
|
|
123
|
+
|
|
124
|
+
:param query: dict, the query to search for.
|
|
125
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
126
|
+
query = {'name': 'John'}
|
|
127
|
+
:param collection_name: str, the name of the collection.
|
|
128
|
+
|
|
129
|
+
:return: result of the operation.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
self.connect()
|
|
133
|
+
|
|
134
|
+
return delete_many(
|
|
135
|
+
query=query,
|
|
99
136
|
database=self.db, collection_name=collection_name,
|
|
100
137
|
mongo_client=self.client, close_client=False)
|
|
101
138
|
|
|
@@ -203,6 +240,69 @@ class MongoDBWrapper:
|
|
|
203
240
|
|
|
204
241
|
return distinct_values
|
|
205
242
|
|
|
243
|
+
def update(
|
|
244
|
+
self,
|
|
245
|
+
collection_name: str,
|
|
246
|
+
query: dict,
|
|
247
|
+
update_instance: Union[dict, list[dict]],
|
|
248
|
+
add_timestamp: bool = False,
|
|
249
|
+
convert_mixed_lists_to_strings: bool = False
|
|
250
|
+
):
|
|
251
|
+
"""
|
|
252
|
+
Update one entry in a MongoDB collection by query.
|
|
253
|
+
:param collection_name: str, the name of the collection.
|
|
254
|
+
:param query: dict, the query to search for.
|
|
255
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
256
|
+
query = {'name': 'John'}
|
|
257
|
+
Find by Object id:
|
|
258
|
+
query = {'_id': ObjectId('5f3e3b3b4b9f3b3b4b9f3b3b')}
|
|
259
|
+
:param update_instance: dict or list of dicts, the update to apply.
|
|
260
|
+
Get examples for operators for each dict in the docstring of the function 'update' below.
|
|
261
|
+
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
262
|
+
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are
|
|
263
|
+
strings and integers, the integers will be converted to strings.
|
|
264
|
+
:return: result of the operation.
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
self.connect()
|
|
268
|
+
|
|
269
|
+
return update(
|
|
270
|
+
database=self.db, collection_name=collection_name,
|
|
271
|
+
query=query, update_instance=update_instance, add_timestamp=add_timestamp,
|
|
272
|
+
convert_mixed_lists_to_strings=convert_mixed_lists_to_strings,
|
|
273
|
+
mongo_client=self.client, close_client=False)
|
|
274
|
+
|
|
275
|
+
def replace(
|
|
276
|
+
self,
|
|
277
|
+
collection_name: str,
|
|
278
|
+
query: dict,
|
|
279
|
+
replacement: dict,
|
|
280
|
+
add_timestamp: bool = False,
|
|
281
|
+
convert_mixed_lists_to_strings: bool = False
|
|
282
|
+
):
|
|
283
|
+
"""
|
|
284
|
+
Replace one entry in a MongoDB collection by query.
|
|
285
|
+
:param collection_name: str, the name of the collection.
|
|
286
|
+
:param query: dict, the query to search for.
|
|
287
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
288
|
+
query = {'name': 'John'}
|
|
289
|
+
Find by Object id:
|
|
290
|
+
query = {'_id': ObjectId('5f3e3b3b4b9f3b3b4b9f3b3b')}
|
|
291
|
+
:param replacement: dict, the replacement to apply.
|
|
292
|
+
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
293
|
+
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are
|
|
294
|
+
|
|
295
|
+
:return: result of the operation.
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
self.connect()
|
|
299
|
+
|
|
300
|
+
return replace(
|
|
301
|
+
database=self.db, collection_name=collection_name,
|
|
302
|
+
query=query, replacement=replacement,
|
|
303
|
+
add_timestamp=add_timestamp, convert_mixed_lists_to_strings=convert_mixed_lists_to_strings,
|
|
304
|
+
mongo_client=self.client, close_client=False)
|
|
305
|
+
|
|
206
306
|
def count_entries_in_collection(
|
|
207
307
|
self,
|
|
208
308
|
collection_name: str,
|
|
@@ -328,7 +428,11 @@ def index(
|
|
|
328
428
|
collection = db[collection_name]
|
|
329
429
|
|
|
330
430
|
if convert_mixed_lists_to_strings:
|
|
331
|
-
|
|
431
|
+
if isinstance(object_instance, dict):
|
|
432
|
+
object_instance = dicts.convert_int_to_str_in_mixed_lists(object_instance)
|
|
433
|
+
elif isinstance(object_instance, list):
|
|
434
|
+
for doc_index, doc in enumerate(object_instance):
|
|
435
|
+
object_instance[doc_index] = dicts.convert_int_to_str_in_mixed_lists(doc)
|
|
332
436
|
|
|
333
437
|
if add_timestamp:
|
|
334
438
|
timestamp = datetime.datetime.now()
|
|
@@ -348,16 +452,18 @@ def index(
|
|
|
348
452
|
|
|
349
453
|
|
|
350
454
|
def delete(
|
|
351
|
-
|
|
455
|
+
query_instance: Union[list[dict], dict],
|
|
352
456
|
database: Union[str, pymongo.database.Database],
|
|
353
457
|
collection_name: str,
|
|
354
458
|
mongo_client: pymongo.MongoClient = None,
|
|
355
459
|
close_client: bool = False
|
|
356
460
|
):
|
|
357
461
|
"""
|
|
358
|
-
Remove a list of dictionaries or a dictionary from a MongoDB collection.
|
|
462
|
+
Remove a dict or list of dictionaries or a dictionary from a MongoDB collection.
|
|
359
463
|
|
|
360
|
-
:param
|
|
464
|
+
:param query_instance: list of dictionaries, the list of dictionaries to remove from the collection.
|
|
465
|
+
For pure mongo, this is the list of queries to remove.
|
|
466
|
+
Each query for a single item.
|
|
361
467
|
:param database: String or the database object.
|
|
362
468
|
str - the name of the database. In this case the database object will be created.
|
|
363
469
|
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
@@ -369,7 +475,7 @@ def delete(
|
|
|
369
475
|
:return: None
|
|
370
476
|
"""
|
|
371
477
|
|
|
372
|
-
_is_object_list_of_dicts_or_dict(
|
|
478
|
+
_is_object_list_of_dicts_or_dict(query_instance)
|
|
373
479
|
|
|
374
480
|
if not mongo_client:
|
|
375
481
|
mongo_client = connect()
|
|
@@ -378,16 +484,55 @@ def delete(
|
|
|
378
484
|
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
379
485
|
collection = db[collection_name]
|
|
380
486
|
|
|
381
|
-
if isinstance(
|
|
382
|
-
collection.delete_one(
|
|
383
|
-
elif isinstance(
|
|
384
|
-
for doc in
|
|
487
|
+
if isinstance(query_instance, dict):
|
|
488
|
+
collection.delete_one(query_instance)
|
|
489
|
+
elif isinstance(query_instance, list):
|
|
490
|
+
for doc in query_instance:
|
|
385
491
|
collection.delete_one(doc)
|
|
386
492
|
|
|
387
493
|
if close_client:
|
|
388
494
|
mongo_client.close()
|
|
389
495
|
|
|
390
496
|
|
|
497
|
+
def delete_many(
|
|
498
|
+
query: dict,
|
|
499
|
+
database: Union[str, pymongo.database.Database],
|
|
500
|
+
collection_name: str,
|
|
501
|
+
mongo_client: pymongo.MongoClient = None,
|
|
502
|
+
close_client: bool = False
|
|
503
|
+
):
|
|
504
|
+
"""
|
|
505
|
+
Remove all entries that match the query from a MongoDB collection.
|
|
506
|
+
|
|
507
|
+
:param query: dict, the query to search for.
|
|
508
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
509
|
+
query = {'name': 'John'}
|
|
510
|
+
:param database: String or the database object.
|
|
511
|
+
str - the name of the database. In this case the database object will be created.
|
|
512
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
513
|
+
:param collection_name: str, the name of the collection.
|
|
514
|
+
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
515
|
+
If None, a new connection will be created to default URI.
|
|
516
|
+
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
517
|
+
|
|
518
|
+
:return: result of the operation.
|
|
519
|
+
"""
|
|
520
|
+
|
|
521
|
+
if not mongo_client:
|
|
522
|
+
mongo_client = connect()
|
|
523
|
+
close_client = True
|
|
524
|
+
|
|
525
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
526
|
+
collection = db[collection_name]
|
|
527
|
+
|
|
528
|
+
result = collection.delete_many(query)
|
|
529
|
+
|
|
530
|
+
if close_client:
|
|
531
|
+
mongo_client.close()
|
|
532
|
+
|
|
533
|
+
return result
|
|
534
|
+
|
|
535
|
+
|
|
391
536
|
def find(
|
|
392
537
|
database: Union[str, pymongo.database.Database],
|
|
393
538
|
collection_name: str,
|
|
@@ -614,6 +759,145 @@ def distinct(
|
|
|
614
759
|
return distinct_values
|
|
615
760
|
|
|
616
761
|
|
|
762
|
+
def update(
|
|
763
|
+
database: Union[str, pymongo.database.Database],
|
|
764
|
+
collection_name: str,
|
|
765
|
+
query: dict,
|
|
766
|
+
update_instance: Union[dict, list[dict]],
|
|
767
|
+
add_timestamp: bool = False,
|
|
768
|
+
convert_mixed_lists_to_strings: bool = False,
|
|
769
|
+
mongo_client: pymongo.MongoClient = None,
|
|
770
|
+
close_client: bool = False
|
|
771
|
+
):
|
|
772
|
+
"""
|
|
773
|
+
Update one entry in a MongoDB collection by query.
|
|
774
|
+
:param database: String or the database object.
|
|
775
|
+
str - the name of the database. In this case the database object will be created.
|
|
776
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
777
|
+
:param collection_name: str, the name of the collection.
|
|
778
|
+
:param query: dict, the query to search for.
|
|
779
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
780
|
+
query = {'name': 'John'}
|
|
781
|
+
Find by Object id:
|
|
782
|
+
query = {'_id': ObjectId('5f3e3b3b4b9f3b3b4b9f3b3b')}
|
|
783
|
+
:param update_instance: dict or list of dicts, the update to apply.
|
|
784
|
+
If dict, the update will be applied to one entry using 'update_one'.
|
|
785
|
+
If list of dicts, the update will be applied to multiple entries using 'update_many'.
|
|
786
|
+
|
|
787
|
+
Examples for operators for each dict:
|
|
788
|
+
$set: update the column 'name' to 'Alice':
|
|
789
|
+
update_instance = {'$set': {'name': 'Alice'}}
|
|
790
|
+
$inc: increment the column 'age' by 1:
|
|
791
|
+
update_instance = {'$inc': {'age': 1}}
|
|
792
|
+
$unset: remove the column 'name':
|
|
793
|
+
update_instance = {'$unset': {'name': ''}}
|
|
794
|
+
$push: add a value to the list 'hobbies':
|
|
795
|
+
update_instance = {'$push': {'hobbies': 'swimming'}}
|
|
796
|
+
$pull: remove a value from the list 'hobbies':
|
|
797
|
+
update_instance = {'$pull': {'hobbies': 'swimming'}}
|
|
798
|
+
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
799
|
+
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are
|
|
800
|
+
strings and integers, the integers will be converted to strings.
|
|
801
|
+
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
802
|
+
If None, a new connection will be created to default URI.
|
|
803
|
+
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
804
|
+
|
|
805
|
+
:return: None
|
|
806
|
+
"""
|
|
807
|
+
|
|
808
|
+
if not mongo_client:
|
|
809
|
+
mongo_client = connect()
|
|
810
|
+
close_client = True
|
|
811
|
+
|
|
812
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
813
|
+
collection = db[collection_name]
|
|
814
|
+
|
|
815
|
+
if convert_mixed_lists_to_strings:
|
|
816
|
+
if isinstance(update_instance, dict):
|
|
817
|
+
object_instance = dicts.convert_int_to_str_in_mixed_lists(update_instance)
|
|
818
|
+
elif isinstance(update_instance, list):
|
|
819
|
+
for doc_index, doc in enumerate(update_instance):
|
|
820
|
+
update_instance[doc_index] = dicts.convert_int_to_str_in_mixed_lists(doc)
|
|
821
|
+
|
|
822
|
+
if add_timestamp:
|
|
823
|
+
timestamp = datetime.datetime.now()
|
|
824
|
+
if isinstance(update_instance, dict):
|
|
825
|
+
update_instance['timestamp'] = timestamp
|
|
826
|
+
elif isinstance(update_instance, list):
|
|
827
|
+
for doc in update_instance:
|
|
828
|
+
doc['timestamp'] = timestamp
|
|
829
|
+
|
|
830
|
+
result = None
|
|
831
|
+
if isinstance(update_instance, dict):
|
|
832
|
+
result = collection.update_one(query, update_instance)
|
|
833
|
+
elif isinstance(update_instance, list):
|
|
834
|
+
result = collection.update_many(query, update_instance)
|
|
835
|
+
|
|
836
|
+
if result.matched_count == 0:
|
|
837
|
+
raise MongoDBUpdateOneError("No document found to update.")
|
|
838
|
+
|
|
839
|
+
if close_client:
|
|
840
|
+
mongo_client.close()
|
|
841
|
+
|
|
842
|
+
return result
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
def replace(
|
|
846
|
+
database: Union[str, pymongo.database.Database],
|
|
847
|
+
collection_name: str,
|
|
848
|
+
query: dict,
|
|
849
|
+
replacement: dict,
|
|
850
|
+
add_timestamp: bool = False,
|
|
851
|
+
convert_mixed_lists_to_strings: bool = False,
|
|
852
|
+
mongo_client: pymongo.MongoClient = None,
|
|
853
|
+
close_client: bool = False
|
|
854
|
+
):
|
|
855
|
+
"""
|
|
856
|
+
Replace one entry in a MongoDB collection by query.
|
|
857
|
+
:param database: String or the database object.
|
|
858
|
+
str - the name of the database. In this case the database object will be created.
|
|
859
|
+
pymongo.database.Database - the database object that will be used instead of creating a new one.
|
|
860
|
+
:param collection_name: str, the name of the collection.
|
|
861
|
+
:param query: dict, the query to search for.
|
|
862
|
+
Example, search for all entries with column name 'name' equal to 'John':
|
|
863
|
+
query = {'name': 'John'}
|
|
864
|
+
Find by Object id:
|
|
865
|
+
query = {'_id': ObjectId('5f3e3b3b4b9f3b3b4b9f3b3b')}
|
|
866
|
+
:param replacement: dict, the replacement to apply.
|
|
867
|
+
:param add_timestamp: bool, if True, a current time timestamp will be added to the object.
|
|
868
|
+
:param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are strings and integers,
|
|
869
|
+
the integers will be converted to strings.
|
|
870
|
+
:param mongo_client: pymongo.MongoClient, the connection object.
|
|
871
|
+
If None, a new connection will be created to default URI.
|
|
872
|
+
:param close_client: bool, if True, the connection will be closed after the operation.
|
|
873
|
+
|
|
874
|
+
:return: None
|
|
875
|
+
"""
|
|
876
|
+
|
|
877
|
+
if not mongo_client:
|
|
878
|
+
mongo_client = connect()
|
|
879
|
+
close_client = True
|
|
880
|
+
|
|
881
|
+
db = _get_pymongo_db_from_string_or_pymongo_db(database, mongo_client)
|
|
882
|
+
collection = db[collection_name]
|
|
883
|
+
|
|
884
|
+
if convert_mixed_lists_to_strings:
|
|
885
|
+
replacement = dicts.convert_int_to_str_in_mixed_lists(replacement)
|
|
886
|
+
|
|
887
|
+
if add_timestamp:
|
|
888
|
+
timestamp = datetime.datetime.now()
|
|
889
|
+
replacement['timestamp'] = timestamp
|
|
890
|
+
|
|
891
|
+
result = collection.replace_one(query, replacement)
|
|
892
|
+
if result.matched_count == 0:
|
|
893
|
+
raise MongoDBReplaceOneError("No document found to replace.")
|
|
894
|
+
|
|
895
|
+
if close_client:
|
|
896
|
+
mongo_client.close()
|
|
897
|
+
|
|
898
|
+
return result
|
|
899
|
+
|
|
900
|
+
|
|
617
901
|
def count_entries_in_collection(
|
|
618
902
|
database: Union[str, pymongo.database.Database],
|
|
619
903
|
collection_name: str,
|
|
@@ -73,20 +73,12 @@ class GetCommandLine:
|
|
|
73
73
|
print_api(
|
|
74
74
|
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
75
75
|
**print_kwargs)
|
|
76
|
-
pass
|
|
77
76
|
except psutil.AccessDenied:
|
|
78
77
|
execution_error = f"Access Denied for 'psutil' to read system process command line. " \
|
|
79
78
|
f"Run script with Admin Rights."
|
|
80
79
|
print_api(
|
|
81
80
|
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
82
81
|
**print_kwargs)
|
|
83
|
-
pass
|
|
84
|
-
except Exception:
|
|
85
|
-
execution_error = "There was undocumented exception in localhost script execution."
|
|
86
|
-
print_api(
|
|
87
|
-
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
88
|
-
**print_kwargs)
|
|
89
|
-
pass
|
|
90
82
|
|
|
91
83
|
if not execution_error:
|
|
92
84
|
# Reading the buffer.
|
|
@@ -97,8 +89,8 @@ class GetCommandLine:
|
|
|
97
89
|
|
|
98
90
|
return process_name
|
|
99
91
|
|
|
92
|
+
@staticmethod
|
|
100
93
|
def get_commandline_and_error(
|
|
101
|
-
self,
|
|
102
94
|
execution_output,
|
|
103
95
|
execution_error,
|
|
104
96
|
print_kwargs: dict = None
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=UtKTcWqPrVHpu6j_BPCWMmIdo2RCZbCRac7Es1CoDwI,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
|
|
@@ -25,7 +25,7 @@ atomicshop/ip_addresses.py,sha256=Hvi4TumEFoTEpKWaq5WNF-YzcRzt24IxmNgv-Mgax1s,11
|
|
|
25
25
|
atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,452
|
|
26
26
|
atomicshop/on_exit.py,sha256=Rpg2SaF0aginuO7JYwA49YJYnS8F6K2jUqhjH65WzuU,6889
|
|
27
27
|
atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
|
|
28
|
-
atomicshop/print_api.py,sha256=
|
|
28
|
+
atomicshop/print_api.py,sha256=q9dAQCASk3pHp_PtYIpr6iZmRcW_lvrV_gPPNwTMRsw,11152
|
|
29
29
|
atomicshop/process.py,sha256=PeLvyixXaCfftdUF3oMbohI1L4MdLtvQVDx2V1Tz_Rk,16662
|
|
30
30
|
atomicshop/python_file_patcher.py,sha256=-uhbUX-um5k-If_XXuOfCr8wMzZ3QE6h9N8xGWw6W_o,5486
|
|
31
31
|
atomicshop/python_functions.py,sha256=zJg4ogUwECxrDD7xdDN5JikIUctITM5lsyabr_ZNsRw,4435
|
|
@@ -48,9 +48,10 @@ atomicshop/web.py,sha256=DkpdUYiwRu_Du5J8LlUyxLj-NAEnDLfEwfVlSI22trM,11642
|
|
|
48
48
|
atomicshop/a_installs/ubuntu/docker_rootless.py,sha256=9IPNtGZYjfy1_n6ZRt7gWz9KZgR6XCgevjqq02xk-o0,281
|
|
49
49
|
atomicshop/a_installs/ubuntu/docker_sudo.py,sha256=JzayxeyKDtiuT4Icp2L2LyFRbx4wvpyN_bHLfZ-yX5E,281
|
|
50
50
|
atomicshop/a_installs/ubuntu/elastic_search_and_kibana.py,sha256=yRB-l1zBxdiN6av-FwNkhcBlaeu4zrDPjQ0uPGgpK2I,244
|
|
51
|
-
atomicshop/a_installs/ubuntu/
|
|
51
|
+
atomicshop/a_installs/ubuntu/mongodb.py,sha256=xuRJS1qqOZ0EZp7of5R3tTjSu6CwBIxYg8-NaM7othE,230
|
|
52
|
+
atomicshop/a_installs/ubuntu/pycharm.py,sha256=Ld7YQBwPxrjuZcTG1K4kZqjbBdt8aooCVRa15u5FOmE,157
|
|
52
53
|
atomicshop/a_installs/win/fibratus.py,sha256=TU4e9gdZ_zI73C40uueJ59pD3qmN-UFGdX5GFoVf6cM,179
|
|
53
|
-
atomicshop/a_installs/win/mongodb.py,sha256=
|
|
54
|
+
atomicshop/a_installs/win/mongodb.py,sha256=AqyItXu19aaoe49pppDxtEkXey6PMy0PoT2Y_RmPpPE,179
|
|
54
55
|
atomicshop/a_installs/win/pycharm.py,sha256=j_RSd7aDOyC3yDd-_GUTMLlQTmDrqtVFG--oUfGLiZk,140
|
|
55
56
|
atomicshop/a_installs/win/wsl_ubuntu_lts.py,sha256=dZbPRLNKFeMd6MotjkE6UDY9cOiIaaclIdR1kGYWI50,139
|
|
56
57
|
atomicshop/a_mains/dns_gateway_setting.py,sha256=ncc2rFQCChxlNP59UshwmTonLqC6MWblrVAzbbz-13M,149
|
|
@@ -250,12 +251,13 @@ atomicshop/wrappers/loggingw/filters.py,sha256=48UVhJHemCS0agXmQP8dHvAHM8r9DFphJ
|
|
|
250
251
|
atomicshop/wrappers/loggingw/formatters.py,sha256=ZY12IokVY1G_Wzn2Zlv9qjK-e8CtIK6yUgUfPHvH2BU,5802
|
|
251
252
|
atomicshop/wrappers/loggingw/handlers.py,sha256=vxaSSnlJGs9NKJvYROKtNjaFTqePdHy0sz-GwN5aNPw,19035
|
|
252
253
|
atomicshop/wrappers/loggingw/loggers.py,sha256=mmM__XR3W4QC82wbsDRG_M4_0JYGGEP0Qn0WCOSp-go,2910
|
|
253
|
-
atomicshop/wrappers/loggingw/loggingw.py,sha256=
|
|
254
|
+
atomicshop/wrappers/loggingw/loggingw.py,sha256=uLY7DJS-3xIYQBRvI--9eFvdcnvsWSXmtJKS-gTRfjM,20863
|
|
254
255
|
atomicshop/wrappers/loggingw/reading.py,sha256=sCNlgqLNH5XdKqOOjjEox7CvViMHzs6h7-hwCnx4NKk,17566
|
|
255
256
|
atomicshop/wrappers/mongodbw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
256
|
-
atomicshop/wrappers/mongodbw/
|
|
257
|
+
atomicshop/wrappers/mongodbw/install_mongodb_ubuntu.py,sha256=pmI9AwWJ2cv5h8GionSpSJkllg6kfp0M381pk6y4Y5U,4015
|
|
258
|
+
atomicshop/wrappers/mongodbw/install_mongodb_win.py,sha256=3ZPqrXxj3lC-PnAKGXclylLuOqsbyXYeUpb5iGjdeUU,6626
|
|
257
259
|
atomicshop/wrappers/mongodbw/mongo_infra.py,sha256=IjEF0jPzQz866MpTm7rnksnyyWQeUT_B2h2DA9ryAio,2034
|
|
258
|
-
atomicshop/wrappers/mongodbw/mongodbw.py,sha256=
|
|
260
|
+
atomicshop/wrappers/mongodbw/mongodbw.py,sha256=DlKiZaB__OIkWNQgQxKD569qrzm1l7m1TWKH2NTe8qs,44278
|
|
259
261
|
atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
260
262
|
atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=TKGa3jSlSqZTL2NA0nMkWDFtlkz7rxGGn44ywCg7MN8,5228
|
|
261
263
|
atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -299,7 +301,7 @@ atomicshop/wrappers/socketw/certificator.py,sha256=3CpQKtcW68FSbH6LVSEZTqWBS6Yg_
|
|
|
299
301
|
atomicshop/wrappers/socketw/creator.py,sha256=3_OraDkw2DAWZfoSdY3svCGMOIxpjLEEY7NxWd7M5P4,9873
|
|
300
302
|
atomicshop/wrappers/socketw/dns_server.py,sha256=VHV6s7vd0zqqW3dhE6li-260YRzmEB5ZUXqYJ9p0vVA,49069
|
|
301
303
|
atomicshop/wrappers/socketw/exception_wrapper.py,sha256=B-X5SHLSUIWToihH2MKnOB1F4A81_X0DpLLfnYKYbEc,7067
|
|
302
|
-
atomicshop/wrappers/socketw/get_process.py,sha256=
|
|
304
|
+
atomicshop/wrappers/socketw/get_process.py,sha256=aJC-_qFUv3NgWCSUzDI72E4z8_-VTZE9NVZ0CwUoNlM,5698
|
|
303
305
|
atomicshop/wrappers/socketw/receiver.py,sha256=XVvWOoeCo3vA0O5p19ryi-hcDIyx382WNG7WzMNVeYk,9322
|
|
304
306
|
atomicshop/wrappers/socketw/sender.py,sha256=5HPrgTS2pA1g-jbG1TUtR7drHT1Z_8UevlRCTwW7dgY,5007
|
|
305
307
|
atomicshop/wrappers/socketw/sni.py,sha256=J1kPnQ77XwKN1pO5aOI1c_VfhuivCm95OOaQxMpPuZ0,17627
|
|
@@ -310,8 +312,8 @@ atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0L
|
|
|
310
312
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=w1AH-zf4mBuT4euf28UKij9ihM-b1BRU9Qfby0QDdqI,2957
|
|
311
313
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
312
314
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=bQ8Jql8bVGBJ0dt3VQ56lga_1LBOMLI3Km_otvvbU6c,7138
|
|
313
|
-
atomicshop-2.16.
|
|
314
|
-
atomicshop-2.16.
|
|
315
|
-
atomicshop-2.16.
|
|
316
|
-
atomicshop-2.16.
|
|
317
|
-
atomicshop-2.16.
|
|
315
|
+
atomicshop-2.16.35.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
316
|
+
atomicshop-2.16.35.dist-info/METADATA,sha256=Dbczjg5jtonq5G-BaD0Hqj93hiHQhsodw5FN3Ytv6UM,10473
|
|
317
|
+
atomicshop-2.16.35.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
318
|
+
atomicshop-2.16.35.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
319
|
+
atomicshop-2.16.35.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|