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.

holado/__init__.py ADDED
@@ -0,0 +1,263 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ #################################################
4
+ # HolAdo (Holistic Automation do)
5
+ #
6
+ # (C) Copyright 2021-2025 by Eric Klumpp
7
+ #
8
+ # 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:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11
+
12
+ # 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.
13
+ #################################################
14
+
15
+
16
+ import os
17
+ import importlib
18
+ import logging
19
+ import copy
20
+ from holado.common.handlers.undefined import default_value
21
+ from holado.common.tools.gc_manager import GcManager
22
+
23
+ try:
24
+ import behave
25
+ with_behave = True
26
+ except:
27
+ with_behave = False
28
+
29
+ logger = None
30
+
31
+
32
+ def __initialize_holado_loggers():
33
+ global logger
34
+ logger = logging.getLogger(__name__)
35
+
36
+ import holado.common
37
+ holado.common.initialize_loggers()
38
+
39
+
40
+
41
+ def _initialize_logging(initialize_logging=True, logging_config_file=None, log_level=None, log_on_console=False, log_in_file=True):
42
+ # print_imported_modules("[initialize]")
43
+ import holado_logging
44
+ # print_imported_modules("[after import holado_logging]")
45
+
46
+ # Configure logging module
47
+ holado_logging.configure(initialize_logging=initialize_logging, log_level=log_level)
48
+ # print_imported_modules("[after import holado_logging]")
49
+
50
+ # Initialize holado loggers
51
+ __initialize_holado_loggers()
52
+
53
+ # Register LogManager in SessionContext
54
+ holado_logging.register()
55
+
56
+ # Configure log manager
57
+ from holado.common.context.session_context import SessionContext
58
+ SessionContext.instance().log_manager.on_console = log_on_console
59
+ SessionContext.instance().log_manager.in_file = log_in_file
60
+ if logging_config_file is not None:
61
+ SessionContext.instance().log_manager.set_config_file_path(logging_config_file, update_default_level=False)
62
+ SessionContext.instance().log_manager.set_config()
63
+
64
+ def change_logging_config(log_level=None, log_on_console=False, log_in_file=True):
65
+ from holado.common.context.session_context import SessionContext
66
+ SessionContext.instance().log_manager.set_level(log_level, do_set_config=False)
67
+ SessionContext.instance().log_manager.on_console = log_on_console
68
+ SessionContext.instance().log_manager.in_file = log_in_file
69
+ SessionContext.instance().log_manager.set_config()
70
+
71
+ def initialize(TSessionContext=None, initialize_logging=True, logging_config_file=None,
72
+ log_level=None, log_on_console=False, log_in_file=True, session_kwargs=None,
73
+ garbage_collector_periodicity=default_value):
74
+ from holado_core.common.tools.tools import Tools
75
+
76
+ if session_kwargs is None:
77
+ session_kwargs = {}
78
+ with_session_path = session_kwargs.get("with_session_path", True)
79
+
80
+ if TSessionContext is not None:
81
+ if isinstance(TSessionContext, str):
82
+ module_name, class_type = TSessionContext.rsplit('.', maxsplit=1)
83
+ module = importlib.import_module(module_name)
84
+ TSessionContext = getattr(module, class_type)
85
+
86
+ from holado.common.context.session_context import SessionContext
87
+ SessionContext.TSessionContext = TSessionContext
88
+
89
+ # Initialize logging
90
+ _initialize_logging(initialize_logging=initialize_logging, logging_config_file=logging_config_file,
91
+ log_level=log_level, log_on_console=log_on_console, log_in_file=log_in_file and with_session_path)
92
+ if Tools.do_log(logger, logging.DEBUG):
93
+ logger.debug("Configured logging")
94
+
95
+ if Tools.do_log(logger, logging.DEBUG):
96
+ logger.debug("Importing HolAdo modules")
97
+ import_modules(get_holado_module_names())
98
+
99
+ initialize_session_context(session_kwargs)
100
+
101
+ # Initialize garbage collector
102
+ if garbage_collector_periodicity is not None:
103
+ GcManager.collect_periodically(garbage_collector_periodicity)
104
+ logger.debug(f"Garbage collector is disabled, and collects are automatically done in a dedicated thread (periodicity: {GcManager.get_collect_periodicity()} s)")
105
+
106
+ def initialize_for_script(TSessionContext=None, initialize_logging=True, logging_config_file=None, log_level=logging.WARNING, log_on_console=True, log_in_file=False, session_kwargs=None):
107
+ if session_kwargs is None:
108
+ session_kwargs={'with_session_path':log_in_file, 'raise_if_not_exist':False}
109
+
110
+ initialize(TSessionContext=TSessionContext, initialize_logging=initialize_logging, logging_config_file=logging_config_file,
111
+ log_level=log_level, log_on_console=log_on_console, log_in_file=log_in_file,
112
+ session_kwargs=session_kwargs )
113
+
114
+
115
+ def initialize_session_context(session_kwargs=None):
116
+ from holado_core.common.tools.tools import Tools
117
+
118
+ if Tools.do_log(logger, logging.DEBUG):
119
+ logger.debug("Initializing SessionContext")
120
+ from holado.common.context.session_context import SessionContext
121
+
122
+ SessionContext.instance().configure(session_kwargs)
123
+ SessionContext.instance().new_session(session_kwargs)
124
+ SessionContext.instance().initialize(session_kwargs)
125
+ if Tools.do_log(logger, logging.DEBUG):
126
+ logger.debug("Initialized SessionContext")
127
+
128
+
129
+ def holado_src_path():
130
+ here = os.path.abspath(os.path.dirname(__file__))
131
+ return os.path.normpath(os.path.join(here, ".."))
132
+
133
+ def get_holado_module_names():
134
+ lp = sorted(os.listdir(holado_src_path()))
135
+ return [name for name in lp if name.startswith("holado_") and name not in ['holado_logging']]
136
+
137
+ def import_modules(module_names):
138
+ from holado_core.common.tools.tools import Tools
139
+
140
+ imported_modules = __import_modules(module_names)
141
+ remaining_imported_modules = __register_modules_with_dependencies(imported_modules)
142
+
143
+ # Register modules with cross dependencies
144
+ if remaining_imported_modules:
145
+ if Tools.do_log(logger, logging.DEBUG):
146
+ logger.debug(f"Registering modules with cross dependencies: {list(remaining_imported_modules.keys())}...")
147
+ for module_name in remaining_imported_modules:
148
+ if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
149
+ logger.trace(f"Registering HolAdo module '{module_name}'...")
150
+ remaining_imported_modules[module_name].register()
151
+ if Tools.do_log(logger, logging.DEBUG):
152
+ logger.debug(f"Registered HolAdo module '{module_name}'")
153
+
154
+ def __import_modules(module_names):
155
+ from holado_core.common.tools.tools import Tools
156
+
157
+ if Tools.do_log(logger, logging.DEBUG):
158
+ logger.debug(f"Importing HolAdo modules: {module_names}")
159
+
160
+ res = {}
161
+ for module_name in module_names:
162
+ if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
163
+ logger.trace(f"Importing HolAdo module '{module_name}'...")
164
+ try:
165
+ module = importlib.import_module(module_name)
166
+ except Exception as exc:
167
+ if Tools.do_log(logger, logging.DEBUG):
168
+ logger.debug(f"Failed to import HolAdo module '{module_name}':\n{Tools.represent_exception(exc)}")
169
+ logger.warning(f"Failed to import HolAdo module '{module_name}': {str(exc)} (see debug logs for more details)")
170
+ pass
171
+ else:
172
+ if Tools.do_log(logger, logging.DEBUG):
173
+ logger.debug(f"Imported HolAdo module '{module_name}'")
174
+ res[module_name] = module
175
+ return res
176
+
177
+ def __register_modules_with_dependencies(imported_modules):
178
+ from holado_core.common.tools.tools import Tools
179
+
180
+ if Tools.do_log(logger, logging.DEBUG):
181
+ logger.debug(f"Registering imported HolAdo modules: {sorted(imported_modules.keys())}")
182
+
183
+ registered_modules = set()
184
+ remaining_imported_modules = copy.copy(imported_modules)
185
+ has_new_registered = True
186
+ while has_new_registered:
187
+ has_new_registered = False
188
+ imported_module_names = list(remaining_imported_modules.keys())
189
+ for module_name in imported_module_names:
190
+ if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
191
+ logger.trace(f"Registering HolAdo module '{module_name}'...")
192
+ module = remaining_imported_modules[module_name]
193
+ module_dependencies = set(module.dependencies()) if hasattr(module, 'dependencies') and module.dependencies() is not None else None
194
+ if module_dependencies is None or registered_modules.issuperset(module_dependencies):
195
+ if hasattr(module, 'register'):
196
+ module.register()
197
+ if Tools.do_log(logger, logging.DEBUG):
198
+ logger.debug(f"Registered HolAdo module '{module_name}'")
199
+ else:
200
+ if Tools.do_log(logger, logging.DEBUG):
201
+ logger.debug(f"Nothing to register for HolAdo module '{module_name}'")
202
+ del remaining_imported_modules[module_name]
203
+ registered_modules.add(module_name)
204
+ has_new_registered = True
205
+ else:
206
+ if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
207
+ logger.trace(f"Pending registration of HolAdo module '{module_name}' due to dependencies: {module_dependencies.difference(registered_modules)}")
208
+ return remaining_imported_modules
209
+
210
+ def import_steps():
211
+ from holado_core.common.exceptions.technical_exception import TechnicalException
212
+ from holado_core.common.tools.tools import Tools
213
+
214
+ lp = sorted(os.listdir(holado_src_path()))
215
+ for module_name in lp:
216
+ if module_name.startswith("holado_"):
217
+ if with_behave:
218
+ module_steps_package = f"{module_name}.tests.behave.steps"
219
+ else:
220
+ raise TechnicalException(f"'behave' is needed for steps")
221
+ try:
222
+ importlib.import_module(module_steps_package)
223
+ except Exception as exc:
224
+ if "No module named" in str(exc):
225
+ if Tools.do_log(logger, logging.DEBUG):
226
+ logger.debug(f"No steps in HolAdo module '{module_name}'")
227
+ # logger.warning(f"No steps in HolAdo module '{module_name}'")
228
+ else:
229
+ raise TechnicalException(f"Failed to import steps of HolAdo module '{module_name}'") from exc
230
+ else:
231
+ if Tools.do_log(logger, logging.DEBUG):
232
+ logger.debug(f"Imported steps of HolAdo module '{module_name}'")
233
+
234
+ def import_private_steps():
235
+ from holado_core.common.tools.tools import Tools
236
+
237
+ lp = sorted(os.listdir(holado_src_path()))
238
+ for module_name in lp:
239
+ if module_name.startswith("holado_"):
240
+ if with_behave:
241
+ module_steps_package = f"{module_name}.tests.behave.steps.private"
242
+ else:
243
+ from holado_core.common.exceptions.technical_exception import TechnicalException
244
+ raise TechnicalException(f"'behave' is needed for steps")
245
+ try:
246
+ importlib.import_module(module_steps_package)
247
+ except:
248
+ pass
249
+ else:
250
+ if Tools.do_log(logger, logging.DEBUG):
251
+ logger.debug(f"Imported private steps of HolAdo module '{module_name}'")
252
+
253
+ def print_imported_modules(prefix):
254
+ import sys
255
+ import types
256
+
257
+ sys_modules = [v.__name__ for _,v in sys.modules.items() if isinstance(v, types.ModuleType)]
258
+ print(f"{prefix} sys modules: {sys_modules}")
259
+
260
+ # globals_modules = [v.__name__ for _,v in globals().items() if isinstance(v, types.ModuleType)]
261
+ # print(f"{prefix} globals modules: {globals_modules}")
262
+
263
+
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ #################################################
4
+ # HolAdo (Holistic Automation do)
5
+ #
6
+ # (C) Copyright 2021-2025 by Eric Klumpp
7
+ #
8
+ # 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:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11
+
12
+ # 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.
13
+ #################################################
14
+
15
+
16
+ def initialize_loggers():
17
+ import holado.common.context
18
+ holado.common.context.initialize_loggers()
19
+
20
+ import holado.common.handlers
21
+ holado.common.handlers.initialize_loggers()
22
+
23
+ import holado.common.tools
24
+ holado.common.tools.initialize_loggers()
25
+
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ #################################################
4
+ # HolAdo (Holistic Automation do)
5
+ #
6
+ # (C) Copyright 2021-2025 by Eric Klumpp
7
+ #
8
+ # 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:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11
+
12
+ # 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.
13
+ #################################################
14
+
15
+
16
+ def initialize_loggers():
17
+ import holado.common.context.context
18
+ holado.common.context.context.initialize_logger()
19
+
20
+ import holado.common.context.service_manager
21
+ holado.common.context.service_manager.initialize_logger()
22
+
23
+ import holado.common.context.session_context
24
+ holado.common.context.session_context.initialize_logger()
25
+
@@ -0,0 +1,145 @@
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 holado.common.handlers.object import DeleteableObject, Object
16
+ from holado_core.common.tools.tools import Tools
17
+ from holado_core.common.exceptions.element_exception import ElementNotFoundException
18
+ from holado_python.standard_library.typing import Typing
19
+
20
+ logger = None
21
+
22
+ def initialize_logger():
23
+ global logger
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ class Context(DeleteableObject):
28
+ """
29
+ @summary: Mother class for any context class
30
+ """
31
+
32
+ def __init__(self, name):
33
+ super().__init__(name)
34
+ self.on_delete_call_gc_collect = True
35
+
36
+ self.__objects = {}
37
+ self.__on_delete_objects = []
38
+
39
+ def get_context_name(self):
40
+ return Object.name(self)
41
+
42
+ def _delete_object(self):
43
+ # Remove all objects
44
+ self.remove_all_objects()
45
+
46
+ def remove_all_objects(self):
47
+ from holado_core.common.exceptions.functional_exception import FunctionalException
48
+ from holado_core.common.exceptions.technical_exception import TechnicalException
49
+
50
+ keys = set(self.__objects.keys())
51
+ if Tools.do_log(logger, logging.DEBUG):
52
+ logger.debug(f"[{self.name}] Removing {len(keys)} objects: {keys}")
53
+ for index, key in enumerate(keys):
54
+ if Tools.do_log(logger, logging.DEBUG):
55
+ logger.debug(f"[{self.name}] Removing object {index+1}/{len(keys)}: '{key}' (type: {Typing.get_object_class_fullname(self.get_object(key))})")
56
+ try:
57
+ self.remove_object(key)
58
+ except FunctionalException as exc:
59
+ raise TechnicalException() from exc
60
+ if Tools.do_log(logger, logging.DEBUG):
61
+ logger.debug(f"[{self.name}] Finished to remove {len(keys)} objects: {keys}")
62
+
63
+ def remove_object(self, name):
64
+ if not self.has_object(name):
65
+ from holado_core.common.exceptions.technical_exception import TechnicalException
66
+ raise TechnicalException("Context doesn't contain object '{}'".format(name))
67
+ self._remove(name, True)
68
+
69
+ def _remove(self, name, remove_from_lifetime_manager):
70
+ obj = self.get_object(name)
71
+ if Tools.do_log(logger, logging.DEBUG):
72
+ logger.debug(f"[{self.name}] Removing object '{name}' (type: {Typing.get_object_class_fullname(obj)})")
73
+ if name in self.__on_delete_objects:
74
+ if isinstance(obj, DeleteableObject):
75
+ if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
76
+ logger.trace(f"[{self.name}] Deleting object '{name}'")
77
+ try:
78
+ obj.delete_object()
79
+ except Exception:
80
+ logger.exception(f"[{self.name}] Catched exception while deleting object '{name}'")
81
+ else:
82
+ if Tools.do_log(logger, logging.DEBUG):
83
+ logger.debug(f"[{self.name}] Deleted object '{name}'")
84
+ self.__on_delete_objects.remove(name)
85
+
86
+ if self.has_object(name):
87
+ del self.__objects[name]
88
+ # if remove_from_lifetime_manager:
89
+ # from holado.common.context.session_context import SessionContext
90
+ # SessionContext.instance().get_object_lifetime_manager().remove_object_lifetime(name, self)
91
+
92
+ def set_object(self, name, obj, raise_if_already_set = True):
93
+ from holado_core.common.exceptions.functional_exception import FunctionalException
94
+ from holado_core.common.exceptions.technical_exception import TechnicalException
95
+
96
+ if obj is None:
97
+ if self.has_object(name):
98
+ try:
99
+ self.remove_object(name)
100
+ except FunctionalException as e:
101
+ raise TechnicalException() from e
102
+ else:
103
+ if raise_if_already_set and self.has_object(name):
104
+ raise TechnicalException(f"[{self.name}] Context already contains object '{name}'")
105
+ self._put(name, obj)
106
+
107
+ def _put(self, name, obj):
108
+ self.__objects[name] = obj
109
+ self.__on_delete_objects.append(name)
110
+
111
+ def get_object(self, name):
112
+ if not self.has_object(name):
113
+ from holado_core.common.exceptions.technical_exception import TechnicalException
114
+ raise TechnicalException(f"[{self.name}] Context doesn't contain object '{name}'")
115
+ return self.__objects[name]
116
+
117
+ def has_object(self, name):
118
+ return name in self.__objects
119
+
120
+ def get_object_name(self, obj):
121
+ for name, value in self.__objects.items():
122
+ if value is obj:
123
+ return name
124
+ return None
125
+
126
+ def remove_lifetimed_object(self, object_id):
127
+ self._remove(object_id, False)
128
+
129
+ def get_or_create_initilizable_object_by_class(self, object_class):
130
+ raise NotImplementedError()
131
+
132
+ def get_or_create_object_by_class(self, object_class):
133
+ raise NotImplementedError()
134
+
135
+ def get_object_getter_eval_string(self, obj, raise_not_found=True):
136
+ name = self.get_object_name(obj)
137
+ if name is not None:
138
+ return f"{Typing.get_object_class_fullname(self)}.instance().get_object('{name}')"
139
+
140
+ if raise_not_found:
141
+ raise ElementNotFoundException(f"[{self.name}] Failed to find object of id {id(obj)}")
142
+ else:
143
+ return None
144
+
145
+