holado 0.6.1__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.

@@ -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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: holado
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: HolAdo framework
5
5
  Project-URL: Homepage, https://gitlab.com/holado_framework/python
6
6
  Project-URL: Issues, https://gitlab.com/holado_framework/python/-/issues
@@ -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=5vR7iV2NUI1sZxvkzcUBOe7FT9LkzYaivNDTE4d_6ds,6703
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
@@ -157,12 +157,12 @@ holado_db/tools/db/db_manager.py,sha256=0llXc6YhXfLr6oNfncPNjh4_ZInIm8XYywutQYvv
157
157
  holado_db/tools/db/clients/base/db_audit.py,sha256=eJ1r_0YUhvq50JngpWAdyEeVHWjAD4YCvWCJsLc1zmc,4368
158
158
  holado_db/tools/db/clients/base/db_client.py,sha256=sdMKDbnhO0zMCxq3n6vHcn5d5Asm6N5WhKDss89v_PU,15298
159
159
  holado_db/tools/db/clients/postgresql/postgresql_audit.py,sha256=yoy4-Yt4lZHJw7xAcuTj2Thg4aTDCYJBt-6HzQeEE80,3939
160
- holado_db/tools/db/clients/postgresql/postgresql_client.py,sha256=40UOniOJS-2Jrl-lxCSPTn32JGmblO-WqRFQYV40srk,4246
160
+ holado_db/tools/db/clients/postgresql/postgresql_client.py,sha256=FW9t4kGh3ClDr1NfOymSMAYSrguPcKeqbwE6BM4ognI,4746
161
161
  holado_db/tools/db/clients/sqlite/sqlite_audit.py,sha256=cK7hBE7aKCFOX5xnT-QnYD_1loQPgPP9Gf6qTT1XuI4,3966
162
162
  holado_db/tools/db/clients/sqlite/sqlite_client.py,sha256=-EvKAeaOc1Iv_wmuAgvzpS5hEfDFvZgP9OkFc9L5M-s,2891
163
163
  holado_db/tools/db/query/query_manager.py,sha256=7n-d_Q373hlsKQshY3accIH8XfqaLScqnhMdTT2oWC4,3642
164
164
  holado_db/tools/db/query/base/query_builder.py,sha256=-nCyBe8zsRhOX39uCV0P7OY_YKobQJVIpJDL2sUA_H8,5926
165
- holado_db/tools/db/query/pypika/pypika_query_builder.py,sha256=qwFtd-7dSRju-qwGkiaDPwSkNgYpdfKsunq-TM3HhI8,10988
165
+ holado_db/tools/db/query/pypika/pypika_query_builder.py,sha256=9x2-7B4p3eXSq3vLWWLscoFWJZakhcPxmNrpGR2ysdw,10964
166
166
  holado_django/__init__.py,sha256=KpbIi2cm1BYZgoWf0LuhE0ei3ZCE15UcUtjC1cSA55M,1653
167
167
  holado_django/server/HOWTO.txt,sha256=91z7uC1Hf_X6dNO2wxdqQFKG2U6wIIW6NKxirUglYOA,2085
168
168
  holado_django/server/django_server.py,sha256=2nVH0WX99nGGH-c4QztfoC-zAJKmLrNTXvhTp4qsL08,4557
@@ -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=SnNIcLM4Slec81uJqlCn6r5NhT2MLdj_-lYs2O-P1X0,13792
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=gCLVMrxI18dKDNOQ9szH4hEKk_PQSWSuoO4enEEORzE,5570
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.1.dist-info/METADATA,sha256=nl2iztCdJ0mOo7toB80StmBvh9zgy8SOSrfi17-7SS0,6166
609
- holado-0.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
610
- holado-0.6.1.dist-info/licenses/LICENSE,sha256=IgGmNlcFHnbp7UWrLJqAFvs_HIgjJDTmjCNRircJLsk,1070
611
- holado-0.6.1.dist-info/RECORD,,
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,,
@@ -15,9 +15,9 @@ import logging
15
15
  from holado_db.tools.db.clients.base.db_client import DBClient
