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

@@ -0,0 +1,254 @@
1
+
2
+ #################################################
3
+ # HolAdo (Holistic Automation do)
4
+ #
5
+ # (C) Copyright 2021-2025 by Eric Klumpp
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
+ #
9
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
+
11
+ # The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
12
+ #################################################
13
+
14
+ import logging
15
+ from builtins import object
16
+
17
+ logger = None
18
+
19
+ def initialize_logger():
20
+ global logger
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class ServiceManager(object):
25
+ """
26
+ Manage services in context types
27
+ """
28
+
29
+ def __init__(self, default_context_type):
30
+ """Create service manager with given default context type.
31
+ Default context type is usually SessionContext.
32
+ """
33
+ self.__default_context_type = default_context_type
34
+ self.__services = {}
35
+
36
+ @property
37
+ def default_context_type(self):
38
+ return self.__default_context_type
39
+
40
+ def has_service(self, name):
41
+ return name in self.__services
42
+
43
+ def register_service_instance(self, name, service_instance, context, raise_if_service_exist=True, raise_if_object_exist=True):
44
+ """
45
+ Register a new service in a context with an existing instance.
46
+
47
+ A property with service name is automatically added to context.
48
+
49
+ Notes:
50
+ It is possible to override an already registered service by passing "raise_if_service_exist=False, raise_if_object_exist=False".
51
+ It is possible to replace an existing property by service property by passing "raise_if_service_exist=False".
52
+ """
53
+ from holado_core.common.exceptions.technical_exception import TechnicalException
54
+ logger_ = logger if logger else logging
55
+
56
+ logger_.trace(f"Registering service '{name}' in context {context}...")
57
+
58
+ if raise_if_object_exist and context.has_object(name):
59
+ raise TechnicalException(f"Context contains already an object '{name}'")
60
+ if raise_if_service_exist and hasattr(context, name):
61
+ raise TechnicalException(f"Context contains already an attribute '{name}'")
62
+
63
+ # Register the service
64
+ if context.has_object(name):
65
+ context.remove_object(name)
66
+ context.set_object(name, service_instance)
67
+
68
+ # Add dedicated property in context
69
+ self.add_context_property(name, type(context), raise_if_service_exist=False)
70
+
71
+ logger_.debug(f"Registered service '{name}' instance {service_instance} in context {context}")
72
+
73
+ def register_service_type(self, name, type_service, initialize_service=None, raise_if_exist=True,
74
+ context_types=None, context_raise_if_service_exist=True, context_raise_if_object_exist=True,
75
+ shortcut_in_types=None):
76
+ """
77
+ Register a new service type in service manager, and in defines context types.
78
+
79
+ After this registration, it is possible to:
80
+ - use the service by calling service manager property (the service instance is stored in service manager context)
81
+ - register service in another context type with method register_service_type_in_context
82
+ A property with service name is automatically added to context of given types.
83
+ If shortcut_in_types is defined, a shortcut property is added in these types to access directly the context service
84
+ (this feature currently works only for ProcessContext, ThreadContext, FeatureContext and ScenarioContext)
85
+
86
+ When the context property is called the first time, the service is instantiated by calling "m = type_service()".
87
+ After instantiation, it will be initialized by calling "initialize_service(m)".
88
+ Initialization is typically used to inject dependencies, and process initialize actions needing these dependencies.
89
+
90
+ Notes:
91
+ If context_types=None, default context type is used
92
+ Use lambda to define "type_service" when service "__init__" method has arguments.
93
+ Use lambda to define "initialize_service" when service "initialize" method has arguments.
94
+ It is possible to replace an existing attribute/property by service property by passing "raise_if_exist=False".
95
+ """
96
+ from holado_core.common.exceptions.technical_exception import TechnicalException
97
+ logger_ = logger if logger else logging
98
+
99
+ logger_.trace(f"Registering service '{name}'...")
100
+
101
+ if shortcut_in_types and context_types and len(context_types) > 1:
102
+ from holado_core.common.exceptions.functional_exception import FunctionalException
103
+ raise FunctionalException(
104
+ f"Impossible to define to which context type service the shortcuts must be linked to. \
105
+ Please define only one context type when creating shortcuts")
106
+ if raise_if_exist and name in self.__services:
107
+ raise TechnicalException(f"A service '{name}' is already registered")
108
+ if raise_if_exist and hasattr(self, name):
109
+ raise TechnicalException(f"Service manager has already an attribute '{name}'")
110
+
111
+ # Register the service
112
+ self.__services[name] = (type_service, initialize_service, context_raise_if_service_exist, context_raise_if_object_exist)
113
+
114
+ # Add dedicated property in service manager
115
+ self.__add_service_manager_property(name)
116
+
117
+ # Add property in context types
118
+ _context_types = context_types
119
+ if _context_types is None:
120
+ _context_types = [self.__default_context_type]
121
+ for context_type in _context_types:
122
+ self.add_context_property(name, context_type, raise_if_exist)
123
+
124
+ # Add shortcut property in given types
125
+ if context_types and len(context_types) == 1:
126
+ for type_ in shortcut_in_types:
127
+ self.add_shortcut_property_to_context_service(name, type_, context_types[0], raise_if_exist)
128
+
129
+ logger_.debug(f"Registered service '{name}'")
130
+ # print(f"Registered service '{name}'")
131
+
132
+ def register_service_type_in_context(self, name, context, raise_if_service_exist=None, raise_if_object_exist=None):
133
+ logger_ = logger if logger else logging
134
+
135
+ logger_.trace(f"Registering service '{name}' in context {context}...")
136
+
137
+ self.__verify_object_doesnt_exist(name, context, raise_if_object_exist)
138
+
139
+ if context.has_object(name):
140
+ context.remove_object(name)
141
+ self.add_context_property(name, type(context), raise_if_service_exist)
142
+
143
+ logger_.trace(f"Registered service '{name}' in context {context}")
144
+
145
+ def _get_context_service(self, name, context):
146
+ """
147
+ Get a service instance.
148
+ If not already created, the instance is created according its registration and stored in context.
149
+ """
150
+ from holado_core.common.exceptions.technical_exception import TechnicalException
151
+ logger_ = logger if logger else logging
152
+
153
+ logger_.trace(f"Getting service '{name}' from {context}...")
154
+ if not context.has_object(name):
155
+ logger_.debug(f"Creating service '{name}'...")
156
+ if name in self.__services:
157
+ service = self.__services[name]
158
+ else:
159
+ raise TechnicalException(f"Unregistered service '{name}'")
160
+
161
+ logger_.trace(f"Instantiating service '{name}'...")
162
+ service_inst = service[0]()
163
+ context.set_object(name, service_inst)
164
+ logger_.debug(f"Service '{name}' is instantiated and stored in context {context}")
165
+
166
+ if service[1] is not None:
167
+ logger_.trace(f"Initializing service '{name}'...")
168
+ service[1](service_inst)
169
+ logger_.debug(f"Created service '{name}' for context {context}")
170
+ return context.get_object(name)
171
+
172
+ def add_context_property(self, name, context_type, raise_if_service_exist=None):
173
+ if raise_if_service_exist is None or raise_if_service_exist:
174
+ self.__verify_service_doesnt_exist(name, context_type, raise_if_service_exist)
175
+
176
+ @property
177
+ def context_service_property(self_context):
178
+ return self._get_context_service(name, self_context)
179
+ setattr(context_type, name, context_service_property)
180
+
181
+ def add_shortcut_property_to_context_service(self, name, dst_type, context_type, raise_if_service_exist=None):
182
+ from holado_multitask.multiprocessing.context.process_context import ProcessContext
183
+ from holado.common.context.session_context import SessionContext
184
+ from holado_multitask.multithreading.context.thread_context import ThreadContext
185
+ from holado_test.common.context.feature_context import FeatureContext
186
+ from holado_test.common.context.scenario_context import ScenarioContext
187
+ from holado_core.common.exceptions.technical_exception import TechnicalException
188
+
189
+ if issubclass(context_type, ProcessContext):
190
+ self.__add_shortcut_property_to_context_service(name, dst_type,
191
+ SessionContext.instance().multitask_manager.get_process_context,
192
+ raise_if_service_exist)
193
+ elif issubclass(context_type, ThreadContext):
194
+ self.__add_shortcut_property_to_context_service(name, dst_type,
195
+ SessionContext.instance().multitask_manager.get_thread_context,
196
+ raise_if_service_exist)
197
+ elif issubclass(context_type, FeatureContext):
198
+ self.__add_shortcut_property_to_context_service(name, dst_type,
199
+ SessionContext.instance().get_feature_context,
200
+ raise_if_service_exist)
201
+ elif issubclass(context_type, ScenarioContext):
202
+ self.__add_shortcut_property_to_context_service(name, dst_type,
203
+ SessionContext.instance().get_scenario_context,
204
+ raise_if_service_exist)
205
+ else:
206
+ raise TechnicalException(f"Unmanaged context of type {context_type}")
207
+
208
+ def __add_shortcut_property_to_context_service(self, name, dst_type, context_getter, raise_if_service_exist=None):
209
+ from holado_core.common.exceptions.technical_exception import TechnicalException
210
+
211
+ self.__verify_service_doesnt_exist(name, dst_type, raise_if_service_exist)
212
+
213
+ @property
214
+ def context_service_property(self_context): # @UnusedVariable
215
+ context = context_getter()
216
+ if not hasattr(context, name):
217
+ raise TechnicalException(f"Service '{name}' doesn't exist in context {context}")
218
+ return getattr(context, name)
219
+ setattr(dst_type, name, context_service_property)
220
+
221
+ def __add_service_manager_property(self, name):
222
+ @property
223
+ def manager_service_property(self_manager):
224
+ return self_manager._get_context_service(name, self_manager.context)
225
+ setattr(self.__class__, name, manager_service_property)
226
+
227
+ def __verify_service_exist(self, name):
228
+ from holado_core.common.exceptions.technical_exception import TechnicalException
229
+
230
+ if name not in self.__services:
231
+ raise TechnicalException(f"Unregistered service '{name}'")
232
+
233
+ def __verify_object_doesnt_exist(self, name, context, raise_if_object_exist=None):
234
+ from holado_core.common.exceptions.technical_exception import TechnicalException
235
+
236
+ if raise_if_object_exist is None:
237
+ self.__verify_service_exist(name)
238
+ raise_if_object_exist = self.__services[name][3]
239
+
240
+ if raise_if_object_exist and context.has_object(name):
241
+ raise TechnicalException(f"Context contains already an object '{name}'")
242
+
243
+ def __verify_service_doesnt_exist(self, name, obj_inst_or_type, raise_if_service_exist=None):
244
+ from holado_core.common.exceptions.technical_exception import TechnicalException
245
+
246
+ if raise_if_service_exist is None:
247
+ self.__verify_service_exist(name)
248
+ raise_if_service_exist = self.__services[name][2]
249
+
250
+ if raise_if_service_exist and hasattr(obj_inst_or_type, name):
251
+ raise TechnicalException(f"Context contains already an attribute '{name}'")
252
+
253
+
254
+