naeural-client 2.0.0__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.
- naeural_client/__init__.py +13 -0
- naeural_client/_ver.py +13 -0
- naeural_client/base/__init__.py +6 -0
- naeural_client/base/distributed_custom_code_presets.py +44 -0
- naeural_client/base/generic_session.py +1763 -0
- naeural_client/base/instance.py +616 -0
- naeural_client/base/payload/__init__.py +1 -0
- naeural_client/base/payload/payload.py +66 -0
- naeural_client/base/pipeline.py +1499 -0
- naeural_client/base/plugin_template.py +5209 -0
- naeural_client/base/responses.py +209 -0
- naeural_client/base/transaction.py +157 -0
- naeural_client/base_decentra_object.py +143 -0
- naeural_client/bc/__init__.py +3 -0
- naeural_client/bc/base.py +1046 -0
- naeural_client/bc/chain.py +0 -0
- naeural_client/bc/ec.py +324 -0
- naeural_client/certs/__init__.py +0 -0
- naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +22 -0
- naeural_client/code_cheker/__init__.py +1 -0
- naeural_client/code_cheker/base.py +520 -0
- naeural_client/code_cheker/checker.py +294 -0
- naeural_client/comm/__init__.py +2 -0
- naeural_client/comm/amqp_wrapper.py +338 -0
- naeural_client/comm/mqtt_wrapper.py +539 -0
- naeural_client/const/README.md +3 -0
- naeural_client/const/__init__.py +9 -0
- naeural_client/const/base.py +101 -0
- naeural_client/const/comms.py +80 -0
- naeural_client/const/environment.py +26 -0
- naeural_client/const/formatter.py +7 -0
- naeural_client/const/heartbeat.py +111 -0
- naeural_client/const/misc.py +20 -0
- naeural_client/const/payload.py +190 -0
- naeural_client/default/__init__.py +1 -0
- naeural_client/default/instance/__init__.py +4 -0
- naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +54 -0
- naeural_client/default/instance/custom_web_app_01_plugin.py +118 -0
- naeural_client/default/instance/net_mon_01_plugin.py +45 -0
- naeural_client/default/instance/view_scene_01_plugin.py +28 -0
- naeural_client/default/session/mqtt_session.py +72 -0
- naeural_client/io_formatter/__init__.py +2 -0
- naeural_client/io_formatter/base/__init__.py +1 -0
- naeural_client/io_formatter/base/base_formatter.py +80 -0
- naeural_client/io_formatter/default/__init__.py +3 -0
- naeural_client/io_formatter/default/a_dummy.py +51 -0
- naeural_client/io_formatter/default/aixp1.py +113 -0
- naeural_client/io_formatter/default/default.py +22 -0
- naeural_client/io_formatter/io_formatter_manager.py +96 -0
- naeural_client/logging/__init__.py +1 -0
- naeural_client/logging/base_logger.py +2056 -0
- naeural_client/logging/logger_mixins/__init__.py +12 -0
- naeural_client/logging/logger_mixins/class_instance_mixin.py +92 -0
- naeural_client/logging/logger_mixins/computer_vision_mixin.py +443 -0
- naeural_client/logging/logger_mixins/datetime_mixin.py +344 -0
- naeural_client/logging/logger_mixins/download_mixin.py +421 -0
- naeural_client/logging/logger_mixins/general_serialization_mixin.py +242 -0
- naeural_client/logging/logger_mixins/json_serialization_mixin.py +481 -0
- naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +301 -0
- naeural_client/logging/logger_mixins/process_mixin.py +63 -0
- naeural_client/logging/logger_mixins/resource_size_mixin.py +81 -0
- naeural_client/logging/logger_mixins/timers_mixin.py +501 -0
- naeural_client/logging/logger_mixins/upload_mixin.py +260 -0
- naeural_client/logging/logger_mixins/utils_mixin.py +675 -0
- naeural_client/logging/small_logger.py +93 -0
- naeural_client/logging/tzlocal/__init__.py +20 -0
- naeural_client/logging/tzlocal/unix.py +231 -0
- naeural_client/logging/tzlocal/utils.py +113 -0
- naeural_client/logging/tzlocal/win32.py +151 -0
- naeural_client/logging/tzlocal/windows_tz.py +718 -0
- naeural_client/plugins_manager_mixin.py +273 -0
- naeural_client/utils/__init__.py +2 -0
- naeural_client/utils/comm_utils.py +44 -0
- naeural_client/utils/dotenv.py +75 -0
- naeural_client-2.0.0.dist-info/METADATA +365 -0
- naeural_client-2.0.0.dist-info/RECORD +78 -0
- naeural_client-2.0.0.dist-info/WHEEL +4 -0
- naeural_client-2.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
from ..const.payload import NOTIFICATION_CODES, PAYLOAD_DATA
|
2
|
+
|
3
|
+
|
4
|
+
class Response():
|
5
|
+
def __init__(self) -> None:
|
6
|
+
self.__is_solved = False
|
7
|
+
self.__is_good = None
|
8
|
+
self.__log = None
|
9
|
+
|
10
|
+
self.__fail_reason = None
|
11
|
+
return
|
12
|
+
|
13
|
+
def __repr__(self) -> str:
|
14
|
+
return f"<Response: {self.__class__.__name__}>"
|
15
|
+
|
16
|
+
def set_logger(self, log) -> None:
|
17
|
+
self.__log = log
|
18
|
+
|
19
|
+
def P(self, *args, **kwargs):
|
20
|
+
if self.__log is None:
|
21
|
+
print(*args, **kwargs)
|
22
|
+
self.__log.P(*args, **kwargs)
|
23
|
+
|
24
|
+
def D(self, *args, **kwargs):
|
25
|
+
if self.__log is None:
|
26
|
+
print(*args, **kwargs)
|
27
|
+
self.__log.D(*args, **kwargs)
|
28
|
+
|
29
|
+
def fail(self, fail_reason: str) -> None:
|
30
|
+
self.__is_solved = True
|
31
|
+
self.__is_good = False
|
32
|
+
self.__fail_reason = fail_reason
|
33
|
+
return
|
34
|
+
|
35
|
+
def success(self) -> None:
|
36
|
+
self.__is_good = True
|
37
|
+
self.__is_solved = True
|
38
|
+
return
|
39
|
+
|
40
|
+
def is_solved(self) -> bool:
|
41
|
+
return self.__is_solved
|
42
|
+
|
43
|
+
@property
|
44
|
+
def fail_reason(self) -> str:
|
45
|
+
return self.__fail_reason
|
46
|
+
|
47
|
+
def is_good_response(self) -> bool:
|
48
|
+
return self.__is_good
|
49
|
+
|
50
|
+
def handle_payload(self, payload: dict) -> None:
|
51
|
+
# Implement this method and call self.success() or self.fail(fail_reason) if expected message is received
|
52
|
+
return
|
53
|
+
|
54
|
+
def handle_notification(self, notification: dict) -> None:
|
55
|
+
# Implement this method and call self.success() or self.fail(fail_reason) if expected message is received
|
56
|
+
return
|
57
|
+
|
58
|
+
def handle_heartbeat(self, heartbeat) -> None:
|
59
|
+
# Implement this method and call self.success() or self.fail(fail_reason) if expected message is received
|
60
|
+
return
|
61
|
+
|
62
|
+
|
63
|
+
class PipelineGenericNotificationResponse(Response):
|
64
|
+
def __init__(self, node, pipeline_name, success_code, fail_code) -> None:
|
65
|
+
super(PipelineGenericNotificationResponse, self).__init__()
|
66
|
+
|
67
|
+
self.node = node
|
68
|
+
self.pipeline_name = pipeline_name
|
69
|
+
|
70
|
+
self.success_code = success_code
|
71
|
+
self.fail_code = fail_code
|
72
|
+
return
|
73
|
+
|
74
|
+
def handle_notification(self, notification: dict) -> None:
|
75
|
+
if self.is_solved():
|
76
|
+
return
|
77
|
+
|
78
|
+
session_id = notification.get(PAYLOAD_DATA.SESSION_ID)
|
79
|
+
payload_path = notification.get(PAYLOAD_DATA.EE_PAYLOAD_PATH)
|
80
|
+
notification_code = notification.get("NOTIFICATION_CODE") # TODO
|
81
|
+
notification_message = notification.get(PAYLOAD_DATA.NOTIFICATION)
|
82
|
+
node = payload_path[0]
|
83
|
+
pipeline = payload_path[1]
|
84
|
+
|
85
|
+
# ignore session_id for now, until we decide on the behavior of the EE
|
86
|
+
same_node = node == self.node
|
87
|
+
same_pipeline = pipeline == self.pipeline_name
|
88
|
+
notification_code_ok = notification_code == self.success_code
|
89
|
+
notification_code_failed = notification_code == self.fail_code
|
90
|
+
|
91
|
+
if same_node and same_pipeline:
|
92
|
+
self.D("Received notification CODE={} for <{}: {}>. Message: {}".format(
|
93
|
+
notification_code, node, pipeline, notification_message))
|
94
|
+
if notification_code_ok:
|
95
|
+
self.success()
|
96
|
+
elif notification_code_failed:
|
97
|
+
self.fail(notification_message)
|
98
|
+
return
|
99
|
+
|
100
|
+
|
101
|
+
class InstanceGenericNotificationResponse(Response):
|
102
|
+
def __init__(self, node, pipeline_name, signature, instance_id, success_code, fail_code) -> None:
|
103
|
+
super(InstanceGenericNotificationResponse, self).__init__()
|
104
|
+
|
105
|
+
self.node = node
|
106
|
+
self.pipeline_name = pipeline_name
|
107
|
+
if signature is not None:
|
108
|
+
self.signature = signature.upper()
|
109
|
+
self.instance_id = instance_id
|
110
|
+
|
111
|
+
self.success_code = success_code
|
112
|
+
self.fail_code = fail_code
|
113
|
+
|
114
|
+
return
|
115
|
+
|
116
|
+
def handle_notification(self, notification: dict) -> None:
|
117
|
+
if self.is_solved():
|
118
|
+
return
|
119
|
+
|
120
|
+
session_id = notification.get(PAYLOAD_DATA.SESSION_ID)
|
121
|
+
payload_path = notification.get(PAYLOAD_DATA.EE_PAYLOAD_PATH)
|
122
|
+
notification_code = notification.get("NOTIFICATION_CODE") # TODO
|
123
|
+
notification_message = notification.get(PAYLOAD_DATA.NOTIFICATION)
|
124
|
+
notification_info = notification.get(PAYLOAD_DATA.INFO)
|
125
|
+
node = payload_path[0]
|
126
|
+
pipeline = payload_path[1]
|
127
|
+
signature = payload_path[2]
|
128
|
+
if signature is not None:
|
129
|
+
signature = signature.upper()
|
130
|
+
instance_id = payload_path[3]
|
131
|
+
|
132
|
+
# ignore session_id for now, until we decide on the behavior of the EE
|
133
|
+
same_node = node == self.node
|
134
|
+
same_pipeline = pipeline == self.pipeline_name
|
135
|
+
same_signature = signature == self.signature
|
136
|
+
same_instance_id = instance_id == self.instance_id
|
137
|
+
notification_code_ok = notification_code == self.success_code
|
138
|
+
notification_code_failed = notification_code == self.fail_code
|
139
|
+
|
140
|
+
if same_node and same_pipeline and same_signature and same_instance_id:
|
141
|
+
self.D("Received notification CODE={} for <{}: {}/{}/{}>. Message: {}\nInfo: {}".format(
|
142
|
+
notification_code, node, pipeline, signature, instance_id,
|
143
|
+
notification_message, notification_info))
|
144
|
+
if notification_code_ok:
|
145
|
+
self.success()
|
146
|
+
elif notification_code_failed:
|
147
|
+
self.fail(notification_info)
|
148
|
+
return
|
149
|
+
|
150
|
+
|
151
|
+
class PipelineOKResponse(PipelineGenericNotificationResponse):
|
152
|
+
def __init__(self, node, pipeline_name) -> None:
|
153
|
+
super(PipelineOKResponse, self).__init__(
|
154
|
+
node=node,
|
155
|
+
pipeline_name=pipeline_name,
|
156
|
+
success_code=NOTIFICATION_CODES.PIPELINE_OK,
|
157
|
+
fail_code=NOTIFICATION_CODES.PIPELINE_FAILED
|
158
|
+
)
|
159
|
+
return
|
160
|
+
|
161
|
+
|
162
|
+
class PipelineArchiveResponse(PipelineGenericNotificationResponse):
|
163
|
+
def __init__(self, node, pipeline_name) -> None:
|
164
|
+
super(PipelineArchiveResponse, self).__init__(
|
165
|
+
node=node,
|
166
|
+
pipeline_name=pipeline_name,
|
167
|
+
success_code=NOTIFICATION_CODES.PIPELINE_ARCHIVE_OK,
|
168
|
+
fail_code=NOTIFICATION_CODES.PIPELINE_ARCHIVE_FAILED
|
169
|
+
)
|
170
|
+
return
|
171
|
+
|
172
|
+
|
173
|
+
class PluginConfigInPauseOKResponse(InstanceGenericNotificationResponse):
|
174
|
+
def __init__(self, node, pipeline_name, signature, instance_id) -> None:
|
175
|
+
super(PluginConfigInPauseOKResponse, self).__init__(
|
176
|
+
node=node,
|
177
|
+
pipeline_name=pipeline_name,
|
178
|
+
signature=signature,
|
179
|
+
instance_id=instance_id,
|
180
|
+
success_code=NOTIFICATION_CODES.PLUGIN_CONFIG_IN_PAUSE_OK,
|
181
|
+
fail_code=NOTIFICATION_CODES.PLUGIN_CONFIG_IN_PAUSE_FAILED
|
182
|
+
)
|
183
|
+
return
|
184
|
+
|
185
|
+
|
186
|
+
class PluginConfigOKResponse(InstanceGenericNotificationResponse):
|
187
|
+
def __init__(self, node, pipeline_name, signature, instance_id) -> None:
|
188
|
+
super(PluginConfigOKResponse, self).__init__(
|
189
|
+
node=node,
|
190
|
+
pipeline_name=pipeline_name,
|
191
|
+
signature=signature,
|
192
|
+
instance_id=instance_id,
|
193
|
+
success_code=NOTIFICATION_CODES.PLUGIN_CONFIG_OK,
|
194
|
+
fail_code=NOTIFICATION_CODES.PLUGIN_CONFIG_FAILED
|
195
|
+
)
|
196
|
+
return
|
197
|
+
|
198
|
+
|
199
|
+
class PluginInstanceCommandOKResponse(InstanceGenericNotificationResponse):
|
200
|
+
def __init__(self, node, pipeline_name, signature, instance_id) -> None:
|
201
|
+
super(PluginInstanceCommandOKResponse, self).__init__(
|
202
|
+
node=node,
|
203
|
+
pipeline_name=pipeline_name,
|
204
|
+
signature=signature,
|
205
|
+
instance_id=instance_id,
|
206
|
+
success_code=NOTIFICATION_CODES.PLUGIN_INSTANCE_COMMAND_OK,
|
207
|
+
fail_code=NOTIFICATION_CODES.PLUGIN_INSTANCE_COMMAND_FAILED
|
208
|
+
)
|
209
|
+
return
|
@@ -0,0 +1,157 @@
|
|
1
|
+
from PyE2.base.responses import Response
|
2
|
+
# from .responses import Response
|
3
|
+
from time import time, sleep
|
4
|
+
|
5
|
+
|
6
|
+
class Transaction():
|
7
|
+
def __init__(self, log, session_id: str, *, lst_required_responses: list[Response] = None, timeout: int = 0, on_success_callback: callable = None, on_failure_callback: callable = None) -> None:
|
8
|
+
self.log = log
|
9
|
+
self.session_id = session_id
|
10
|
+
self.lst_required_responses = lst_required_responses
|
11
|
+
self.timeout = timeout
|
12
|
+
|
13
|
+
self.on_success_callback = on_success_callback
|
14
|
+
self.on_failure_callback = on_failure_callback
|
15
|
+
|
16
|
+
self.resolved_callback = None
|
17
|
+
self.__is_solved = False
|
18
|
+
self.__is_finished = False
|
19
|
+
|
20
|
+
self.start_time = time()
|
21
|
+
for response in self.lst_required_responses:
|
22
|
+
response.set_logger(log)
|
23
|
+
|
24
|
+
return
|
25
|
+
|
26
|
+
def get_unsolved_responses(self) -> list[Response]:
|
27
|
+
"""
|
28
|
+
Returns a list of unsolved responses in the transaction.
|
29
|
+
|
30
|
+
Returns
|
31
|
+
-------
|
32
|
+
list[Response]
|
33
|
+
List of unsolved responses in the transaction.
|
34
|
+
"""
|
35
|
+
return [response for response in self.lst_required_responses if not response.is_solved()]
|
36
|
+
|
37
|
+
def is_solved(self) -> bool:
|
38
|
+
"""
|
39
|
+
Returns whether the transaction is solved or not.
|
40
|
+
If the transaction is solved in this call, the resolved_callback is set to the appropriate callback function.
|
41
|
+
|
42
|
+
Returns
|
43
|
+
-------
|
44
|
+
bool
|
45
|
+
Whether the transaction is solved or not.
|
46
|
+
"""
|
47
|
+
|
48
|
+
# if the transaction is already solved, return True
|
49
|
+
if self.__is_solved:
|
50
|
+
return True
|
51
|
+
|
52
|
+
# first check if all responses are solved
|
53
|
+
all_responses_solved = all([response.is_solved() for response in self.lst_required_responses])
|
54
|
+
if all_responses_solved:
|
55
|
+
self.__is_solved = True
|
56
|
+
|
57
|
+
all_responses_good = all([response.is_good_response() for response in self.lst_required_responses])
|
58
|
+
if all_responses_good:
|
59
|
+
self.resolved_callback = self.on_success_callback
|
60
|
+
else:
|
61
|
+
if not self.on_failure_callback:
|
62
|
+
self.resolved_callback = lambda: self.log.P("Transaction failed")
|
63
|
+
else:
|
64
|
+
fail_reasons = [
|
65
|
+
response.fail_reason for response in self.lst_required_responses if not response.is_good_response()]
|
66
|
+
self.resolved_callback = lambda: self.on_failure_callback(fail_reasons)
|
67
|
+
# endif computing resolved_callback for failure
|
68
|
+
# endif computing resolved_callback
|
69
|
+
return True
|
70
|
+
# endif all responses solved
|
71
|
+
|
72
|
+
# if the transaction is not solved, check if the transaction has timed out
|
73
|
+
elapsed_time = time() - self.start_time
|
74
|
+
if self.timeout > 0 and elapsed_time > self.timeout:
|
75
|
+
# Timeout occurred
|
76
|
+
self.__is_solved = True
|
77
|
+
|
78
|
+
fail_reason = f"Transaction timeout ({self.timeout}s). Responses not received: "
|
79
|
+
fail_reason += ", ".join([str(response) for response in self.lst_required_responses if not response.is_solved()])
|
80
|
+
|
81
|
+
if not self.on_failure_callback:
|
82
|
+
self.resolved_callback = lambda: self.log.P(fail_reason)
|
83
|
+
else:
|
84
|
+
self.resolved_callback = lambda: self.on_failure_callback([fail_reason])
|
85
|
+
return True
|
86
|
+
|
87
|
+
return False
|
88
|
+
|
89
|
+
def is_finished(self) -> bool:
|
90
|
+
"""
|
91
|
+
Returns whether the transaction is finished or not.
|
92
|
+
A transaction finishes when the callback is called.
|
93
|
+
|
94
|
+
Returns
|
95
|
+
-------
|
96
|
+
bool
|
97
|
+
Whether the transaction is finished or not.
|
98
|
+
"""
|
99
|
+
return self.__is_finished
|
100
|
+
|
101
|
+
def handle_payload(self, payload: dict) -> None:
|
102
|
+
"""
|
103
|
+
This method is called when a payload is received from the server.
|
104
|
+
This method calls `handle_payload()` method of all the unsolved responses in the `lst_required_responses`.
|
105
|
+
|
106
|
+
Parameters
|
107
|
+
----------
|
108
|
+
payload : dict
|
109
|
+
The payload received from the server.
|
110
|
+
"""
|
111
|
+
unsolved_responses = self.get_unsolved_responses()
|
112
|
+
|
113
|
+
for response in unsolved_responses:
|
114
|
+
response.handle_payload(payload)
|
115
|
+
return
|
116
|
+
|
117
|
+
def handle_notification(self, notification: dict) -> None:
|
118
|
+
"""
|
119
|
+
This method is called when a notification is received from the server.
|
120
|
+
This method calls `handle_notification()` method of all the unsolved responses in the `lst_required_responses`.
|
121
|
+
|
122
|
+
Parameters
|
123
|
+
----------
|
124
|
+
notification : dict
|
125
|
+
The notification received from the server.
|
126
|
+
"""
|
127
|
+
unsolved_responses = self.get_unsolved_responses()
|
128
|
+
|
129
|
+
for response in unsolved_responses:
|
130
|
+
response.handle_notification(notification)
|
131
|
+
return
|
132
|
+
|
133
|
+
def handle_heartbeat(self, heartbeat) -> None:
|
134
|
+
"""
|
135
|
+
This method is called when a heartbeat is received from the server.
|
136
|
+
This method calls `handle_heartbeat()` method of all the unsolved responses in the `lst_required_responses`.
|
137
|
+
|
138
|
+
Parameters
|
139
|
+
----------
|
140
|
+
heartbeat : dict
|
141
|
+
The heartbeat received from the server.
|
142
|
+
"""
|
143
|
+
unsolved_responses = self.get_unsolved_responses()
|
144
|
+
|
145
|
+
for response in unsolved_responses:
|
146
|
+
response.handle_heartbeat(heartbeat)
|
147
|
+
return
|
148
|
+
|
149
|
+
def callback(self):
|
150
|
+
"""
|
151
|
+
Calls the resolved_callback only if the transaction is solved.
|
152
|
+
"""
|
153
|
+
if self.__is_solved:
|
154
|
+
if self.resolved_callback:
|
155
|
+
self.resolved_callback()
|
156
|
+
self.__is_finished = True
|
157
|
+
return
|
@@ -0,0 +1,143 @@
|
|
1
|
+
from .logging import Logger
|
2
|
+
|
3
|
+
|
4
|
+
class BaseDecentrAIObject(object):
|
5
|
+
"""
|
6
|
+
Generic class
|
7
|
+
|
8
|
+
Instructions:
|
9
|
+
|
10
|
+
1. use `super().__init__(**kwargs)` at the end of child `__init__`
|
11
|
+
2. define `startup(self)` method for the child class and call
|
12
|
+
`super().startup()` at beginning of `startup()` method
|
13
|
+
|
14
|
+
OR
|
15
|
+
|
16
|
+
use `super().__init__(**kwargs)` at beginning of child `__init__` and then
|
17
|
+
you can safely proceed with other initilization
|
18
|
+
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(self, log: Logger,
|
22
|
+
create_logger=False,
|
23
|
+
DEBUG=False,
|
24
|
+
show_prefixes=False,
|
25
|
+
prefix_log=None,
|
26
|
+
log_at_startup=False,
|
27
|
+
**kwargs):
|
28
|
+
|
29
|
+
super(BaseDecentrAIObject, self).__init__()
|
30
|
+
|
31
|
+
if (log is None) or not hasattr(log, '_logger'):
|
32
|
+
if not create_logger:
|
33
|
+
raise ValueError("Logger object is invalid: {}".format(log))
|
34
|
+
else:
|
35
|
+
log = Logger(DEBUG=DEBUG, base_folder='.', app_folder='_local_cache')
|
36
|
+
# endif
|
37
|
+
|
38
|
+
self.log = log
|
39
|
+
self.show_prefixes = show_prefixes
|
40
|
+
self.prefix_log = prefix_log
|
41
|
+
self.config_data = self.log.config_data
|
42
|
+
self.DEBUG = DEBUG
|
43
|
+
self.log_at_startup = log_at_startup
|
44
|
+
|
45
|
+
if not hasattr(self, '__name__'):
|
46
|
+
self.__name__ = self.__class__.__name__
|
47
|
+
self.startup()
|
48
|
+
|
49
|
+
return
|
50
|
+
|
51
|
+
def startup(self):
|
52
|
+
self.log.set_nice_prints()
|
53
|
+
ver = ''
|
54
|
+
if hasattr(self, '__version__'):
|
55
|
+
ver = 'v.' + self.__version__
|
56
|
+
if hasattr(self, 'version'):
|
57
|
+
ver = 'v.' + self.version
|
58
|
+
|
59
|
+
if self.log_at_startup:
|
60
|
+
self.P("{}{} startup.".format(self.__class__.__name__, ' ' + ver if ver != '' else ''))
|
61
|
+
return
|
62
|
+
|
63
|
+
def shutdown(self):
|
64
|
+
self.P("Shutdown in progress...")
|
65
|
+
_VARS = ['sess', 'session']
|
66
|
+
for var_name in _VARS:
|
67
|
+
if vars(self).get(var_name, None) is not None:
|
68
|
+
self.P("Warning: {} property {} still not none before closing".format(
|
69
|
+
self.__class__.__name__, var_name), color='r')
|
70
|
+
return
|
71
|
+
|
72
|
+
def P(self, s, t=False, color=None, prefix=False, **kwargs):
|
73
|
+
if self.show_prefixes or prefix:
|
74
|
+
msg = "[{}] {}".format(self.__name__, s)
|
75
|
+
else:
|
76
|
+
if self.prefix_log is None:
|
77
|
+
msg = "{}".format(s)
|
78
|
+
else:
|
79
|
+
msg = "{} {}".format(self.prefix_log, s)
|
80
|
+
# endif
|
81
|
+
# endif
|
82
|
+
|
83
|
+
_r = self.log.P(msg, show_time=t, color=color, **kwargs)
|
84
|
+
return _r
|
85
|
+
|
86
|
+
def D(self, s, t=False, color=None, prefix=False, **kwargs):
|
87
|
+
_r = -1
|
88
|
+
if self.DEBUG:
|
89
|
+
if self.show_prefixes:
|
90
|
+
msg = "[DEBUG] {}: {}".format(self.__name__, s)
|
91
|
+
else:
|
92
|
+
if self.prefix_log is None:
|
93
|
+
msg = "[DEBUG] {}".format(s)
|
94
|
+
else:
|
95
|
+
msg = "[DEBUG]{} {}".format(self.prefix_log, s)
|
96
|
+
# endif
|
97
|
+
# endif
|
98
|
+
_r = self.log.P(msg, show_time=t, color=color, prefix=prefix, **kwargs)
|
99
|
+
# endif
|
100
|
+
return _r
|
101
|
+
|
102
|
+
def start_timer(self, tmr_id):
|
103
|
+
if hasattr(self, '_timers_section'):
|
104
|
+
return self.log.start_timer(tmr_id, section=self._timers_section)
|
105
|
+
else:
|
106
|
+
return self.log.start_timer(sname=self.__name__ + '_' + tmr_id)
|
107
|
+
|
108
|
+
def end_timer(self, tmr_id, skip_first_timing=True, **kwargs):
|
109
|
+
if hasattr(self, '_timers_section'):
|
110
|
+
return self.log.end_timer(tmr_id, section=self._timers_section)
|
111
|
+
else:
|
112
|
+
return self.log.end_timer(
|
113
|
+
sname=self.__name__ + '_' + tmr_id,
|
114
|
+
skip_first_timing=skip_first_timing,
|
115
|
+
**kwargs
|
116
|
+
)
|
117
|
+
|
118
|
+
def raise_error(self, error_text):
|
119
|
+
"""
|
120
|
+
logs the error and raises it
|
121
|
+
"""
|
122
|
+
self.P("{}: {}".format(self.__class__.__name__, error_text))
|
123
|
+
raise ValueError(error_text)
|
124
|
+
|
125
|
+
def timer_name(self, name=''):
|
126
|
+
tn = ''
|
127
|
+
if name == '':
|
128
|
+
tn = self.__class__.__name__
|
129
|
+
else:
|
130
|
+
tn = '{}__{}'.format(self.__class__.__name__, name)
|
131
|
+
return tn
|
132
|
+
|
133
|
+
def __repr__(self):
|
134
|
+
# Get the name of the class
|
135
|
+
class_name = self.__class__.__name__
|
136
|
+
|
137
|
+
# Get public properties (those not starting with "_")
|
138
|
+
public_properties = {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
|
139
|
+
|
140
|
+
# Convert properties to a string representation
|
141
|
+
properties_str = ", ".join(f"{k}={v!r}" for k, v in public_properties.items())
|
142
|
+
|
143
|
+
return f"{class_name}({properties_str})"
|