16
16
  from holado_core.common.tables.table_with_header import TableWithHeader
17
17
  from holado_core.common.tools.tools import Tools
18
- import json
19
- from pypika.terms import Function, LiteralValue
20
18
  from holado_db.tools.db.clients.postgresql.postgresql_audit import PostgreSQLTriggerAuditManager
19
+ from holado_db.tools.db.query.pypika.pypika_query_builder import PypikaQueryBuilder
20
+ from holado_core.common.exceptions.technical_exception import TechnicalException
21
21
 
22
22
  logger = logging.getLogger(__name__)
23
23
 
@@ -29,11 +29,13 @@ except Exception as exc:
29
29
  logger.debug(f"PostgreSQLClient is not available. Initialization failed on error: {exc}")
30
30
  with_psycopg = False
31
31
 
32
-
33
- # from pypika import Function
34
- class JsonbSet(Function):
35
- def __init__(self, name, *args, **kwargs):
36
- super().__init__('jsonb_set', LiteralValue(name), *args, **kwargs)
32
+ if PypikaQueryBuilder.is_available():
33
+ from pypika.terms import Function, LiteralValue
34
+
35
+ # from pypika import Function
36
+ class JsonbSet(Function):
37
+ def __init__(self, name, *args, **kwargs):
38
+ super().__init__('jsonb_set', LiteralValue(name), *args, **kwargs)
37
39
 
38
40
 
39
41
  class PostgreSQLClient(DBClient):
@@ -72,6 +74,9 @@ class PostgreSQLClient(DBClient):
72
74
  if isinstance(result, TableWithHeader) and result[0][0].content is not None:
73
75
  is_key_set = json_key in result[0][0].content
74
76
  if is_key_set:
77
+ if not PypikaQueryBuilder.is_available():
78
+ # Note: This case cannot appear currently (04/08/2025), but can appear if another QueryBuilder is managed that is not using pypika
79
+ raise TechnicalException(f"Missing dependence: pypika")
75
80
  self.update(table_name, {field_name: JsonbSet(f'{field_name}', f'{{"{json_key}"}}', f'"{json_value}"')}, where_data=where_data, where_compare_data=where_compare_data, do_commit=True)
76
81
  else:
77
82
  self.update(table_name, {field_name: f'{field_name} || {{"{json_key}":"{json_value}"}}'}, where_data=where_data, where_compare_data=where_compare_data, do_commit=True)
@@ -16,7 +16,6 @@ from holado_core.common.exceptions.technical_exception import TechnicalException
16
16
  from holado_db.tools.db.query.base.query_builder import QueryBuilder, DBCompareOperator
17
17
  from holado_core.common.tools.tools import Tools
18
18
  from holado_python.standard_library.typing import Typing
19
- from pypika.terms import Function
20
19
 
21
20
 
22
21
  logger = logging.getLogger(__name__)
@@ -24,7 +23,7 @@ logger = logging.getLogger(__name__)
24
23
  try:
25
24
  import pypika.functions
26
25
  from pypika.queries import Table, Query
27
- from pypika.terms import Parameter
26
+ from pypika.terms import Parameter, Function
28
27
  with_pypika = True
29
28
  except Exception as exc:
30
29
  if Tools.do_log(logger, logging.DEBUG):
@@ -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=True, sparse=True, ignore_removed=True):
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 get_all_container_names(self):
96
- res = []
97
- for c in self.__client.containers.list(all=True, sparse=True, ignore_removed=True):
98
- try:
99
- c_name = c.name
100
- except docker.errors.NotFound:
101
- # Container 'c' doesn't exist anymore
102
- continue
103
-
104
- res.append(c_name)
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=True, ignore_removed=True):
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
- del self.__containers[name]
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
- 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
+ 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
- logger.exception(f"[Thread '{self.name}'] Exception catched during threaded function [{self._function.represent()}]")
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
- logger.exception(msg)
113
+ if self.__do_log:
114
+ logger.exception(msg)
111
115
  raise FunctionalException(msg) from exc
112
116
 
113
- logger.info(f"[Thread '{self.name}'] Thread has finished")
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