holado 0.9.3__py3-none-any.whl → 0.10.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 +24 -6
- holado/common/context/session_context.py +5 -4
- holado/holado_config.py +4 -1
- {holado-0.9.3.dist-info → holado-0.10.1.dist-info}/METADATA +1 -1
- {holado-0.9.3.dist-info → holado-0.10.1.dist-info}/RECORD +48 -47
- holado_ais/ais/ais_messages.py +33 -3
- holado_ais/tests/behave/steps/ais/ais_messages_steps.py +23 -3
- holado_core/common/tools/path_manager.py +6 -3
- holado_docker/tools/docker_controller/server/rest/run.py +5 -2
- holado_docker/tools/docker_viewer/server/rest/run.py +5 -2
- holado_logging/common/logging/log_manager.py +71 -29
- holado_multitask/multithreading/context/thread_context.py +3 -1
- holado_python/standard_library/queue.py +1 -1
- holado_python/standard_library/ssl/resources/certificates/tcpbin.crt +16 -16
- holado_python/standard_library/ssl/resources/certificates/tcpbin.key +26 -26
- holado_scripting/__init__.py +2 -1
- holado_scripting/common/tools/variable_manager.py +42 -9
- holado_test/common/context/feature_context.py +3 -1
- holado_test/common/context/scenario_context.py +3 -1
- holado_test/test_server/server/rest/run.py +2 -1
- test_holado/environment.py +3 -1
- test_holado/features/NonReg/holado_ais/ais_message-bitarray_to_nmea.feature +1 -1
- test_holado/features/NonReg/holado_ais/ais_message-nmea_raw_to_dict.feature +93 -0
- test_holado/features/NonReg/holado_ais/message_types/type-10.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-12.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-14.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-15.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-16.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-17.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-18.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-19.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-1_2_3.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-20.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-21.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-22.feature +2 -2
- test_holado/features/NonReg/holado_ais/message_types/type-23.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-24.feature +2 -2
- test_holado/features/NonReg/holado_ais/message_types/type-25.feature +4 -4
- test_holado/features/NonReg/holado_ais/message_types/type-26.feature +4 -4
- test_holado/features/NonReg/holado_ais/message_types/type-27.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-4_11.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-5.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-6.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-7_13.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-8.feature +1 -1
- test_holado/features/NonReg/holado_ais/message_types/type-9.feature +1 -1
- {holado-0.9.3.dist-info → holado-0.10.1.dist-info}/WHEEL +0 -0
- {holado-0.9.3.dist-info → holado-0.10.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -39,6 +39,7 @@ class LogManager(object):
|
|
|
39
39
|
self.on_console = False
|
|
40
40
|
self.__console_handler = None
|
|
41
41
|
|
|
42
|
+
# Manage file handlers
|
|
42
43
|
self.in_file = True
|
|
43
44
|
self.__files_lock = threading.Lock()
|
|
44
45
|
self.__file_names = []
|
|
@@ -47,20 +48,26 @@ class LogManager(object):
|
|
|
47
48
|
self.__root_file_handler = None
|
|
48
49
|
self.__root_file_handler_active = False
|
|
49
50
|
|
|
51
|
+
# Manage file paths LIFO by loggers
|
|
52
|
+
self.__files_by_logger = {}
|
|
53
|
+
|
|
50
54
|
# Initialize format according python version
|
|
51
55
|
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
52
56
|
if MultitaskManager.has_thread_native_id():
|
|
53
57
|
# Exists since python 3.8
|
|
54
58
|
# self.format = '{asctime:s} | {thread_native_id:-5d} | {levelname:5s} | {name:50s} | {message:s}'
|
|
55
59
|
self.format = '{asctime:s} | {process:-5d}-{thread_native_id:-5d} | {levelname:5s} | {name:50s} | {message:s}'
|
|
60
|
+
self.format_short = '{asctime:s} | {message:s}'
|
|
56
61
|
self.style = '{'
|
|
57
62
|
else:
|
|
58
63
|
if sys.version_info > (3, 2):
|
|
59
64
|
# self.format = '{asctime:s} | {thread:-5d} | {levelname:5s} | {module:35s} | {message:s}'
|
|
60
65
|
self.format = '{asctime:s} | {process:-5d}-{thread:-5d} | {levelname:5s} | {name:50s} | {message:s}'
|
|
66
|
+
self.format_short = '{asctime:s} | {message:s}'
|
|
61
67
|
self.style = '{'
|
|
62
68
|
else:
|
|
63
69
|
self.format = '%(asctime)s | %(process)-5d-%(thread)-5d | %(levelname)5s | %(module)35s | %(message)s'
|
|
70
|
+
self.format_short = '%(asctime)s | %(message)s'
|
|
64
71
|
self.style = '%'
|
|
65
72
|
|
|
66
73
|
def configure(self):
|
|
@@ -193,7 +200,6 @@ class LogManager(object):
|
|
|
193
200
|
|
|
194
201
|
def add_root_file_handler(self):
|
|
195
202
|
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
196
|
-
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
197
203
|
|
|
198
204
|
logger_ = logging.getLogger()
|
|
199
205
|
|
|
@@ -201,13 +207,8 @@ class LogManager(object):
|
|
|
201
207
|
raise TechnicalException("Root log file is not defined")
|
|
202
208
|
|
|
203
209
|
if self.__root_file_handler is None:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
self.__root_file_handler = logging.FileHandler(self.__root_file_name, mode='w', encoding='utf8')
|
|
208
|
-
self.__root_file_handler.setFormatter(logging.Formatter(fmt=self.format, style=self.style))
|
|
209
|
-
if MultitaskManager.has_thread_native_id():
|
|
210
|
-
self.__root_file_handler.addFilter(filter_thread_native_id)
|
|
210
|
+
logger.info("Creating file handler to root file '{}'.".format(self.__root_file_name))
|
|
211
|
+
self.__root_file_handler = self.__new_file_handler(self.__root_file_name)
|
|
211
212
|
|
|
212
213
|
logger_.addHandler(self.__root_file_handler)
|
|
213
214
|
self.__root_file_handler_active = True
|
|
@@ -215,15 +216,13 @@ class LogManager(object):
|
|
|
215
216
|
def remove_root_file_handler(self, do_reset=False):
|
|
216
217
|
logger_ = logging.getLogger()
|
|
217
218
|
if self.__root_file_handler:
|
|
218
|
-
|
|
219
|
+
logger.info(f"Removing log destination to root file '{self.__root_file_name}'.")
|
|
219
220
|
logger_.removeHandler(self.__root_file_handler)
|
|
220
221
|
self.__root_file_handler_active = False
|
|
221
222
|
if do_reset:
|
|
222
223
|
self.__root_file_handler = None
|
|
223
224
|
|
|
224
225
|
def add_file_handler(self, file_name, logger_=None):
|
|
225
|
-
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
226
|
-
|
|
227
226
|
if logger_ is None:
|
|
228
227
|
logger_ = logging.getLogger()
|
|
229
228
|
|
|
@@ -232,35 +231,59 @@ class LogManager(object):
|
|
|
232
231
|
self.add_log_file(file_name)
|
|
233
232
|
|
|
234
233
|
if file_name in self.__file_handlers:
|
|
235
|
-
|
|
234
|
+
logger.debug("Log destination already set to file '{}'.".format(file_name))
|
|
236
235
|
else:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
file_handler = logging.FileHandler(file_name, mode='w', encoding='utf8')
|
|
241
|
-
file_handler.setFormatter(logging.Formatter(fmt=self.format, style=self.style))
|
|
242
|
-
if MultitaskManager.has_thread_native_id():
|
|
243
|
-
file_handler.addFilter(filter_thread_native_id)
|
|
244
|
-
|
|
236
|
+
logger.info("Adding log destination to file '{}'.".format(file_name))
|
|
237
|
+
file_handler = self.__new_file_handler(file_name)
|
|
245
238
|
self.__file_handlers[file_name] = file_handler
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
def
|
|
249
|
-
from
|
|
239
|
+
self.add_existing_file_handler_to_logger(file_name, logger_)
|
|
240
|
+
|
|
241
|
+
def __new_file_handler(self, file_path, use_format_short=False):
|
|
242
|
+
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
243
|
+
|
|
244
|
+
Path(os.path.dirname(file_path)).mkdir(parents=True, exist_ok=True)
|
|
245
|
+
|
|
246
|
+
res = logging.FileHandler(file_path, mode='w', encoding='utf8')
|
|
247
|
+
fmt = self.format_short if use_format_short else self.format
|
|
248
|
+
res.setFormatter(logging.Formatter(fmt=fmt, style=self.style))
|
|
249
|
+
if MultitaskManager.has_thread_native_id():
|
|
250
|
+
res.addFilter(filter_thread_native_id)
|
|
250
251
|
|
|
252
|
+
return res
|
|
253
|
+
|
|
254
|
+
def remove_file_handler(self, file_name, logger_=None, do_remove_log_file=True):
|
|
251
255
|
if logger_ is None:
|
|
252
256
|
logger_ = logging.getLogger()
|
|
253
257
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
logger_.info("Removing log destination to file '{}'.".format(file_name))
|
|
258
|
-
logger_.removeHandler(self.__file_handlers[file_name])
|
|
258
|
+
logger.info("Removing log destination to file '{}'.".format(file_name))
|
|
259
|
+
self.remove_existing_file_handler_from_logger(file_name, logger_)
|
|
259
260
|
del self.__file_handlers[file_name]
|
|
260
261
|
|
|
261
262
|
if do_remove_log_file:
|
|
262
263
|
self.remove_log_file(file_name)
|
|
263
264
|
|
|
265
|
+
def add_existing_file_handler_to_logger(self, file_name, logger_):
|
|
266
|
+
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
267
|
+
|
|
268
|
+
if self.__root_file_name == file_name:
|
|
269
|
+
file_handler = self.__root_file_handler
|
|
270
|
+
else:
|
|
271
|
+
if file_name not in self.__file_handlers:
|
|
272
|
+
raise TechnicalException(f"Not set log destination to file '{file_name}'")
|
|
273
|
+
file_handler = self.__file_handlers[file_name]
|
|
274
|
+
logger_.addHandler(file_handler)
|
|
275
|
+
|
|
276
|
+
def remove_existing_file_handler_from_logger(self, file_name, logger_):
|
|
277
|
+
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
278
|
+
|
|
279
|
+
if self.__root_file_name == file_name:
|
|
280
|
+
file_handler = self.__root_file_handler
|
|
281
|
+
else:
|
|
282
|
+
if file_name not in self.__file_handlers:
|
|
283
|
+
raise TechnicalException(f"Not set log destination to file '{file_name}'")
|
|
284
|
+
file_handler = self.__file_handlers[file_name]
|
|
285
|
+
logger_.removeHandler(file_handler)
|
|
286
|
+
|
|
264
287
|
def __remove_existing_file_handlers(self, log_level_if_exists=None):
|
|
265
288
|
with self.__files_lock:
|
|
266
289
|
if len(self.__file_names) > 0:
|
|
@@ -289,5 +312,24 @@ class LogManager(object):
|
|
|
289
312
|
self.add_root_file_handler()
|
|
290
313
|
self.remove_file_handler(file_name, do_remove_log_file=do_remove_log_file)
|
|
291
314
|
|
|
315
|
+
def enter_log_file_for_logger(self, logger_, file_path, use_format_short=False, switch_in=True):
|
|
316
|
+
logger_name = logger_.name
|
|
317
|
+
if logger_name not in self.__files_by_logger:
|
|
318
|
+
self.__files_by_logger[logger_name] = []
|
|
319
|
+
|
|
320
|
+
if switch_in and len(self.__files_by_logger[logger_name]) > 0:
|
|
321
|
+
logger_.removeHandler(self.__files_by_logger[logger_name][-1][1])
|
|
322
|
+
|
|
323
|
+
file_handler = self.__new_file_handler(file_path, use_format_short=use_format_short)
|
|
324
|
+
logger_.addHandler(file_handler)
|
|
325
|
+
self.__files_by_logger[logger_name].append( (file_path, file_handler) )
|
|
326
|
+
|
|
327
|
+
def leave_log_file_for_logger(self, logger_, switch_out=True):
|
|
328
|
+
logger_name = logger_.name
|
|
329
|
+
_, file_handler = self.__files_by_logger[logger_name].pop()
|
|
330
|
+
logger_.removeHandler(file_handler)
|
|
331
|
+
|
|
332
|
+
if switch_out and len(self.__files_by_logger[logger_name]) > 0:
|
|
333
|
+
logger_.addHandler(self.__files_by_logger[logger_name][-1][1])
|
|
292
334
|
|
|
293
335
|
|
|
@@ -61,7 +61,9 @@ class ThreadContext(Context):
|
|
|
61
61
|
|
|
62
62
|
manager = VariableManager(var_man)
|
|
63
63
|
self.set_object("variable_manager", manager)
|
|
64
|
-
|
|
64
|
+
file_path = SessionContext.instance().report_manager.get_path("logs", f"variable_update-thread_{self.thread_uid}.log")
|
|
65
|
+
manager.initialize(SessionContext.instance().dynamic_text_manager, SessionContext.instance().unique_value_manager,
|
|
66
|
+
variable_update_log_file_path=file_path)
|
|
65
67
|
return self.get_object("variable_manager")
|
|
66
68
|
|
|
67
69
|
|
|
@@ -61,7 +61,7 @@ class IterableQueue(queue.Queue, typing.Iterable):
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
class IterableLifoQueue(IterableQueue):
|
|
64
|
-
'''
|
|
64
|
+
'''Copy of implementation of queue.LifoQueue but inheriting of IterableQueue.'''
|
|
65
65
|
|
|
66
66
|
def _init(self, maxsize):
|
|
67
67
|
self.queue = []
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
MIIDZTCCAk2gAwIBAgIBKjANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMCVVMx
|
|
3
3
|
CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZ0
|
|
4
4
|
Y3BiaW4xDDAKBgNVBAsMA29wczETMBEGA1UEAwwKdGNwYmluLmNvbTEjMCEGCSqG
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
FOLuMowBSAZfV5v82LmlaIIOvU/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
SIb3DQEJARYUaGFycnliYWdkaUBnbWFpbC5jb20wHhcNMjUxMDE2MjIzNTE5WhcN
|
|
6
|
+
MjUxMDE3MjIzNTE5WjAcMRowGAYDVQQDDBF0Y3BiaW4uY29tLWNsaWVudDCCASIw
|
|
7
|
+
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMxmg8CRudZQj9pgRnvPQrWyqn1A
|
|
8
|
+
55RlXoax8OMEeEQHhreCOj69WV6K9OvHebbAtMNCEyXFwNUNX1XjlhhLcqhY5yLR
|
|
9
|
+
5k9vgOoq2ribBwdMRnYyIajWp7y53L/J35Qf2FWNeS+3AXv/mWiYnGpTJZHXCMyo
|
|
10
|
+
wOgDqeqz5wzl8ncvj5HWBkZm/mPDwK6fR/4SXMv+NIBooUKGZTST/1Q75/tvPhwf
|
|
11
|
+
dpGWTUd1xKw3TKz63B+jAATdPbIxTnSxJY1uLdBZ1hUguGxrC+nvqgY0283lVz3n
|
|
12
|
+
Jz7P2BCwmwmgRwBLIUw1381QuFJjGlKSglw/HraIfVyJASQqEk2gVil5Gr8CAwEA
|
|
13
|
+
AaNCMEAwHQYDVR0OBBYEFMQRuiY7hUUnl5wxL6R6gnlhyXaiMB8GA1UdIwQYMBaA
|
|
14
|
+
FOLuMowBSAZfV5v82LmlaIIOvU/DMA0GCSqGSIb3DQEBCwUAA4IBAQBAX/CniZsN
|
|
15
|
+
9YWuDt7CS+YBpLRe46ryZXzmACpmz4uDzRs+3MRnCtOz1121dW0+zuPMdopxwjG2
|
|
16
|
+
GyPirI1mDasoJDn5jRWP1NBvuFN7fcAVsMDi3vBMfzd+oV4Pcgi7uydcd0zX+onp
|
|
17
|
+
1QIyNwAulQB03gfe6IcPAUwyTOtJoc7yo1W6eH/W+RGmj5BaUP+5SB3EHjqih6ds
|
|
18
|
+
xPc4yJ43N1gYsXRZDoYuqmy+/h0JQmFupPJRAbOFbh3IsunbLXvsKXzlrgKlhsCg
|
|
19
|
+
H0Kc97t7ZQNCzgymNnxsbepNddWwGF8hAj4FruFYtO9rt00aT2bqb9Yw4pRJ+fM8
|
|
20
|
+
nDVx1r7BCieF
|
|
21
21
|
-----END CERTIFICATE-----
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
2
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMZoPAkbnWUI/a
|
|
3
|
+
YEZ7z0K1sqp9QOeUZV6GsfDjBHhEB4a3gjo+vVleivTrx3m2wLTDQhMlxcDVDV9V
|
|
4
|
+
45YYS3KoWOci0eZPb4DqKtq4mwcHTEZ2MiGo1qe8udy/yd+UH9hVjXkvtwF7/5lo
|
|
5
|
+
mJxqUyWR1wjMqMDoA6nqs+cM5fJ3L4+R1gZGZv5jw8Cun0f+ElzL/jSAaKFChmU0
|
|
6
|
+
k/9UO+f7bz4cH3aRlk1HdcSsN0ys+twfowAE3T2yMU50sSWNbi3QWdYVILhsawvp
|
|
7
|
+
76oGNNvN5Vc95yc+z9gQsJsJoEcASyFMNd/NULhSYxpSkoJcPx62iH1ciQEkKhJN
|
|
8
|
+
oFYpeRq/AgMBAAECggEAUKjruSRIl6A3BFAVwGnrw1P8H21rdY4DHVg+3Pc4lm/5
|
|
9
|
+
45TKc1O5XqurNxgCmfG144/BiphdHjYmtvgWlQPA/VoH7B+0qQgxcTb0FQFoZqLc
|
|
10
|
+
82uZCM2cZ8dYq354cjWW4zvu5LttJIea/EGtB/BD1SdsW4cEiQpZFTtlJBvh8NHo
|
|
11
|
+
7+o0mPwwBrXmadsLlxDmhQ0Wsw4ltaK7eMBJlLalg9f/3uW4ArW0OXVK1ycszNXM
|
|
12
|
+
2pfrp9zKYcPzWEP+wrC/6f+AXFDacUIzwxsfNtlI7O57t8pQXf5pkyeBHHlxCvN/
|
|
13
|
+
XYx+UBWip6tRnlZRqNvl/8NC0JpX9P8xaeNp21haAQKBgQD1rlkZ9umlmC9PB5oc
|
|
14
|
+
Tp00KC5KQmgfqRfEBEVzmm4yGHK0OMx0pCnP/ZONZaE4QX4TmeLCnUxgYCdxl6ep
|
|
15
|
+
406g0i2ig7M+RZ18skh4ubpoiQlLIoNW2mOpV/Hzt53st0HAYogPubrVZAnn/KwA
|
|
16
|
+
zehlj0w1yljBXDsK9c6deCdIgQKBgQDU/E12s8aCC0ngOSZqe0lkDWU/yQfX8BnJ
|
|
17
|
+
cSA3dU1mwGzP+02N5AXZuxwUql1rjE45ERPISQ2+eHtUk3n7QH0+7KNRmj7Jk9xC
|
|
18
|
+
QIN5lExdO3tAXo/muH6PCkyeNrkRSdfNgssYMVJZqbD8O5IM6v6yEbQHOxuskvvu
|
|
19
|
+
uWRxQZTDPwKBgEfqcUqYbGx8z9xibUo7+Oh7mpFCPxiFdt96IJpmajtfzLPUrIS4
|
|
20
|
+
SUUJBVgul7LP+Qfj0+0D/od3nhQyQHIKh8mrvJAF3UItPpxx06UDOP3An2fPAoM6
|
|
21
|
+
ClJX3AtrhF72hdi6/vkbdQVh80RlQjQ6Ef0opTZZtQFk7iOXMJQHx/gBAoGAahxl
|
|
22
|
+
T41Tifirzq1KaWSQ9OsDlZrHcJrrjgPxZA/qBxY5YAk440dGbuqcm+Mg9fMKCb5r
|
|
23
|
+
V66lzU5jS4jKDhZcD9x/pakuPOmQo+VWW106Cn0W88Po967VRth/wZdL7sQWYwoV
|
|
24
|
+
uzDfcVJsnc3j/tGZIQhW4/9b00fLgm0VEKP2xKsCgYEAkylyhMcTA9nuiBGecBFW
|
|
25
|
+
fRbuL6tWcnj3b8lnNOoBFTp6uVSi7VTYcZttGP7zLa9v/LRegawpf1meOarn80Wo
|
|
26
|
+
pz1Ot3ZEgx6iArdgdejSHbps58dTpoXp6YBlZR08G5tw2aHfppJYq2Vz3RLrv5Kf
|
|
27
|
+
k6MQ4yJFgkb+8+cpvp3NxgA=
|
|
28
28
|
-----END PRIVATE KEY-----
|
holado_scripting/__init__.py
CHANGED
|
@@ -27,7 +27,8 @@ def register():
|
|
|
27
27
|
from holado_scripting.common.tools.variable_manager import VariableManager
|
|
28
28
|
SessionContext.instance().services.register_service_type("variable_manager", VariableManager,
|
|
29
29
|
lambda m: m.initialize(SessionContext.instance().dynamic_text_manager,
|
|
30
|
-
SessionContext.instance().unique_value_manager
|
|
30
|
+
SessionContext.instance().unique_value_manager,
|
|
31
|
+
variable_update_log_file_path=SessionContext.instance().report_manager.get_path("logs", "variable_update.log") ) )
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
from holado_scripting.common.tools.expression_evaluator import ExpressionEvaluator
|
|
@@ -22,8 +22,10 @@ from typing import NamedTuple
|
|
|
22
22
|
import threading
|
|
23
23
|
from holado.common.tools.gc_manager import GcManager
|
|
24
24
|
from holado_python.standard_library.typing import Typing
|
|
25
|
+
from holado.common.context.session_context import SessionContext
|
|
25
26
|
|
|
26
27
|
logger = logging.getLogger(__name__)
|
|
28
|
+
# logger_update = logging.getLogger(__name__ + ".update")
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
class VariableManager(DeleteableObject):
|
|
@@ -46,9 +48,22 @@ class VariableManager(DeleteableObject):
|
|
|
46
48
|
self.__temporary_variables_lock = threading.Lock()
|
|
47
49
|
self.__temporary_variables = {}
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
# Manage variable update log file
|
|
52
|
+
self.__variable_update_log_file_path = None
|
|
53
|
+
self.__is_entered_in_variable_update_log_file = False
|
|
54
|
+
self.__logger_update = logging.getLogger(__name__ + f".update.{id(self)}")
|
|
55
|
+
|
|
56
|
+
def initialize(self, dynamic_text_manager, unique_value_manager, variable_update_log_file_path=None):
|
|
57
|
+
""" Initialize variable manager
|
|
58
|
+
@param dynamic_text_manager Dynamic text manager instance to use
|
|
59
|
+
@param unique_value_manager Unique value manager instance to use
|
|
60
|
+
@param variable_update_log_filename If defined, log all variable updates in given file in addition to normal logs
|
|
61
|
+
"""
|
|
50
62
|
self.__dynamic_text_manager = dynamic_text_manager
|
|
51
63
|
self.__unique_value_manager = unique_value_manager
|
|
64
|
+
|
|
65
|
+
# Manage variable update log file
|
|
66
|
+
self.__variable_update_log_file_path = variable_update_log_file_path
|
|
52
67
|
|
|
53
68
|
@property
|
|
54
69
|
def parent(self):
|
|
@@ -71,6 +86,19 @@ class VariableManager(DeleteableObject):
|
|
|
71
86
|
# # Clear variables
|
|
72
87
|
# self.__variables.clear()
|
|
73
88
|
|
|
89
|
+
# Leave variable update log file
|
|
90
|
+
self.__leave_variable_update_log_file()
|
|
91
|
+
|
|
92
|
+
def __enter_variable_update_log_file(self):
|
|
93
|
+
if self.__variable_update_log_file_path is not None and not self.__is_entered_in_variable_update_log_file:
|
|
94
|
+
SessionContext.instance().log_manager.enter_log_file_for_logger(self.__logger_update, self.__variable_update_log_file_path, use_format_short=True)
|
|
95
|
+
self.__is_entered_in_variable_update_log_file = True
|
|
96
|
+
|
|
97
|
+
def __leave_variable_update_log_file(self):
|
|
98
|
+
if self.__variable_update_log_file_path is not None and self.__is_entered_in_variable_update_log_file:
|
|
99
|
+
SessionContext.instance().log_manager.leave_log_file_for_logger(self.__logger_update)
|
|
100
|
+
self.__is_entered_in_variable_update_log_file = False
|
|
101
|
+
|
|
74
102
|
@contextmanager
|
|
75
103
|
def temporary_variables(self):
|
|
76
104
|
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
@@ -125,6 +153,7 @@ class VariableManager(DeleteableObject):
|
|
|
125
153
|
def register_variable(self, variable_name, value, accept_expression=True, log_level=logging.INFO):
|
|
126
154
|
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
127
155
|
|
|
156
|
+
self.__enter_variable_update_log_file()
|
|
128
157
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
129
158
|
logger.trace(f"Setting variable: {variable_name}=[{value}] (type: {Typing.get_object_class_fullname(value)})...")
|
|
130
159
|
|
|
@@ -134,13 +163,13 @@ class VariableManager(DeleteableObject):
|
|
|
134
163
|
self.register_variable(names[0], Object())
|
|
135
164
|
var = self.get_value(names[0], through_patent=False)
|
|
136
165
|
setattr(var, names[1], value)
|
|
137
|
-
if Tools.do_log(
|
|
138
|
-
|
|
166
|
+
if Tools.do_log(self.__logger_update, log_level):
|
|
167
|
+
self.__logger_update.log(log_level, f"Set variable expression: {variable_name}=[{value}] (type: {Typing.get_object_class_fullname(value)})")
|
|
139
168
|
else:
|
|
140
169
|
var_name = self.evaluate_variable_name(variable_name)
|
|
141
170
|
self.__variables[var_name] = value
|
|
142
|
-
if Tools.do_log(
|
|
143
|
-
|
|
171
|
+
if Tools.do_log(self.__logger_update, log_level):
|
|
172
|
+
self.__logger_update.log(log_level, f"Set variable: {var_name}=[{value}] (type: {Typing.get_object_class_fullname(value)})")
|
|
144
173
|
|
|
145
174
|
# Manage temporary variables
|
|
146
175
|
uid = MultitaskManager.get_thread_uid()
|
|
@@ -149,6 +178,8 @@ class VariableManager(DeleteableObject):
|
|
|
149
178
|
self.__temporary_variables[uid].variable_names.add(var_name)
|
|
150
179
|
|
|
151
180
|
def unregister_variable(self, variable_name, through_parent=False, delete_value=False):
|
|
181
|
+
self.__enter_variable_update_log_file()
|
|
182
|
+
|
|
152
183
|
var_name = self.evaluate_variable_name(variable_name)
|
|
153
184
|
if self.exists_variable(var_name, through_parent=False):
|
|
154
185
|
value = self.__variables[var_name]
|
|
@@ -161,8 +192,8 @@ class VariableManager(DeleteableObject):
|
|
|
161
192
|
except Exception:
|
|
162
193
|
logger.exception(f"Catched exception while deleting object '{var_name}' (type: {Typing.get_object_class_fullname(value)})")
|
|
163
194
|
else:
|
|
164
|
-
if Tools.do_log(
|
|
165
|
-
|
|
195
|
+
if Tools.do_log(self.__logger_update, logging.DEBUG):
|
|
196
|
+
self.__logger_update.debug(f"Deleted variable '{var_name}' (type: {Typing.get_object_class_fullname(value)})")
|
|
166
197
|
|
|
167
198
|
del self.__variables[var_name]
|
|
168
199
|
elif through_parent and self.parent:
|
|
@@ -270,6 +301,8 @@ class VariableManager(DeleteableObject):
|
|
|
270
301
|
Tools.raise_same_exception_type(exc, f"{exc}\nVariable '{var_name}': {var_repr}", add_from=True)
|
|
271
302
|
|
|
272
303
|
def exec_set_variable_expression(self, expression, value, through_parent=True, log_level=logging.INFO):
|
|
304
|
+
self.__enter_variable_update_log_file()
|
|
305
|
+
|
|
273
306
|
var_name, expr_rest = self.__extract_expression_name(expression)
|
|
274
307
|
var_value = self.get_variable_value(var_name, through_parent=through_parent)
|
|
275
308
|
new_var_name = self.new_local_variable_name(sub_name=self.__regular_variable_name(var_name))
|
|
@@ -289,8 +322,8 @@ class VariableManager(DeleteableObject):
|
|
|
289
322
|
# Tools.raise_same_exception_type(exc, f"{exc}\nVariable '{var_name}': {var_repr}", add_from=True)
|
|
290
323
|
raise FunctionalException(f"Failed to set value in variable expression (by exec): {expression}=[{value}] (type: {Typing.get_object_class_fullname(value)})\nVariable '{var_name}': {var_repr}") from exc
|
|
291
324
|
else:
|
|
292
|
-
if Tools.do_log(
|
|
293
|
-
|
|
325
|
+
if Tools.do_log(self.__logger_update, log_level):
|
|
326
|
+
self.__logger_update.log(log_level, f"Set value in variable expression (by exec): {expression}=[{value}] (type: {Typing.get_object_class_fullname(value)})")
|
|
294
327
|
|
|
295
328
|
def __regular_variable_name(self, name):
|
|
296
329
|
return "".join([c if re.match(r'\w', c) else '_' for c in name])
|
|
@@ -73,7 +73,9 @@ class FeatureContext(Context):
|
|
|
73
73
|
if not self.has_variable_manager():
|
|
74
74
|
manager = VariableManager(SessionContext.instance().multitask_manager.get_thread_context().get_variable_manager())
|
|
75
75
|
self.set_object("variable_manager", manager)
|
|
76
|
-
|
|
76
|
+
file_path = SessionContext.instance().report_manager.current_feature_report.get_path("logs", "variable_update.log")
|
|
77
|
+
manager.initialize(SessionContext.instance().dynamic_text_manager, SessionContext.instance().unique_value_manager,
|
|
78
|
+
variable_update_log_file_path=file_path)
|
|
77
79
|
return self.get_object("variable_manager")
|
|
78
80
|
|
|
79
81
|
|
|
@@ -135,7 +135,9 @@ class ScenarioContext(Context):
|
|
|
135
135
|
if not self.has_variable_manager():
|
|
136
136
|
manager = VariableManager(SessionContext.instance().get_feature_context().get_variable_manager())
|
|
137
137
|
self.set_object("variable_manager", manager)
|
|
138
|
-
|
|
138
|
+
file_path = SessionContext.instance().report_manager.current_scenario_report.get_path("logs", "variable_update.log")
|
|
139
|
+
manager.initialize(self.get_dynamic_text_manager(), SessionContext.instance().unique_value_manager,
|
|
140
|
+
variable_update_log_file_path=file_path)
|
|
139
141
|
return self.get_object("variable_manager")
|
|
140
142
|
|
|
141
143
|
def has_expression_evaluator(self):
|
|
@@ -26,7 +26,8 @@ import holado
|
|
|
26
26
|
from holado_test.test_server.server.core.server_context import TestServerSessionContext
|
|
27
27
|
holado.initialize(TSessionContext=TestServerSessionContext,
|
|
28
28
|
logging_config_file_path=os.path.join(here, 'logging.conf'), log_level=logging.INFO,
|
|
29
|
-
log_on_console=True, log_in_file=False,
|
|
29
|
+
log_on_console=True, log_in_file=False,
|
|
30
|
+
config_kwargs={'application_group':'test_server'},
|
|
30
31
|
garbage_collector_periodicity=None)
|
|
31
32
|
|
|
32
33
|
# Update stored campaigns
|
test_holado/environment.py
CHANGED
|
@@ -33,7 +33,9 @@ import holado
|
|
|
33
33
|
# - log_on_console is True for initialization phase, it will be set to False when root log file will be defined
|
|
34
34
|
# - logging config file
|
|
35
35
|
from test_holado.test_holado_session_context import TestHoladoSessionContext
|
|
36
|
-
holado.initialize(TSessionContext=TestHoladoSessionContext, logging_config_file_path=os.path.join(here, 'logging.conf'),
|
|
36
|
+
holado.initialize(TSessionContext=TestHoladoSessionContext, logging_config_file_path=os.path.join(here, 'logging.conf'),
|
|
37
|
+
log_level=logging.INFO, log_on_console=True,
|
|
38
|
+
config_kwargs={'application_group':'test_runner'})
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@testing_solution
|
|
2
2
|
@ais
|
|
3
|
-
Feature: Test decode of AIS message from
|
|
3
|
+
Feature: Test decode of AIS message from bitarray and its encode in NMEAv4
|
|
4
4
|
|
|
5
5
|
@bitarray_to_nmea_through_decode
|
|
6
6
|
Scenario Outline: from bitarray to NMEAv4 sentences through decode
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
@testing_solution
|
|
2
|
+
@ais
|
|
3
|
+
Feature: Test decode of NMEA AIS raw to dict
|
|
4
|
+
|
|
5
|
+
@nmea_to_dict_without_tagblock
|
|
6
|
+
Scenario: from NMEA raw to dict (without tagblock)
|
|
7
|
+
Given RAW = '!AIVDM,1,1,,A,13KG`rU0001RbwdT6CR3TB3f0000,0*4E'
|
|
8
|
+
|
|
9
|
+
When MSG_DICT = decode NMEA AIS raw RAW as dictionary
|
|
10
|
+
|
|
11
|
+
Then MSG_TABLE = convert dictionary MSG_DICT to name/value table
|
|
12
|
+
Then table MSG_TABLE is
|
|
13
|
+
| Name | Value |
|
|
14
|
+
| 'accuracy' | False |
|
|
15
|
+
| 'course' | 91.3 |
|
|
16
|
+
| 'heading' | 65 |
|
|
17
|
+
| 'lat' | 63.086733 |
|
|
18
|
+
| 'lon' | 21.555183 |
|
|
19
|
+
| 'maneuver' | 0 |
|
|
20
|
+
| 'mmsi' | 230025450 |
|
|
21
|
+
| 'msg_type' | 1 |
|
|
22
|
+
| 'radio' | 0 |
|
|
23
|
+
| 'raim' | False |
|
|
24
|
+
| 'repeat' | 0 |
|
|
25
|
+
| 'second' | 55 |
|
|
26
|
+
| 'speed' | 0.0 |
|
|
27
|
+
| 'status' | 5 |
|
|
28
|
+
| 'turn' | 0.0 |
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@nmea_to_dict_with_tagblock
|
|
32
|
+
@without_merge
|
|
33
|
+
Scenario: from NMEA raw to dict (with tagblock, without merge)
|
|
34
|
+
Given RAW = '\\s:STATION1,t:Hello*2\\!AIVDM,1,1,,A,13KG`rU0001RbwdT6CR3TB3f0000,0*4E'
|
|
35
|
+
|
|
36
|
+
When TB_DICT, MSG_DICT = decode NMEA AIS raw RAW as dictionary
|
|
37
|
+
|
|
38
|
+
Then TB_TABLE = convert dictionary TB_DICT to name/value table
|
|
39
|
+
Then table TB_TABLE is
|
|
40
|
+
| Name | Value |
|
|
41
|
+
| 'source_station' | 'STATION1' |
|
|
42
|
+
| 'text' | 'Hello' |
|
|
43
|
+
|
|
44
|
+
Then MSG_TABLE = convert dictionary MSG_DICT to name/value table
|
|
45
|
+
Then table MSG_TABLE is
|
|
46
|
+
| Name | Value |
|
|
47
|
+
| 'accuracy' | False |
|
|
48
|
+
| 'course' | 91.3 |
|
|
49
|
+
| 'heading' | 65 |
|
|
50
|
+
| 'lat' | 63.086733 |
|
|
51
|
+
| 'lon' | 21.555183 |
|
|
52
|
+
| 'maneuver' | 0 |
|
|
53
|
+
| 'mmsi' | 230025450 |
|
|
54
|
+
| 'msg_type' | 1 |
|
|
55
|
+
| 'radio' | 0 |
|
|
56
|
+
| 'raim' | False |
|
|
57
|
+
| 'repeat' | 0 |
|
|
58
|
+
| 'second' | 55 |
|
|
59
|
+
| 'speed' | 0.0 |
|
|
60
|
+
| 'status' | 5 |
|
|
61
|
+
| 'turn' | 0.0 |
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@nmea_to_dict_with_tagblock
|
|
65
|
+
@with_merge
|
|
66
|
+
Scenario: from NMEA raw to dict (with tagblock, with merge)
|
|
67
|
+
Given RAW = '\\s:STATION1,t:Hello*2\\!AIVDM,1,1,,A,13KG`rU0001RbwdT6CR3TB3f0000,0*4E'
|
|
68
|
+
|
|
69
|
+
When MSG_DICT = decode NMEA AIS raw RAW as dictionary (merge tag block and message dictionaries)
|
|
70
|
+
|
|
71
|
+
Then MSG_TABLE = convert dictionary MSG_DICT to name/value table
|
|
72
|
+
Then table MSG_TABLE is
|
|
73
|
+
| Name | Value |
|
|
74
|
+
| 'accuracy' | False |
|
|
75
|
+
| 'course' | 91.3 |
|
|
76
|
+
| 'heading' | 65 |
|
|
77
|
+
| 'lat' | 63.086733 |
|
|
78
|
+
| 'lon' | 21.555183 |
|
|
79
|
+
| 'maneuver' | 0 |
|
|
80
|
+
| 'mmsi' | 230025450 |
|
|
81
|
+
| 'msg_type' | 1 |
|
|
82
|
+
| 'radio' | 0 |
|
|
83
|
+
| 'raim' | False |
|
|
84
|
+
| 'repeat' | 0 |
|
|
85
|
+
| 'second' | 55 |
|
|
86
|
+
| 'source_station' | 'STATION1' |
|
|
87
|
+
| 'speed' | 0.0 |
|
|
88
|
+
| 'status' | 5 |
|
|
89
|
+
| 'text' | 'Hello' |
|
|
90
|
+
| 'turn' | 0.0 |
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
@@ -26,7 +26,7 @@ Feature: Message type 10 : Coordinated UTC Inquiry
|
|
|
26
26
|
Then STRING_NMEA_MSG[-3] == 'A'
|
|
27
27
|
|
|
28
28
|
# Decode NMEA message
|
|
29
|
-
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as
|
|
29
|
+
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as dictionary
|
|
30
30
|
When DECODED_NMEA_MESSAGE_TABLE = convert dictionary DECODED_NMEA_MESSAGE to table with keys as columns
|
|
31
31
|
Then table DECODED_NMEA_MESSAGE_TABLE is
|
|
32
32
|
| dest_mmsi | mmsi | msg_type | repeat |
|
|
@@ -26,7 +26,7 @@ Feature: Message type 12 : Addressed Safety Related Message
|
|
|
26
26
|
Then STRING_NMEA_MSG[-3] == 'A'
|
|
27
27
|
|
|
28
28
|
# Decode NMEA message
|
|
29
|
-
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as
|
|
29
|
+
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as dictionary
|
|
30
30
|
When DECODED_NMEA_MESSAGE_TABLE = convert dictionary DECODED_NMEA_MESSAGE to table with keys as columns
|
|
31
31
|
Then table DECODED_NMEA_MESSAGE_TABLE is
|
|
32
32
|
| dest_mmsi | mmsi | msg_type | repeat | retransmit | seqno | text |
|
|
@@ -26,7 +26,7 @@ Feature: Message type 14 : Safety Related Broadcast Message
|
|
|
26
26
|
Then STRING_NMEA_MSG[-3] == 'A'
|
|
27
27
|
|
|
28
28
|
# Decode NMEA message
|
|
29
|
-
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as
|
|
29
|
+
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as dictionary
|
|
30
30
|
When DECODED_NMEA_MESSAGE_TABLE = convert dictionary DECODED_NMEA_MESSAGE to table with keys as columns
|
|
31
31
|
Then table DECODED_NMEA_MESSAGE_TABLE is
|
|
32
32
|
| mmsi | msg_type | repeat | text |
|
|
@@ -26,7 +26,7 @@ Feature: Message type 15 : Interrogation
|
|
|
26
26
|
Then STRING_NMEA_MSG[-3] == 'A'
|
|
27
27
|
|
|
28
28
|
# Decode NMEA message
|
|
29
|
-
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as
|
|
29
|
+
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as dictionary
|
|
30
30
|
When DECODED_NMEA_MESSAGE_TABLE = convert dictionary DECODED_NMEA_MESSAGE to table with keys as columns
|
|
31
31
|
Then table DECODED_NMEA_MESSAGE_TABLE is
|
|
32
32
|
| mmsi | mmsi1 | mmsi2 | msg_type | offset1_1 | offset1_2 | offset2_1 | repeat | type1_1 | type1_2 | type2_1 |
|
|
@@ -26,7 +26,7 @@ Feature: Message type 16 : Assigned Mode Command
|
|
|
26
26
|
Then STRING_NMEA_MSG[-3] == 'A'
|
|
27
27
|
|
|
28
28
|
# Decode NMEA message
|
|
29
|
-
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as
|
|
29
|
+
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as dictionary
|
|
30
30
|
When DECODED_NMEA_MESSAGE_TABLE = convert dictionary DECODED_NMEA_MESSAGE to table with keys as columns
|
|
31
31
|
Then table DECODED_NMEA_MESSAGE_TABLE is
|
|
32
32
|
| increment1 | increment2 | mmsi | mmsi1 | mmsi2 | msg_type | offset1 | offset2 | repeat |
|
|
@@ -35,7 +35,7 @@ Feature: Message type 17 : GNSS Broadcast Binary Message
|
|
|
35
35
|
Then STRING_NMEA_MSG[-3] == 'A'
|
|
36
36
|
|
|
37
37
|
# Decode NMEA message
|
|
38
|
-
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as
|
|
38
|
+
Given DECODED_NMEA_MESSAGE = decode NMEA AIS message NMEA_SENTENCES as dictionary
|
|
39
39
|
When DECODED_NMEA_MESSAGE_TABLE = convert dictionary DECODED_NMEA_MESSAGE to table with keys as columns
|
|
40
40
|
Then table DECODED_NMEA_MESSAGE_TABLE is
|
|
41
41
|
| data | lat | lon | mmsi | msg_type | repeat |
|