atomicshop 2.7.0__py3-none-any.whl → 2.7.2__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/python_file_patcher.py +34 -19
- atomicshop/wrappers/dockerw/dockerw.py +136 -2
- atomicshop/wrappers/factw/fact_extractor/docker_image.py +0 -1
- {atomicshop-2.7.0.dist-info → atomicshop-2.7.2.dist-info}/METADATA +1 -1
- {atomicshop-2.7.0.dist-info → atomicshop-2.7.2.dist-info}/RECORD +9 -9
- {atomicshop-2.7.0.dist-info → atomicshop-2.7.2.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.7.0.dist-info → atomicshop-2.7.2.dist-info}/WHEEL +0 -0
- {atomicshop-2.7.0.dist-info → atomicshop-2.7.2.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -4,9 +4,35 @@ from .file_io import file_io
|
|
|
4
4
|
from . import hashing
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
class FindAndReplaceInfo:
|
|
8
|
+
"""
|
|
9
|
+
This class is used to store information about the find and replace operation.
|
|
10
|
+
"""
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
find_what: str,
|
|
14
|
+
replace_to: str,
|
|
15
|
+
class_name: str = None,
|
|
16
|
+
function_name: str = None,
|
|
17
|
+
):
|
|
18
|
+
"""
|
|
19
|
+
:param find_what: string to find.
|
|
20
|
+
:param replace_to: string, replace to this string.
|
|
21
|
+
:param class_name: string name of the class to search in,
|
|
22
|
+
if the string to replace is not in a class, put 'None'.
|
|
23
|
+
:param function_name: string of the function name to search in,
|
|
24
|
+
if the string to replace is not in a function, put 'None'.
|
|
25
|
+
Also, if Class name and Function Name are both 'None', then it will search for the string in the whole file.
|
|
26
|
+
"""
|
|
27
|
+
self.find_what: str = find_what
|
|
28
|
+
self.replace_to: str = replace_to
|
|
29
|
+
self.class_name: str = class_name
|
|
30
|
+
self.function_name: str = function_name
|
|
31
|
+
|
|
32
|
+
|
|
7
33
|
def find_and_replace_in_file(
|
|
8
34
|
file_path: str,
|
|
9
|
-
find_and_replace_list: list[
|
|
35
|
+
find_and_replace_list: list[FindAndReplaceInfo],
|
|
10
36
|
encoding: str = None,
|
|
11
37
|
raise_if_more_than_one_string_found: bool = False,
|
|
12
38
|
raise_if_more_than_one_class_or_function_found: bool = False,
|
|
@@ -16,12 +42,7 @@ def find_and_replace_in_file(
|
|
|
16
42
|
Find and replace string in file.
|
|
17
43
|
|
|
18
44
|
:param file_path: String with full file path to read.
|
|
19
|
-
:param find_and_replace_list: list of
|
|
20
|
-
1: Class name, if the string to replace is not in a class, put 'None'.
|
|
21
|
-
2: Function name, if the string to replace is not in a function, put 'None'.
|
|
22
|
-
Also, if Class name and Function Name are both 'None', then it will search for the string in the whole file.
|
|
23
|
-
3: String to find.
|
|
24
|
-
4: String to replace to.
|
|
45
|
+
:param find_and_replace_list: list of FindAndReplaceInfo instances.
|
|
25
46
|
:param encoding: string, read the file with encoding. Example: 'utf-8'. 'None' is default, since it is default
|
|
26
47
|
in 'open()' function.
|
|
27
48
|
:param raise_if_more_than_one_string_found: Boolean, if True, the function will raise an error if more than one
|
|
@@ -48,22 +69,16 @@ def find_and_replace_in_file(
|
|
|
48
69
|
# Initialize the cache dictionary
|
|
49
70
|
block_lines_cache: dict = {}
|
|
50
71
|
|
|
51
|
-
for
|
|
52
|
-
|
|
53
|
-
find_function_name: str = single_find_replace[1]
|
|
54
|
-
find_what_string: str = single_find_replace[2]
|
|
55
|
-
replace_to: str = single_find_replace[3]
|
|
56
|
-
|
|
57
|
-
# list_of_blocks: list[tuple[int, int]] = list()
|
|
58
|
-
cache_key = (find_class_name, find_function_name)
|
|
72
|
+
for single_find in find_and_replace_list:
|
|
73
|
+
cache_key = (single_find.class_name, single_find.function_name)
|
|
59
74
|
if cache_key in block_lines_cache:
|
|
60
75
|
# Retrieve from cache
|
|
61
76
|
list_of_blocks = block_lines_cache[cache_key]
|
|
62
77
|
else:
|
|
63
78
|
# Use AST to find the start and end lines of the class or function.
|
|
64
|
-
if
|
|
79
|
+
if single_find.class_name is not None or single_find.function_name is not None:
|
|
65
80
|
list_of_blocks = astw.find_code_block(
|
|
66
|
-
file_path, class_name=
|
|
81
|
+
file_path, class_name=single_find.class_name, function_name=single_find.function_name)
|
|
67
82
|
if raise_if_more_than_one_class_or_function_found and len(list_of_blocks) > 1:
|
|
68
83
|
raise LookupError(f"More than one class or function was found in the file: {file_path}\n"
|
|
69
84
|
f"Nothing was changed.")
|
|
@@ -82,7 +97,7 @@ def find_and_replace_in_file(
|
|
|
82
97
|
found_string_indexes: list = list()
|
|
83
98
|
# for string_index, line in enumerate(file_data, start=start_line):
|
|
84
99
|
for string_index, line in enumerations.enumerate_from_start_to_end_index(file_data, start_line, end_line):
|
|
85
|
-
if
|
|
100
|
+
if single_find.find_what in line:
|
|
86
101
|
found_string_indexes.append(string_index)
|
|
87
102
|
|
|
88
103
|
if raise_if_more_than_one_string_found and len(found_string_indexes) > 1:
|
|
@@ -96,6 +111,6 @@ def find_and_replace_in_file(
|
|
|
96
111
|
|
|
97
112
|
# Replace the string.
|
|
98
113
|
for index in found_string_indexes:
|
|
99
|
-
file_data[index] = file_data[index].replace(
|
|
114
|
+
file_data[index] = file_data[index].replace(single_find.find_what, single_find.replace_to)
|
|
100
115
|
|
|
101
116
|
file_io.write_file(content=file_data, file_path=file_path, encoding=encoding, convert_list_to_string=True)
|
|
@@ -18,10 +18,11 @@ def get_images():
|
|
|
18
18
|
return images
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def remove_image(image_id_or_tag: str, print_kwargs: dict = None):
|
|
21
|
+
def remove_image(image_id_or_tag: str, force: bool = False, print_kwargs: dict = None):
|
|
22
22
|
"""
|
|
23
23
|
Remove an image from the local registry by providing the image id or tag.
|
|
24
24
|
:param image_id_or_tag: string, the image id or tag.
|
|
25
|
+
:param force: bool, force remove the image.
|
|
25
26
|
:param print_kwargs: dict, the print arguments.
|
|
26
27
|
:return:
|
|
27
28
|
"""
|
|
@@ -31,5 +32,138 @@ def remove_image(image_id_or_tag: str, print_kwargs: dict = None):
|
|
|
31
32
|
|
|
32
33
|
client = docker.from_env()
|
|
33
34
|
|
|
34
|
-
client.images.remove(image_id_or_tag)
|
|
35
|
+
client.images.remove(image_id_or_tag, force=force)
|
|
35
36
|
print_api(f"Removed Image {image_id_or_tag} successfully.", color='green', **print_kwargs)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ChangeImageByCommands(Exception):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ChangeImageByCallback(Exception):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def change_image_content(
|
|
48
|
+
image_id_or_name: str,
|
|
49
|
+
list_of_commands: list[str] = None,
|
|
50
|
+
print_kwargs: dict = None,
|
|
51
|
+
change_callback=None, *args, **kwargs):
|
|
52
|
+
"""
|
|
53
|
+
Change an image id or tag.
|
|
54
|
+
:param image_id_or_name: string, the image id or image tag name.
|
|
55
|
+
:param list_of_commands: list of strings, the commands to run in the docker container.
|
|
56
|
+
:param print_kwargs: dict, the print arguments.
|
|
57
|
+
:param change_callback: function callable, the function to change the image. The first argument of the function
|
|
58
|
+
must be the docker container object. The rest of the arguments are optional *args and **kwargs.
|
|
59
|
+
The function must return a tuple of (exit_code, output).
|
|
60
|
+
:return:
|
|
61
|
+
----------------------
|
|
62
|
+
Example usage by providing a list of commands:
|
|
63
|
+
from atomicshop.wrappers.dockerw import dockerw
|
|
64
|
+
dockerw.change_image_content(
|
|
65
|
+
image_id_or_name="your_docker_image_id_or_name",
|
|
66
|
+
list_of_commands=[
|
|
67
|
+
"apt-get update",
|
|
68
|
+
"apt-get install -y python3"
|
|
69
|
+
]
|
|
70
|
+
)
|
|
71
|
+
----------------------
|
|
72
|
+
Example usage by providing a command to update execution permissions of a file:
|
|
73
|
+
from atomicshop.wrappers.dockerw import dockerw
|
|
74
|
+
dockerw.change_image_content(
|
|
75
|
+
image_id_or_name="your_docker_image_id_or_name",
|
|
76
|
+
list_of_commands=[
|
|
77
|
+
"chmod +x /your_script.py"
|
|
78
|
+
]
|
|
79
|
+
)
|
|
80
|
+
----------------------
|
|
81
|
+
Example usage by providing a callback function:
|
|
82
|
+
from atomicshop.wrappers.dockerw import dockerw
|
|
83
|
+
dockerw.change_image_content(
|
|
84
|
+
image_id_or_name="your_docker_image_id_or_name",
|
|
85
|
+
change_callback=your_callback_function,
|
|
86
|
+
your_callback_function_args=(your_callback_function_arg1, your_callback_function_arg2),
|
|
87
|
+
your_callback_function_kwargs={'your_callback_function_kwarg1': your_callback_function_kwarg1}
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def your_callback_function(container, your_callback_function_arg1, your_callback_function_arg2,
|
|
91
|
+
your_callback_function_kwarg1=None):
|
|
92
|
+
# Do something with the container.
|
|
93
|
+
# Return a tuple of (exit_code, output).
|
|
94
|
+
return 0, b"Done"
|
|
95
|
+
----------------------
|
|
96
|
+
Example of providing callback function that change permissions of a file:
|
|
97
|
+
from atomicshop.wrappers.dockerw import dockerw
|
|
98
|
+
dockerw.change_image_content(
|
|
99
|
+
image_id_or_name="your_docker_image_id_or_name",
|
|
100
|
+
change_callback=change_permissions,
|
|
101
|
+
script_path="/your_python_script.py"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def change_permissions(container, script_path):
|
|
105
|
+
return container.exec_run(f"chmod +x {script_path}")
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
if not list_of_commands and not change_callback:
|
|
110
|
+
raise ValueError("Either list_of_commands or change_callback must be provided.")
|
|
111
|
+
|
|
112
|
+
if print_kwargs is None:
|
|
113
|
+
print_kwargs = {}
|
|
114
|
+
|
|
115
|
+
client = docker.from_env()
|
|
116
|
+
|
|
117
|
+
# Create and start a container from the existing image
|
|
118
|
+
container = client.containers.run(image_id_or_name, "/bin/bash", entrypoint="", detach=True, tty=True)
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
if list_of_commands:
|
|
122
|
+
# Execute the list of commands.
|
|
123
|
+
for command_index, command in enumerate(list_of_commands):
|
|
124
|
+
exit_code, output = container.exec_run(command)
|
|
125
|
+
if exit_code != 0:
|
|
126
|
+
raise ChangeImageByCommands(
|
|
127
|
+
f"Error in executing command [{command_index+1}]: {output.decode('utf-8')}")
|
|
128
|
+
|
|
129
|
+
if change_callback:
|
|
130
|
+
# Execute the callback function with additional arguments.
|
|
131
|
+
exit_code, output = change_callback(container, *args, **kwargs)
|
|
132
|
+
if exit_code != 0:
|
|
133
|
+
raise ChangeImageByCallback(f"Error in Updating image with callback function: {output.decode('utf-8')}")
|
|
134
|
+
|
|
135
|
+
# Commit the container
|
|
136
|
+
new_image = container.commit()
|
|
137
|
+
|
|
138
|
+
# Remove the original image
|
|
139
|
+
client.images.remove(image_id_or_name, force=True)
|
|
140
|
+
|
|
141
|
+
# Tag the new image with the original image's name
|
|
142
|
+
client.images.get(new_image.id).tag(image_id_or_name)
|
|
143
|
+
|
|
144
|
+
print_api(f"Updated image [{image_id_or_name}].", color='green', **print_kwargs)
|
|
145
|
+
|
|
146
|
+
finally:
|
|
147
|
+
# Clean up: Stop and remove the temporary container
|
|
148
|
+
container.stop()
|
|
149
|
+
container.remove()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def add_execution_permissions_for_file(image_id_or_name: str, file_path: str, print_kwargs: dict = None):
|
|
153
|
+
"""
|
|
154
|
+
Add execution permissions for a file inside docker image.
|
|
155
|
+
|
|
156
|
+
:param image_id_or_name: string, the image id or image tag name.
|
|
157
|
+
:param file_path: string, the path to the file.
|
|
158
|
+
:param print_kwargs: dict, the print arguments.
|
|
159
|
+
:return:
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
if print_kwargs is None:
|
|
163
|
+
print_kwargs = {}
|
|
164
|
+
|
|
165
|
+
change_image_content(
|
|
166
|
+
image_id_or_name=image_id_or_name,
|
|
167
|
+
list_of_commands=[f"chmod +x {file_path}"],
|
|
168
|
+
print_kwargs=print_kwargs
|
|
169
|
+
)
|
|
@@ -37,7 +37,6 @@ def create_docker_image_ubuntu(directory_path: str):
|
|
|
37
37
|
# There are 2 images:
|
|
38
38
|
# 'fkiecad/fact_extractor:latest' - The image that is downloaded.
|
|
39
39
|
# 'fact_extractor:latest' - The image that is built.
|
|
40
|
-
test = image.tags
|
|
41
40
|
for tag in image.tags:
|
|
42
41
|
if 'fact_extractor' in tag:
|
|
43
42
|
dockerw.remove_image(image_id_or_tag=image.id)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=TozzApCxU71SSLmjAZiCz1GbHRQyojy71z7Aqk7D41g,122
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
4
4
|
atomicshop/appointment_management.py,sha256=N3wVGJgrqJfsj_lqiRfaL3FxMEe57by5Stzanh189mk,7263
|
|
@@ -26,7 +26,7 @@ atomicshop/print_api.py,sha256=3n1CoiXvDcDGg00n5gEmQYInHryIhWbcpNjVobO1Gao,11468
|
|
|
26
26
|
atomicshop/process.py,sha256=5lqepm1psRbz66J4MB43ou6HHyac9F34QJedGukwAnk,14188
|
|
27
27
|
atomicshop/process_name_cmd.py,sha256=TNAK6kQZm5JKWzEW6QLqVHEG98ZLNDQiSS4YwDk8V8c,3830
|
|
28
28
|
atomicshop/process_poller.py,sha256=t79SwTX_4scH2WIH_ziw27aodG1ibhEFWbsVsmTyOVA,10846
|
|
29
|
-
atomicshop/python_file_patcher.py,sha256=
|
|
29
|
+
atomicshop/python_file_patcher.py,sha256=kd3rBWvTcosLEk-7TycNdfKW9fZbe161iVwmH4niUo0,5515
|
|
30
30
|
atomicshop/python_functions.py,sha256=zJg4ogUwECxrDD7xdDN5JikIUctITM5lsyabr_ZNsRw,4435
|
|
31
31
|
atomicshop/question_answer_engine.py,sha256=DuOn7QEgKKfqZu2cR8mVeFIfFgayfBHiW-jY2VPq_Fo,841
|
|
32
32
|
atomicshop/queues.py,sha256=Al0fdC3ZJmdKfv-PyBeIck9lnfLr82BYchvzr189gsI,640
|
|
@@ -149,7 +149,7 @@ atomicshop/wrappers/certauthw/certauth.py,sha256=hKedW0DOWlEigSNm8wu4SqHkCQsGJ1t
|
|
|
149
149
|
atomicshop/wrappers/certauthw/certauthw.py,sha256=4WvhjANI7Kzqrr_nKmtA8Kf7B6rute_5wfP65gwQrjw,8082
|
|
150
150
|
atomicshop/wrappers/ctyping/process_winapi.py,sha256=QcXL-ETtlSSkoT8F7pYle97ubGWsjYp8cx8HxkVMgAc,2762
|
|
151
151
|
atomicshop/wrappers/dockerw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
152
|
-
atomicshop/wrappers/dockerw/dockerw.py,sha256=
|
|
152
|
+
atomicshop/wrappers/dockerw/dockerw.py,sha256=w8zSJr5C7cbvbuG09ORCpAe0BOcibqqL_Z2EKEBHYK4,6266
|
|
153
153
|
atomicshop/wrappers/dockerw/install_docker.py,sha256=dpSOmD690oLukoLCo0u6Pzh5fRyCWBuSQEtG8VwC3jk,2765
|
|
154
154
|
atomicshop/wrappers/elasticsearchw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
155
155
|
atomicshop/wrappers/elasticsearchw/config_basic.py,sha256=nMtWYBlkQwzUMTLBaL3US8-f87bNPS_wzVxpLR1D6Hc,121
|
|
@@ -159,7 +159,7 @@ atomicshop/wrappers/factw/config_fact.py,sha256=J-K9Zn50WcDC7ubb-boraSZExfBk7a6M
|
|
|
159
159
|
atomicshop/wrappers/factw/config_install.py,sha256=QRygFnZ5r1ybJQl7ftFci3kNRmU-a-w3lMG1joElvcY,417
|
|
160
160
|
atomicshop/wrappers/factw/get_file_data.py,sha256=ChKC0OjgjFlNubZQBwcGhRO3L2pccc27RLRlAMIUix4,1641
|
|
161
161
|
atomicshop/wrappers/factw/fact_extractor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
162
|
-
atomicshop/wrappers/factw/fact_extractor/docker_image.py,sha256=
|
|
162
|
+
atomicshop/wrappers/factw/fact_extractor/docker_image.py,sha256=2wFzJd5iloXg5_bRDpaDpX_km8neTLuJgiqiEFQmgbk,2492
|
|
163
163
|
atomicshop/wrappers/factw/fact_extractor/get_extractor.py,sha256=2mfOAftHIlCcGt1s7MWdq7DsDCuI6wX3MtvcEZ4SK-0,756
|
|
164
164
|
atomicshop/wrappers/factw/install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
165
165
|
atomicshop/wrappers/factw/install/install_after_restart.py,sha256=Wixuc-foMA0qGjzypbbQ5sdE-F72yIKmrI9c6xwLY-g,1571
|
|
@@ -212,8 +212,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
|
|
|
212
212
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
|
|
213
213
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
|
|
214
214
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
|
|
215
|
-
atomicshop-2.7.
|
|
216
|
-
atomicshop-2.7.
|
|
217
|
-
atomicshop-2.7.
|
|
218
|
-
atomicshop-2.7.
|
|
219
|
-
atomicshop-2.7.
|
|
215
|
+
atomicshop-2.7.2.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
216
|
+
atomicshop-2.7.2.dist-info/METADATA,sha256=1Z5YAD-v2gwpnZxf7dCVNGdLRydjB5cHznkb7_TxQVA,10369
|
|
217
|
+
atomicshop-2.7.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
218
|
+
atomicshop-2.7.2.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
219
|
+
atomicshop-2.7.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|