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 CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.7.0'
4
+ __version__ = '2.7.2'
@@ -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[tuple[str, str, str, str]],
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 tuples. Each tuple has 4 strings.
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 single_find_replace in find_and_replace_list:
52
- find_class_name: str = single_find_replace[0]
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 find_class_name is not None or find_function_name is not None:
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=find_class_name, function_name=find_function_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 find_what_string in line:
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(find_what_string, replace_to)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.7.0
3
+ Version: 2.7.2
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=pI9HaUaffycFBm-uxjzPkctXsfbBrHNGXNLrGiv1Pv8,122
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=au12o_fkWS9j4Z0gI_Z2V1mfw2S2buj72F2Eh88d18Q,5077
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=8MZCMek6L-QpawO5hn_gxXczI6ustPGcYBFWNiuQ1cw,949
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=v6ZSG8lnagTwOWOcPszlNRqPWuCzXScuw72XEXAq8YU,2519
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.0.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
216
- atomicshop-2.7.0.dist-info/METADATA,sha256=b3_2bHYVrfgK6JoIvpAO-kuFenRKx8bRaE_Fu9je6Wg,10369
217
- atomicshop-2.7.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
218
- atomicshop-2.7.0.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
219
- atomicshop-2.7.0.dist-info/RECORD,,
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,,