py_canoe 3.0.4__py3-none-any.whl → 26.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.
Files changed (124) hide show
  1. py_canoe/__init__.py +2 -1
  2. py_canoe/canoe.py +910 -0
  3. py_canoe/core/__init__.py +0 -0
  4. py_canoe/core/application.py +170 -0
  5. py_canoe/core/bus.py +301 -0
  6. py_canoe/core/capl.py +59 -0
  7. py_canoe/core/child_elements/__init__.py +0 -0
  8. py_canoe/core/child_elements/application_model.py +24 -0
  9. py_canoe/core/child_elements/application_model_file.py +21 -0
  10. py_canoe/core/child_elements/application_model_files.py +22 -0
  11. py_canoe/core/child_elements/application_model_setup.py +15 -0
  12. py_canoe/core/child_elements/application_models.py +22 -0
  13. py_canoe/core/child_elements/application_socket.py +11 -0
  14. py_canoe/core/child_elements/application_specific_module.py +24 -0
  15. py_canoe/core/child_elements/application_specific_modules.py +16 -0
  16. py_canoe/core/child_elements/audio_interface.py +28 -0
  17. py_canoe/core/child_elements/available_modules.py +22 -0
  18. py_canoe/core/child_elements/basic_module.py +19 -0
  19. py_canoe/core/child_elements/basic_modules.py +16 -0
  20. py_canoe/core/child_elements/c_libraries.py +28 -0
  21. py_canoe/core/child_elements/c_library.py +33 -0
  22. py_canoe/core/child_elements/can_controller.py +74 -0
  23. py_canoe/core/child_elements/capl_function.py +17 -0
  24. py_canoe/core/child_elements/ccp_setup.py +15 -0
  25. py_canoe/core/child_elements/channel.py +20 -0
  26. py_canoe/core/child_elements/channels.py +19 -0
  27. py_canoe/core/child_elements/communication_setup.py +23 -0
  28. py_canoe/core/child_elements/compile_result.py +22 -0
  29. py_canoe/core/child_elements/configured_channel.py +48 -0
  30. py_canoe/core/child_elements/configured_channels.py +21 -0
  31. py_canoe/core/child_elements/configured_module.py +82 -0
  32. py_canoe/core/child_elements/configured_modules.py +61 -0
  33. py_canoe/core/child_elements/connected_modules.py +14 -0
  34. py_canoe/core/child_elements/data_source.py +42 -0
  35. py_canoe/core/child_elements/data_source_file.py +21 -0
  36. py_canoe/core/child_elements/data_source_files.py +22 -0
  37. py_canoe/core/child_elements/data_source_issue.py +22 -0
  38. py_canoe/core/child_elements/data_source_issues.py +16 -0
  39. py_canoe/core/child_elements/data_source_setup.py +17 -0
  40. py_canoe/core/child_elements/data_sources.py +27 -0
  41. py_canoe/core/child_elements/database_setup.py +62 -0
  42. py_canoe/core/child_elements/device.py +34 -0
  43. py_canoe/core/child_elements/devices.py +13 -0
  44. py_canoe/core/child_elements/diagnostic.py +22 -0
  45. py_canoe/core/child_elements/diagnostic_request.py +59 -0
  46. py_canoe/core/child_elements/diagnostic_response.py +34 -0
  47. py_canoe/core/child_elements/diagnostic_responses.py +13 -0
  48. py_canoe/core/child_elements/diagnostics_setup.py +254 -0
  49. py_canoe/core/child_elements/distributed_mode.py +74 -0
  50. py_canoe/core/child_elements/encoding.py +27 -0
  51. py_canoe/core/child_elements/encodings.py +13 -0
  52. py_canoe/core/child_elements/environment_array.py +13 -0
  53. py_canoe/core/child_elements/environment_group.py +22 -0
  54. py_canoe/core/child_elements/environment_info.py +14 -0
  55. py_canoe/core/child_elements/environment_variable.py +55 -0
  56. py_canoe/core/child_elements/fdx_files.py +50 -0
  57. py_canoe/core/child_elements/file_group_data_source.py +17 -0
  58. py_canoe/core/child_elements/general_setup.py +66 -0
  59. py_canoe/core/child_elements/macros_setup.py +52 -0
  60. py_canoe/core/child_elements/mc_ecus.py +428 -0
  61. py_canoe/core/child_elements/measurement_setup.py +269 -0
  62. py_canoe/core/child_elements/modules.py +87 -0
  63. py_canoe/core/child_elements/most_disassembler.py +21 -0
  64. py_canoe/core/child_elements/most_network_interface.py +4 -0
  65. py_canoe/core/child_elements/namespace.py +21 -0
  66. py_canoe/core/child_elements/namespaces.py +19 -0
  67. py_canoe/core/child_elements/network.py +18 -0
  68. py_canoe/core/child_elements/network_adapters.py +13 -0
  69. py_canoe/core/child_elements/nodes.py +119 -0
  70. py_canoe/core/child_elements/open_configuration_result.py +0 -0
  71. py_canoe/core/child_elements/panel_setup.py +97 -0
  72. py_canoe/core/child_elements/participant.py +17 -0
  73. py_canoe/core/child_elements/participants.py +22 -0
  74. py_canoe/core/child_elements/ports.py +81 -0
  75. py_canoe/core/child_elements/replay_collection.py +56 -0
  76. py_canoe/core/child_elements/security_configuration.py +20 -0
  77. py_canoe/core/child_elements/security_setup.py +31 -0
  78. py_canoe/core/child_elements/signals.py +39 -0
  79. py_canoe/core/child_elements/simulation_setup.py +0 -0
  80. py_canoe/core/child_elements/single_file_data_source.py +13 -0
  81. py_canoe/core/child_elements/snippet_setup.py +68 -0
  82. py_canoe/core/child_elements/standalone_mode.py +0 -0
  83. py_canoe/core/child_elements/start_value_list.py +0 -0
  84. py_canoe/core/child_elements/symbol_mappings.py +0 -0
  85. py_canoe/core/child_elements/tcp_ip_stack_setting.py +0 -0
  86. py_canoe/core/child_elements/test_configurations.py +0 -0
  87. py_canoe/core/child_elements/test_environment.py +64 -0
  88. py_canoe/core/child_elements/test_environments.py +26 -0
  89. py_canoe/core/child_elements/test_module.py +213 -0
  90. py_canoe/core/child_elements/test_modules.py +23 -0
  91. py_canoe/core/child_elements/test_setup.py +16 -0
  92. py_canoe/core/child_elements/test_setup_folder_ext.py +36 -0
  93. py_canoe/core/child_elements/test_setup_folders.py +25 -0
  94. py_canoe/core/child_elements/user_files.py +0 -0
  95. py_canoe/core/child_elements/variable.py +144 -0
  96. py_canoe/core/child_elements/variable_events.py +14 -0
  97. py_canoe/core/child_elements/variables.py +29 -0
  98. py_canoe/core/child_elements/variables_file.py +15 -0
  99. py_canoe/core/child_elements/variables_files.py +19 -0
  100. py_canoe/core/child_elements/visual_sequence_setup.py +46 -0
  101. py_canoe/core/child_elements/vt_system.py +83 -0
  102. py_canoe/core/child_elements/vtt_sut_import_result.py +21 -0
  103. py_canoe/core/child_elements/write.py +71 -0
  104. py_canoe/core/child_elements/xcp_setup.py +12 -0
  105. py_canoe/core/configuration.py +509 -0
  106. py_canoe/core/environment.py +59 -0
  107. py_canoe/core/measurement.py +149 -0
  108. py_canoe/core/networks.py +103 -0
  109. py_canoe/core/performance.py +21 -0
  110. py_canoe/core/simulation.py +53 -0
  111. py_canoe/core/system.py +164 -0
  112. py_canoe/core/ui.py +53 -0
  113. py_canoe/core/version.py +54 -0
  114. py_canoe/helpers/__init__.py +0 -0
  115. py_canoe/helpers/common.py +78 -0
  116. {py_canoe-3.0.4.dist-info → py_canoe-26.0.0.dist-info}/METADATA +332 -322
  117. py_canoe-26.0.0.dist-info/RECORD +118 -0
  118. py_canoe-26.0.0.dist-info/WHEEL +4 -0
  119. py_canoe/py_canoe.py +0 -2586
  120. py_canoe/py_canoe_utils/logging_collection.py +0 -345
  121. py_canoe/py_canoe_utils/py_canoe_logger.py +0 -29
  122. py_canoe-3.0.4.dist-info/LICENSE +0 -21
  123. py_canoe-3.0.4.dist-info/RECORD +0 -8
  124. py_canoe-3.0.4.dist-info/WHEEL +0 -4
