holado 0.6.2__py3-none-any.whl → 0.6.3__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 holado might be problematic. Click here for more details.
- holado/common/handlers/object.py +15 -1
- {holado-0.6.2.dist-info → holado-0.6.3.dist-info}/METADATA +1 -1
- {holado-0.6.2.dist-info → holado-0.6.3.dist-info}/RECORD +7 -7
- holado_docker/sdk/docker/docker_client.py +26 -22
- holado_multitask/multithreading/functionthreaded.py +11 -5
- {holado-0.6.2.dist-info → holado-0.6.3.dist-info}/WHEEL +0 -0
- {holado-0.6.2.dist-info → holado-0.6.3.dist-info}/licenses/LICENSE +0 -0
holado/common/handlers/object.py
CHANGED
|
@@ -62,9 +62,20 @@ class DeleteableObject(Object):
|
|
|
62
62
|
|
|
63
63
|
self.__on_delete_funcs = []
|
|
64
64
|
self.__on_delete_gc_collect = False
|
|
65
|
+
self.__is_deleteable = True
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def _is_deleteable(self):
|
|
69
|
+
return self.__is_deleteable
|
|
70
|
+
|
|
71
|
+
@_is_deleteable.setter
|
|
72
|
+
def _is_deleteable(self, is_deleteable):
|
|
73
|
+
self.__is_deleteable = is_deleteable
|
|
65
74
|
|
|
66
75
|
def __del__(self):
|
|
67
76
|
try:
|
|
77
|
+
if not self._is_deleteable:
|
|
78
|
+
return
|
|
68
79
|
if self.object_state in [ObjectStates.Deleting, ObjectStates.Deleted]:
|
|
69
80
|
return
|
|
70
81
|
|
|
@@ -83,7 +94,8 @@ class DeleteableObject(Object):
|
|
|
83
94
|
self.__delete()
|
|
84
95
|
else:
|
|
85
96
|
from holado_multitask.multithreading.functionthreaded import FunctionThreaded
|
|
86
|
-
func = FunctionThreaded(self.__delete, name=f"delete object '{self.name}'", register_thread=False)
|
|
97
|
+
func = FunctionThreaded(self.__delete, name=f"delete object '{self.name}'", register_thread=False, do_log=False)
|
|
98
|
+
func._is_deleteable = False # Deactivate deletion mechanism of DeleteableObject to avoid an infinite loop
|
|
87
99
|
func.start()
|
|
88
100
|
func.join(timeout=30, raise_if_still_alive=False) # timeout of 30s to limit deadlock impact ; raise to False since exceptions are omitted in gc collect context
|
|
89
101
|
except AttributeError as exc:
|
|
@@ -124,6 +136,8 @@ class DeleteableObject(Object):
|
|
|
124
136
|
from holado_core.common.tools.tools import Tools
|
|
125
137
|
from holado_python.standard_library.typing import Typing
|
|
126
138
|
|
|
139
|
+
if not self._is_deleteable:
|
|
140
|
+
return
|
|
127
141
|
if self.object_state in [ObjectStates.Deleting, ObjectStates.Deleted]:
|
|
128
142
|
return False
|
|
129
143
|
|
|
@@ -7,7 +7,7 @@ holado/common/context/service_manager.py,sha256=LaCn8ukE1aqJynmwoexAYj5hCkdb_F3h
|
|
|
7
7
|
holado/common/context/session_context.py,sha256=eIcq3AfS1zQLzd2ud6n2T-p8Z6I-WThCmhFFSb22O70,22770
|
|
8
8
|
holado/common/handlers/__init__.py,sha256=d0KDUpaAAw1eBXyX08gaRh4RECnJlXjYQ0TcU-Ndicc,1372
|
|
9
9
|
holado/common/handlers/enums.py,sha256=ieqKVoukEiNyfE3KrKmMOImdbFS1ocUMud8JHe2xNLs,1662
|
|
10
|
-
holado/common/handlers/object.py,sha256=
|
|
10
|
+
holado/common/handlers/object.py,sha256=rDaav8zHTYfKVEaLtEdeXMxYXATGVcs2a7um1f5MvCs,7205
|
|
11
11
|
holado/common/handlers/undefined.py,sha256=yXZRPIDZI8R0vT4kdf87JPkFhnltLcQwwc3zmKhmv30,2529
|
|
12
12
|
holado/common/tools/__init__.py,sha256=z-T6zX_tOVkJjniTDA0KSKmdtosjfEhjaNa1-3g8wTs,1374
|
|
13
13
|
holado/common/tools/gc_manager.py,sha256=TjQg7MisGRhxuiQ22hB3IuqNhnWCVEWpU253-rOjR0w,7611
|
|
@@ -185,7 +185,7 @@ holado_django/server/django_projects/rest_api/rest_api/application/migrations/__
|
|
|
185
185
|
holado_django/tests/behave/steps/__init__.py,sha256=1x7ID0w53eDe1P-n4Y5XOnLOTg_bta54gZE2YI0-IHo,1281
|
|
186
186
|
holado_django/tests/behave/steps/django_server_steps.py,sha256=XAnKDUXJxsZ4L7-PYatjevh2BT3qdKIg5sXXG5Y3QFQ,3819
|
|
187
187
|
holado_docker/__init__.py,sha256=CtGYR7aEkaCdAHPDAsu_ErjpVtYE0yz9wbgbfRUwS8s,1574
|
|
188
|
-
holado_docker/sdk/docker/docker_client.py,sha256=
|
|
188
|
+
holado_docker/sdk/docker/docker_client.py,sha256=rh1VLtcefIAZY88FMz7eyh1mFrWn3vVxop6TlC9t2sU,14138
|
|
189
189
|
holado_docker/sdk/docker/docker_service.py,sha256=SvMSIZ7XTCbC7q5rur03lJhJVSHL3uIq1dBQz9oDpkw,3767
|
|
190
190
|
holado_docker/tests/behave/steps/__init__.py,sha256=lrP0btKLA3qQD2wp3zbOp0ug8RmgpaYWCrOAWehcPiI,1298
|
|
191
191
|
holado_docker/tests/behave/steps/tools/docker_controller/client_steps.py,sha256=hgns0Kyl38jJlZsVpMtEWlQKfga815BfJRFS_JhQvWc,4438
|
|
@@ -265,7 +265,7 @@ holado_multitask/multiprocessing/processesmanager.py,sha256=WCWD-Zo5adBNKz-X34Vh
|
|
|
265
265
|
holado_multitask/multiprocessing/context/process_context.py,sha256=UADxmma8f5tW6etJz7kvrfDdeBOrFxNYCieRev0hFJY,1709
|
|
266
266
|
holado_multitask/multitasking/multitask_manager.py,sha256=lPi4gqK9HNK3FR4Mi-0hDn43PEq7RxXJ4JXKl2Nr_DM,21838
|
|
267
267
|
holado_multitask/multithreading/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
268
|
-
holado_multitask/multithreading/functionthreaded.py,sha256=
|
|
268
|
+
holado_multitask/multithreading/functionthreaded.py,sha256=jtfytI-AtST7Ay8U9ZvsCbWmYSvtZe8u-BvpmqWCO8Y,5848
|
|
269
269
|
holado_multitask/multithreading/loopfunctionthreaded.py,sha256=5kfONDR76uuT1bTJrAtnfSncHwvVvzl8jagWUvTduHw,2492
|
|
270
270
|
holado_multitask/multithreading/loopthread.py,sha256=4II3d22PRf891De8dd9P4WjuwI52KrTDRTSTPzzvso8,4265
|
|
271
271
|
holado_multitask/multithreading/periodicfunctionthreaded.py,sha256=PCBKpbOIThNGLq12rOONAh2ECxEOmaOb6Aqj2Ob2XY8,6926
|
|
@@ -605,7 +605,7 @@ test_holado/tools/django/api_rest/api_rest/api1/serializers.py,sha256=o_YxFr-tgC
|
|
|
605
605
|
test_holado/tools/django/api_rest/api_rest/api1/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
606
606
|
test_holado/tools/django/api_rest/api_rest/api1/views.py,sha256=kOt2xT6bxO47_z__5yYR9kcYIWWv4qYzpX0K8Tqonik,758
|
|
607
607
|
test_holado/tools/django/api_rest/api_rest/api1/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
608
|
-
holado-0.6.
|
|
609
|
-
holado-0.6.
|
|
610
|
-
holado-0.6.
|
|
611
|
-
holado-0.6.
|
|
608
|
+
holado-0.6.3.dist-info/METADATA,sha256=s5lhqII0WpArpL1LRYvaksB51qGVf2jmNGf8rUuTqNc,6166
|
|
609
|
+
holado-0.6.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
610
|
+
holado-0.6.3.dist-info/licenses/LICENSE,sha256=IgGmNlcFHnbp7UWrLJqAFvs_HIgjJDTmjCNRircJLsk,1070
|
|
611
|
+
holado-0.6.3.dist-info/RECORD,,
|
|
@@ -43,10 +43,10 @@ class DockerClient(object):
|
|
|
43
43
|
def client(self):
|
|
44
44
|
return self.__client
|
|
45
45
|
|
|
46
|
-
def has_container(self, name, in_list=True, reset_if_removed=True):
|
|
46
|
+
def has_container(self, name, in_list=True, all_=False, reset_if_removed=True):
|
|
47
47
|
# Note: Even if name exists in __containers, it is possible that the container has been removed
|
|
48
48
|
if in_list:
|
|
49
|
-
c = self.__get_container_from_list(name)
|
|
49
|
+
c = self.__get_container_from_list(name, all_=all_)
|
|
50
50
|
res = c is not None
|
|
51
51
|
|
|
52
52
|
if reset_if_removed and not res and name in self.__containers:
|
|
@@ -60,7 +60,7 @@ class DockerClient(object):
|
|
|
60
60
|
res = False
|
|
61
61
|
return res
|
|
62
62
|
|
|
63
|
-
def get_container(self, name, reset_if_removed=True):
|
|
63
|
+
def get_container(self, name, all_=False, reset_if_removed=True):
|
|
64
64
|
# Reset container if removed
|
|
65
65
|
if reset_if_removed and name in self.__containers:
|
|
66
66
|
if self.__containers[name].status == "removed":
|
|
@@ -68,16 +68,16 @@ class DockerClient(object):
|
|
|
68
68
|
|
|
69
69
|
# Get container from list if needed
|
|
70
70
|
if name not in self.__containers:
|
|
71
|
-
c = self.__get_container_from_list(name)
|
|
71
|
+
c = self.__get_container_from_list(name, all_=all_)
|
|
72
72
|
if c:
|
|
73
73
|
self.__containers[name] = DockerContainer(self, c)
|
|
74
74
|
|
|
75
75
|
return self.__containers.get(name)
|
|
76
76
|
|
|
77
|
-
def update_containers(self, reset_if_removed=True):
|
|
77
|
+
def update_containers(self, all_=False, sparse=False, reset_if_removed=True):
|
|
78
78
|
# Add new containers
|
|
79
79
|
updated_names = set()
|
|
80
|
-
for c in self.__client.containers.list(all=
|
|
80
|
+
for c in self.__client.containers.list(all=all_, sparse=sparse, ignore_removed=True):
|
|
81
81
|
try:
|
|
82
82
|
c_name = c.name
|
|
83
83
|
except docker.errors.NotFound:
|
|
@@ -92,21 +92,24 @@ class DockerClient(object):
|
|
|
92
92
|
for name in set(self.__containers.keys()).difference(updated_names):
|
|
93
93
|
del self.__containers[name]
|
|
94
94
|
|
|
95
|
-
def
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
def get_container_names(self, in_list=True, all_=False, sparse=False):
|
|
96
|
+
if in_list:
|
|
97
|
+
res = []
|
|
98
|
+
for c in self.__client.containers.list(all=all_, sparse=sparse, ignore_removed=True):
|
|
99
|
+
try:
|
|
100
|
+
c_name = c.name
|
|
101
|
+
except docker.errors.NotFound:
|
|
102
|
+
# Container 'c' doesn't exist anymore
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
res.append(c_name)
|
|
106
|
+
else:
|
|
107
|
+
res = list(self.__containers.keys())
|
|
105
108
|
return res
|
|
106
109
|
|
|
107
|
-
def __get_container_from_list(self, name):
|
|
110
|
+
def __get_container_from_list(self, name, all_=False):
|
|
108
111
|
res = None
|
|
109
|
-
for c in self.__client.containers.list(all=
|
|
112
|
+
for c in self.__client.containers.list(all=all_, ignore_removed=True):
|
|
110
113
|
try:
|
|
111
114
|
c_name = c.name
|
|
112
115
|
except docker.errors.NotFound:
|
|
@@ -205,7 +208,7 @@ class DockerClient(object):
|
|
|
205
208
|
def start_container(self, name, wait_running=True, **kwargs):
|
|
206
209
|
if Tools.do_log(logger, logging.DEBUG):
|
|
207
210
|
logger.debug(f"Starting docker container '{name}' with arguments {kwargs}{', and waiting running status' if wait_running else ''}")
|
|
208
|
-
container = self.get_container(name)
|
|
211
|
+
container = self.get_container(name, all_=True)
|
|
209
212
|
if not container:
|
|
210
213
|
raise FunctionalException("Container of name '{}' doesn't exist")
|
|
211
214
|
|
|
@@ -245,13 +248,14 @@ class DockerClient(object):
|
|
|
245
248
|
def remove_container(self, name):
|
|
246
249
|
if Tools.do_log(logger, logging.DEBUG):
|
|
247
250
|
logger.debug(f"Removing docker container of name '{name}'")
|
|
248
|
-
if not self.has_container(name):
|
|
251
|
+
if not self.has_container(name, in_list=True, all_=True):
|
|
249
252
|
raise FunctionalException(f"Container of name '{name}' doesn't exist")
|
|
250
253
|
|
|
251
|
-
|
|
254
|
+
if name in self.__containers:
|
|
255
|
+
del self.__containers[name]
|
|
252
256
|
self.client.api.remove_container(name)
|
|
253
257
|
|
|
254
|
-
if self.has_container(name):
|
|
258
|
+
if self.has_container(name, in_list=True, all_=True):
|
|
255
259
|
raise FunctionalException(f"Failed to remove container of name '{name}'")
|
|
256
260
|
else:
|
|
257
261
|
if Tools.do_log(logger, logging.DEBUG):
|
|
@@ -29,7 +29,7 @@ class FunctionThreaded(ctt.InterruptableThread):
|
|
|
29
29
|
Execute in a thread given function with given arguments
|
|
30
30
|
'''
|
|
31
31
|
|
|
32
|
-
def __init__(self, target, args=None, kwargs=None, name=None, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None):
|
|
32
|
+
def __init__(self, target, args=None, kwargs=None, name=None, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None, do_log=True):
|
|
33
33
|
super().__init__(name if name is not None else f"FunctionThreaded({repr(target)})", default_wait_timeout=default_wait_timeout, register_thread=register_thread, register_scope=register_scope, delay_before_run_sec=delay_before_run_sec)
|
|
34
34
|
|
|
35
35
|
if args is None:
|
|
@@ -46,6 +46,7 @@ class FunctionThreaded(ctt.InterruptableThread):
|
|
|
46
46
|
self.__interrupt_function = None
|
|
47
47
|
|
|
48
48
|
self.__callback_function = None
|
|
49
|
+
self.__do_log = do_log
|
|
49
50
|
|
|
50
51
|
@property
|
|
51
52
|
def error(self):
|
|
@@ -87,7 +88,8 @@ class FunctionThreaded(ctt.InterruptableThread):
|
|
|
87
88
|
try:
|
|
88
89
|
time.sleep(self.delay_before_run_seconds)
|
|
89
90
|
except Exception as exc:
|
|
90
|
-
|
|
91
|
+
if self.__do_log:
|
|
92
|
+
logger.exception(f"[Thread '{self.name}'] Exception while waiting delay before run (delay: {self.delay_before_run_seconds} ; type: {Typing.get_object_class_fullname(self.delay_before_run_seconds)})")
|
|
91
93
|
|
|
92
94
|
if self.is_interrupted:
|
|
93
95
|
return
|
|
@@ -96,7 +98,8 @@ class FunctionThreaded(ctt.InterruptableThread):
|
|
|
96
98
|
# logging.debug("+++++++++ Launching function [{}({})]".format(repr(self._target), repr(self._args)))
|
|
97
99
|
self.__result = self._function.run()
|
|
98
100
|
except Exception as exc:
|
|
99
|
-
|
|
101
|
+
if self.__do_log:
|
|
102
|
+
logger.exception(f"[Thread '{self.name}'] Exception catched during threaded function [{self._function.represent()}]")
|
|
100
103
|
self.__error = exc
|
|
101
104
|
|
|
102
105
|
if self.is_interrupted:
|
|
@@ -107,10 +110,13 @@ class FunctionThreaded(ctt.InterruptableThread):
|
|
|
107
110
|
self.__callback_function.run(self.result, self.error)
|
|
108
111
|
except Exception as exc:
|
|
109
112
|
msg = "Exception catched while calling callback function:\n callback_function: {}\n result: [{}]\n error: [{}]".format(repr(self.__callback_function), Tools.truncate_text(repr(self.result)), repr(self.error))
|
|
110
|
-
|
|
113
|
+
if self.__do_log:
|
|
114
|
+
logger.exception(msg)
|
|
111
115
|
raise FunctionalException(msg) from exc
|
|
112
116
|
|
|
113
|
-
|
|
117
|
+
if self.__do_log:
|
|
118
|
+
# logger.info(f"[Thread '{self.name}'] Thread has finished")
|
|
119
|
+
logger.info(f"[Thread '{self.name}'] Thread has finished (func: {self._function})")
|
|
114
120
|
|
|
115
121
|
def throw_if_error(self):
|
|
116
122
|
if self.error:
|
|
File without changes
|
|
File without changes
|