@@ -0,0 +1,509 @@
1
+ from typing import TYPE_CHECKING, Iterable, Union
2
+ if TYPE_CHECKING:
3
+ from py_canoe.core.application import Application
4
+ from py_canoe.core.child_elements.measurement_setup import Logging, ExporterSymbol, Message
5
+ import os
6
+ import win32com.client
7
+
8
+ from py_canoe.core.child_elements.c_libraries import CLibraries
9
+ from py_canoe.core.child_elements.communication_setup import CommunicationSetup
10
+ from py_canoe.core.child_elements.distributed_mode import DistributedMode
11
+ from py_canoe.core.child_elements.fdx_files import FDXFiles
12
+ from py_canoe.core.child_elements.general_setup import GeneralSetup
13
+ from py_canoe.core.child_elements.measurement_setup import MeasurementSetup
14
+ from py_canoe.core.child_elements.database_setup import Databases
15
+ from py_canoe.core.child_elements.replay_collection import ReplayCollection
16
+ from py_canoe.core.child_elements.test_setup import TestSetup
17
+ from py_canoe.helpers.common import logger, wait
18
+
19
+
20
+ class ConfigurationEvents:
21
+ def __init__(self):
22
+ self.CONFIGURATION_CLOSED = False
23
+ self.SYSTEM_VARIABLES_DEFINITION_CHANGED = False
24
+
25
+ def OnClose(self):
26
+ self.CONFIGURATION_CLOSED = True
27
+
28
+ def OnSystemVariablesDefinitionChanged(self):
29
+ self.SYSTEM_VARIABLES_DEFINITION_CHANGED = True
30
+
31
+
32
+ class Configuration:
33
+ """
34
+ The Configuration object represents the active configuration.
35
+ """
36
+ def __init__(self, app: 'Application'):
37
+ self.app = app
38
+ self.bus_types = self.app.bus_types
39
+ self.com_object = win32com.client.Dispatch(self.app.com_object.Configuration)
40
+ # self.configuration_events: ConfigurationEvents = win32com.client.WithEvents(self.com_object, ConfigurationEvents)
41
+ self.configuration_test_setup = lambda: self.test_setup
42
+ self.__test_setup_environments = self.configuration_test_setup().test_environments.fetch_all_test_environments()
43
+ self.__test_modules = list()
44
+
45
+ def fetch_test_modules(self):
46
+ for te_name, te_inst in self.__test_setup_environments.items():
47
+ for tm_name, tm_inst in te_inst.get_all_test_modules().items():
48
+ self.__test_modules.append({'name': tm_name, 'object': tm_inst, 'environment': te_name})
49
+
50
+ @property
51
+ def c_libraries(self) -> 'CLibraries':
52
+ return CLibraries(self.com_object.CLibraries)
53
+
54
+ @property
55
+ def comment(self) -> str:
56
+ return self.com_object.Comment
57
+
58
+ @property
59
+ def communication_setup(self) -> 'CommunicationSetup':
60
+ return CommunicationSetup(self.com_object.CommunicationSetup)
61
+
62
+ @property
63
+ def distributed_mode(self) -> 'DistributedMode':
64
+ return DistributedMode(self.com_object.DistributedMode)
65
+
66
+ @property
67
+ def fdx_enabled(self) -> bool:
68
+ return self.com_object.FDXEnabled
69
+
70
+ @fdx_enabled.setter
71
+ def fdx_enabled(self, enabled: bool):
72
+ self.com_object.FDXEnabled = enabled
73
+
74
+ @property
75
+ def fdx_files(self) -> 'FDXFiles':
76
+ return FDXFiles(self.com_object.FDXFiles)
77
+
78
+ @property
79
+ def full_name(self) -> str:
80
+ return self.com_object.FullName
81
+
82
+ @property
83
+ def general_setup(self) -> 'GeneralSetup':
84
+ return GeneralSetup(self.com_object.GeneralSetup)
85
+
86
+ # GlobalTcpIpStackSetting
87
+
88
+ @property
89
+ def mode(self) -> int:
90
+ return self.com_object.Mode
91
+
92
+ @mode.setter
93
+ def mode(self, type: int):
94
+ self.com_object.Mode = type
95
+
96
+ @property
97
+ def modified(self) -> bool:
98
+ return self.com_object.Modified
99
+
100
+ @modified.setter
101
+ def modified(self, modified: bool):
102
+ self.com_object.Modified = modified
103
+
104
+ @property
105
+ def name(self) -> str:
106
+ return self.com_object.Name
107
+
108
+ # NETTargetFramework
109
+
110
+ @property
111
+ def offline_setup(self) -> 'MeasurementSetup':
112
+ return MeasurementSetup(self.com_object.OfflineSetup)
113
+
114
+ @property
115
+ def online_setup(self) -> 'MeasurementSetup':
116
+ return MeasurementSetup(self.com_object.OnlineSetup)
117
+
118
+ @property
119
+ def path(self) -> str:
120
+ return self.com_object.Path
121
+
122
+ @property
123
+ def read_only(self) -> bool:
124
+ return self.com_object.ReadOnly
125
+
126
+ @property
127
+ def saved(self) -> bool:
128
+ return self.com_object.Saved
129
+
130
+ @property
131
+ def test_setup(self) -> 'TestSetup':
132
+ return TestSetup(self.com_object.TestSetup)
133
+
134
+ # Sensor
135
+
136
+ # SimulationSetup
137
+
138
+ # StandaloneMode
139
+
140
+ # StartValueList
141
+
142
+ # SymbolMappings
143
+
144
+ # TestConfigurations
145
+
146
+ # TestSetup
147
+
148
+ # UserFiles
149
+
150
+ # VTSystem
151
+
152
+ def compile_and_verify(self) -> bool:
153
+ self.com_object.CompileAndVerify()
154
+
155
+ def save(self) -> bool:
156
+ try:
157
+ if self.saved:
158
+ logger.warning("⚠️ CANoe configuration is already saved.")
159
+ return True
160
+ self.com_object.Save()
161
+ logger.info("📢 CANoe configuration saved 💾 successfully 🎉")
162
+ return True
163
+ except Exception as e:
164
+ logger.error(f"❌ Error saving CANoe configuration: {e}")
165
+ return False
166
+
167
+ def save_as(self, path: str, major: int, minor: int, prompt_user: bool = False, create_dir: bool = True) -> bool:
168
+ try:
169
+ if create_dir:
170
+ dir_path = os.path.dirname(path)
171
+ if dir_path:
172
+ os.makedirs(dir_path, exist_ok=True)
173
+ logger.info(f'📂 Created directory {dir_path} for saving configuration')
174
+ self.com_object.SaveAs(path, major, minor, prompt_user)
175
+ logger.info(f"📢 CANoe configuration saved 💾 as {path} successfully 🎉")
176
+ return True
177
+ except Exception as e:
178
+ logger.error(f"❌ Error saving CANoe configuration as '{path}': {e}")
179
+ return False
180
+
181
+ def get_can_bus_statistics(self, channel: int) -> dict:
182
+ try:
183
+ can_stat_obj = self.online_setup.bus_statistics.BusStatistic(self.bus_types['CAN'], channel)
184
+ keys = [
185
+ 'BusLoad', 'ChipState', 'Error', 'ErrorTotal', 'Extended', 'ExtendedTotal',
186
+ 'ExtendedRemote', 'ExtendedRemoteTotal', 'Overload', 'OverloadTotal', 'PeakLoad',
187
+ 'RxErrorCount', 'Standard', 'StandardTotal', 'StandardRemote', 'StandardRemoteTotal',
188
+ 'TxErrorCount'
189
+ ]
190
+ can_bus_stat_info = {key.lower(): getattr(can_stat_obj, key) for key in keys}
191
+ logger.info(f'📜 CAN bus channel ({channel}) statistics:')
192
+ for key, value in can_bus_stat_info.items():
193
+ logger.info(f" {key}: {value}")
194
+ return can_bus_stat_info
195
+ except Exception as e:
196
+ logger.error(f"❌ Error retrieving CAN bus statistics for channel {channel}: {e}")
197
+ return {}
198
+
199
+ def add_offline_source_log_file(self, absolute_log_file_path: str) -> bool:
200
+ try:
201
+ if not os.path.isfile(absolute_log_file_path):
202
+ logger.error(f"❌ Error: Offline source log file '{absolute_log_file_path}' does not exist.")
203
+ return False
204
+ offline_sources_obj = self.com_object.OfflineSetup.Source.Sources
205
+ offline_sources_files = [offline_sources_obj.Item(i) for i in range(1, offline_sources_obj.Count + 1)]
206
+ file_already_added = any([file == absolute_log_file_path for file in offline_sources_files])
207
+ if file_already_added:
208
+ logger.warning(f"⚠️ Offline source log file '{absolute_log_file_path}' is already added.")
209
+ else:
210
+ offline_sources_obj.Add(absolute_log_file_path)
211
+ logger.info(f'📢 File "{absolute_log_file_path}" added as offline source')
212
+ return True
213
+ except Exception as e:
214
+ logger.error(f"❌ Error adding offline source log file '{absolute_log_file_path}': {e}")
215
+ return False
216
+
217
+ def set_replay_block_file(self, block_name: str, recording_file_path: str) -> bool:
218
+ try:
219
+ replay_collection_obj = ReplayCollection(self.com_object.SimulationSetup.ReplayCollection)
220
+ replay_blocks_obj_dict = dict()
221
+ for i in range(1, replay_collection_obj.count + 1):
222
+ replay_block_obj = replay_collection_obj.item(i)
223
+ replay_blocks_obj_dict[replay_block_obj.name] = replay_block_obj
224
+ if block_name in replay_blocks_obj_dict:
225
+ replay_blocks_obj_dict[block_name].path = recording_file_path
226
+ logger.info(f"📢 Replay block path for '{block_name}' set to '{recording_file_path}'")
227
+ return True
228
+ else:
229
+ logger.warning(f"⚠️ Replay block '{block_name}' not found")
230
+ return False
231
+ except Exception as e:
232
+ logger.error(f"❌ Error setting replay block file for '{block_name}': {e}")
233
+ return False
234
+
235
+ def control_replay_block(self, block_name: str, start_stop: bool) -> bool:
236
+ try:
237
+ replay_collection_obj = ReplayCollection(self.com_object.SimulationSetup.ReplayCollection)
238
+ replay_blocks_obj_dict = dict()
239
+ for i in range(1, replay_collection_obj.count + 1):
240
+ replay_block_obj = replay_collection_obj.item(i)
241
+ replay_blocks_obj_dict[replay_block_obj.name] = replay_block_obj
242
+ if block_name in replay_blocks_obj_dict:
243
+ if start_stop:
244
+ replay_blocks_obj_dict[block_name].start()
245
+ logger.info(f"📢 Replay block '{block_name}' started")
246
+ else:
247
+ replay_blocks_obj_dict[block_name].stop()
248
+ logger.info(f"📢 Replay block '{block_name}' stopped")
249
+ return True
250
+ else:
251
+ logger.warning(f"⚠️ Replay block '{block_name}' not found")
252
+ return False
253
+ except Exception as e:
254
+ logger.error(f"❌ Error controlling replay block '{block_name}': {e}")
255
+ return False
256
+
257
+ def enable_disable_replay_block(self, block_name: str, enable_disable: bool) -> bool:
258
+ try:
259
+ replay_collection_obj = ReplayCollection(self.com_object.SimulationSetup.ReplayCollection)
260
+ replay_blocks_obj_dict = dict()
261
+ for i in range(1, replay_collection_obj.count + 1):
262
+ replay_block_obj = replay_collection_obj.item(i)
263
+ replay_blocks_obj_dict[replay_block_obj.name] = replay_block_obj
264
+ if block_name in replay_blocks_obj_dict:
265
+ replay_blocks_obj_dict[block_name].enabled = enable_disable
266
+ logger.info(f"📢 Replay block '{block_name}' {'enabled' if enable_disable else 'disabled'}")
267
+ return True
268
+ else:
269
+ logger.warning(f"⚠️ Replay block '{block_name}' not found")
270
+ return False
271
+ except Exception as e:
272
+ logger.error(f"❌ Error enabling/disabling replay block '{block_name}': {e}")
273
+ return False
274
+
275
+ def get_test_environments(self) -> dict:
276
+ try:
277
+ return self.__test_setup_environments
278
+ except Exception as e:
279
+ logger.error(f'❌ failed to get test environments. {e}')
280
+ return {}
281
+
282
+ def get_test_modules(self, env_name: str) -> dict:
283
+ try:
284
+ test_environments = self.get_test_environments()
285
+ if len(test_environments) > 0:
286
+ if env_name in test_environments.keys():
287
+ return test_environments[env_name].get_all_test_modules()
288
+ else:
289
+ logger.warning(f'⚠️ "{env_name}" not found in configuration')
290
+ return {}
291
+ else:
292
+ logger.warning('⚠️ Zero test environments found in configuration. Not possible to fetch test modules')
293
+ return {}
294
+ except Exception as e:
295
+ logger.error(f'❌ failed to get test modules. {e}')
296
+ return {}
297
+
298
+ def execute_test_module(self, test_module_name: str) -> int:
299
+ try:
300
+ test_verdict = {0: 'NotAvailable',
301
+ 1: 'Passed',
302
+ 2: 'Failed',
303
+ 3: 'None (not available for test modules)',
304
+ 4: 'Inconclusive (not available for test modules)',
305
+ 5: 'ErrorInTestSystem (not available for test modules)', }
306
+ execution_result = 0
307
+ test_module_found = False
308
+ test_env_name = ''
309
+ for tm in self.__test_modules:
310
+ if tm['name'] == test_module_name:
311
+ test_module_found = True
312
+ tm_obj = tm['object']
313
+ test_env_name = tm['environment']
314
+ logger.info(f'🔎 test module "{test_module_name}" found in "{test_env_name}"')
315
+ tm_obj.start()
316
+ tm_obj.wait_for_completion()
317
+ execution_result = tm_obj.verdict
318
+ break
319
+ else:
320
+ continue
321
+ if test_module_found and (execution_result == 1):
322
+ logger.info(f'🧪🟢 test module "{test_env_name}.{test_module_name}" verdict = {test_verdict[execution_result]}')
323
+ elif test_module_found and (execution_result != 1):
324
+ logger.info(f'🧪🔴 test module "{test_env_name}.{test_module_name}" verdict = {test_verdict[execution_result]}')
325
+ else:
326
+ logger.warning(f'🧪⚠️ test module "{test_module_name}" not found. not possible to execute')
327
+ return execution_result
328
+ except Exception as e:
329
+ logger.error(f'❌ failed to execute test module. {e}')
330
+ return 0
331
+
332
+ def stop_test_module(self, test_module_name: str):
333
+ try:
334
+ for tm in self.__test_modules:
335
+ if tm['name'] == test_module_name:
336
+ tm['object'].stop()
337
+ test_env_name = tm['environment']
338
+ logger.info(f'🧪⏹️ test module "{test_module_name}" in test environment "{test_env_name}" stopped 🧍‍♂️')
339
+ else:
340
+ logger.warning(f'🧪⚠️ test module "{test_module_name}" not found. not possible to execute')
341
+ except Exception as e:
342
+ logger.error(f'❌ failed to stop test module. {e}')
343
+
344
+ def execute_all_test_modules_in_test_env(self, env_name: str):
345
+ try:
346
+ test_modules = self.get_test_modules(env_name=env_name)
347
+ if test_modules:
348
+ for tm_name in test_modules.keys():
349
+ self.execute_test_module(tm_name)
350
+ else:
351
+ logger.warning(f'🧪⚠️ test modules not available in "{env_name}" test environment')
352
+ except Exception as e:
353
+ logger.error(f'🧪❌ failed to execute all test modules in "{env_name}" test environment. {e}')
354
+
355
+ def stop_all_test_modules_in_test_env(self, env_name: str):
356
+ try:
357
+ test_modules = self.get_test_modules(env_name=env_name)
358
+ if test_modules:
359
+ for tm_name in test_modules.keys():
360
+ self.stop_test_module(tm_name)
361
+ else:
362
+ logger.warning(f'🧪⚠️ test modules not available in "{env_name}" test environment')
363
+ except Exception as e:
364
+ logger.error(f'🧪❌ failed to stop all test modules in "{env_name}" test environment. {e}')
365
+
366
+ def execute_all_test_environments(self):
367
+ try:
368
+ test_environments = self.get_test_environments()
369
+ if len(test_environments) > 0:
370
+ for test_env_name in test_environments.keys():
371
+ logger.info(f'🧐🏃‍➡️🥱 executing test environment "{test_env_name}". please wait...')
372
+ self.execute_all_test_modules_in_test_env(test_env_name)
373
+ logger.info(f'🧐🧍✔️ completed executing test environment "{test_env_name}"')
374
+ else:
375
+ logger.warning('🧐⚠️ Zero test environments found in configuration')
376
+ except Exception as e:
377
+ logger.error(f'🧐❌ failed to execute all test environments. {e}')
378
+
379
+ def stop_all_test_environments(self):
380
+ try:
381
+ test_environments = self.get_test_environments()
382
+ if len(test_environments) > 0:
383
+ for test_env_name in test_environments.keys():
384
+ logger.info(f'🧐⏹️🥱 stopping test environment "{test_env_name}" execution. please wait...')
385
+ self.stop_all_test_modules_in_test_env(test_env_name)
386
+ logger.info(f'🧐🧍✔️ completed stopping test environment "{test_env_name}"')
387
+ else:
388
+ logger.warning('🧐⚠️ Zero test environments found in configuration')
389
+ except Exception as e:
390
+ logger.error(f'🧐❌ failed to stop all test environments. {e}')
391
+
392
+ def add_database(self, database_file: str, database_channel: int, database_network: Union[str, None]=None) -> bool:
393
+ try:
394
+ if self.app.measurement.running:
395
+ logger.warning("⚠️ Cannot add database while measurement is running. Please stop the measurement first.")
396
+ return False
397
+ else:
398
+ databases = Databases(self.com_object.GeneralSetup.DatabaseSetup.Databases)
399
+ databases_info = {databases.item(index).full_name: databases.item(index) for index in range(1, databases.count + 1)}
400
+ if database_file in databases_info.keys():
401
+ logger.warning(f'⚠️ database "{database_file}" already added')
402
+ return False
403
+ else:
404
+ if database_network:
405
+ database = databases.add_network(database_file, database_network)
406
+ else:
407
+ database = databases.add(database_file)
408
+ wait(0.5)
409
+ database.channel = database_channel
410
+ wait(0.5)
411
+ logger.info(f'📢 database "{database_file}" added successfully to channel {database_channel}')
412
+ return True
413
+ except Exception as e:
414
+ logger.error(f"❌ Error adding database '{database_file}': {e}")
415
+ return False
416
+
417
+ def remove_database(self, database_file: str, database_channel: int) -> bool:
418
+ try:
419
+ if self.app.measurement.running:
420
+ logger.warning("⚠️ Cannot remove database while measurement is running. Please stop the measurement first.")
421
+ return False
422
+ else:
423
+ databases = Databases(self.com_object.GeneralSetup.DatabaseSetup.Databases)
424
+ databases_info = {databases.item(index).full_name: databases.item(index) for index in range(1, databases.count + 1)}
425
+ if database_file not in databases_info.keys():
426
+ logger.warning(f'⚠️ database "{database_file}" not available to remove')
427
+ return False
428
+ else:
429
+ for index in range(1, databases.count + 1):
430
+ database = databases.item(index)
431
+ if (database.full_name == database_file) and (database.channel == database_channel):
432
+ databases.remove(index)
433
+ wait(1)
434
+ logger.info(f'📢 database "{database_file}" removed from channel "{database_channel}"')
435
+ return True
436
+ logger.warning(f'⚠️ unable to remove database "{database_file}" from channel "{database_channel}"')
437
+ return False
438
+ except Exception as e:
439
+ logger.error(f"❌ Error removing database '{database_file}': {e}")
440
+ return False
441
+
442
+ def get_mode(self) -> int:
443
+ logger.info(f"⚙️ CANoe Configuration mode = ({self.mode} - {'Offline mode' if self.mode == 1 else 'Online mode'})")
444
+ return self.mode
445
+
446
+ def set_mode(self, type: int) -> bool:
447
+ try:
448
+ if type in [0, 1]:
449
+ self.mode = type
450
+ logger.info(f"⚙️ CANoe Configuration mode set to ({type} - {'Offline mode' if type == 1 else 'Online mode'})")
451
+ return True
452
+ else:
453
+ logger.warning("⚠️ Invalid mode type. Use 0 for Offline mode and 1 for Online mode.")
454
+ return False
455
+ except Exception as e:
456
+ logger.error(f"❌ Error setting CANoe Configuration mode: {e}")
457
+ return False
458
+
459
+ def get_logging_blocks(self) -> list['Logging']:
460
+ blocks = []
461
+ for i in range(1, self.online_setup.logging_collection.count + 1):
462
+ logging_block = self.online_setup.logging_collection.item(i)
463
+ blocks.append(logging_block)
464
+ return blocks
465
+
466
+ def add_logging_block(self, full_name: str) -> 'Logging':
467
+ return self.online_setup.logging_collection.add(full_name)
468
+
469
+ def remove_logging_block(self, index: int) -> None:
470
+ if index == 0:
471
+ raise ValueError("Logging blocks indexing starts from 1 and not 0.")
472
+ self.online_setup.logging_collection.remove(index)
473
+
474
+ def load_logs_for_exporter(self, logger_index: int) -> None:
475
+ self.online_setup.logging_collection.item(logger_index).exporter.load()
476
+
477
+ def get_symbols(self, logger_index: int) -> list['ExporterSymbol']:
478
+ return self.online_setup.logging_collection.item(logger_index).exporter.symbols
479
+
480
+ def get_messages(self, logger_index: int) -> list['Message']:
481
+ return self.online_setup.logging_collection.item(logger_index).exporter.messages
482
+
483
+ def add_filters_to_exporter(self, logger_index: int, full_names: 'Iterable'):
484
+ expo_filter = self.online_setup.logging_collection.item(logger_index).exporter.filter
485
+ for name in full_names:
486
+ expo_filter.add(name)
487
+
488
+ def start_export(self, logger_index: int):
489
+ self.online_setup.logging_collection.item(logger_index).exporter.save()
490
+
491
+ def start_stop_online_logging_block(self, full_name: str, start_stop: bool) -> bool:
492
+ try:
493
+ logging_blocks = self.get_logging_blocks()
494
+ for logging_block in logging_blocks:
495
+ if logging_block.full_name.lower() == full_name.lower():
496
+ if start_stop:
497
+ logging_block.trigger.start()
498
+ logger.info(f'📢 logging block {full_name} started')
499
+ else:
500
+ logging_block.trigger.stop()
501
+ logger.info(f'📢 logging block {full_name} stopped')
502
+ return True
503
+ logger.warning(f'⚠️ logging block {full_name} not found.')
504
+ return False
505
+ except Exception as e:
506
+ logger.error(f"❌ Error starting/stopping logging block {full_name}. {e}")
507
+
508
+ def set_configuration_modified(self, modified: bool) -> None:
509
+ self.modified = modified
@@ -0,0 +1,59 @@
1
+ # TODO: complete implementation of the Environment class
2
+ from typing import Union
3
+
4
+ from py_canoe.helpers.common import logger
5
+ from py_canoe.core.child_elements.environment_group import EnvironmentGroup
6
+ from py_canoe.core.child_elements.environment_info import EnvironmentInfo
7
+ from py_canoe.core.child_elements.environment_variable import EnvironmentVariable
8
+
9
+
10
+ class Environment:
11
+ """
12
+ The Environment object represents the environment variables.
13
+ """
14
+ def __init__(self, app):
15
+ self.com_object = app.com_object.Environment
16
+
17
+ def create_group(self):
18
+ return EnvironmentGroup(self.com_object.CreateGroup())
19
+
20
+ def create_info(self) -> 'EnvironmentInfo':
21
+ return EnvironmentInfo(self.com_object.CreateInfo())
22
+
23
+ def get_variable(self, name: str) -> 'EnvironmentVariable':
24
+ return EnvironmentVariable(self.com_object.GetVariable(name))
25
+
26
+ def get_variables(self, vars: list[list[Union[str, int, float]]]) -> list:
27
+ return self.com_object.GetVariables(vars)
28
+
29
+ def set_variables(self, vars: dict):
30
+ self.com_object.SetVariables(vars)
31
+
32
+ def get_environment_variable_value(self, env_var_name: str) -> Union[int, float, str, tuple, None]:
33
+ var_value = None
34
+ try:
35
+ variable = self.get_variable(env_var_name)
36
+ var_value = variable.value if variable.type != 3 else tuple(variable.value)
37
+ logger.info(f'🔢 environment variable({env_var_name}) value = {var_value}')
38
+ except Exception as e:
39
+ logger.error(f"❌ Failed to get environment variable '{env_var_name}': {e}")
40
+ finally:
41
+ return var_value
42
+
43
+ def set_environment_variable_value(self, env_var_name: str, value: Union[int, float, str, tuple]) -> bool:
44
+ try:
45
+ variable = self.get_variable(env_var_name)
46
+ if variable.type == 0:
47
+ converted_value = int(value)
48
+ elif variable.type == 1:
49
+ converted_value = float(value)
50
+ elif variable.type == 2:
51
+ converted_value = str(value)
52
+ else:
53
+ converted_value = tuple(value)
54
+ variable.value = converted_value
55
+ logger.info(f'🔢 environment variable({env_var_name}) set to 👉 {converted_value}')
56
+ return True
57
+ except Exception as e:
58
+ logger.error(f"❌ Failed to set environment variable '{env_var_name}': {e}")
59
+ return False