baldertest 0.1.0b10__py3-none-any.whl → 0.1.0b12__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.
- _balder/_version.py +1 -1
- _balder/cnnrelations/__init__.py +7 -0
- _balder/cnnrelations/and_connection_relation.py +149 -0
- _balder/cnnrelations/base_connection_relation.py +270 -0
- _balder/cnnrelations/or_connection_relation.py +65 -0
- _balder/collector.py +10 -16
- _balder/connection.py +400 -881
- _balder/connection_metadata.py +255 -0
- _balder/controllers/device_controller.py +37 -16
- _balder/controllers/feature_controller.py +63 -99
- _balder/controllers/normal_scenario_setup_controller.py +5 -5
- _balder/controllers/scenario_controller.py +6 -6
- _balder/controllers/setup_controller.py +2 -3
- _balder/decorator_connect.py +12 -10
- _balder/decorator_for_vdevice.py +17 -25
- _balder/decorator_gateway.py +3 -3
- _balder/executor/testcase_executor.py +0 -1
- _balder/executor/variation_executor.py +212 -199
- _balder/feature.py +1 -1
- _balder/feature_replacement_mapping.py +69 -0
- _balder/feature_vdevice_mapping.py +88 -0
- _balder/fixture_manager.py +10 -9
- _balder/objects/connections/osi_3_network.py +2 -2
- _balder/objects/connections/osi_4_transport.py +2 -2
- _balder/routing_path.py +27 -31
- _balder/solver.py +1 -1
- _balder/testresult.py +1 -1
- _balder/utils.py +27 -1
- {baldertest-0.1.0b10.dist-info → baldertest-0.1.0b12.dist-info}/METADATA +2 -2
- {baldertest-0.1.0b10.dist-info → baldertest-0.1.0b12.dist-info}/RECORD +34 -27
- {baldertest-0.1.0b10.dist-info → baldertest-0.1.0b12.dist-info}/WHEEL +1 -1
- {baldertest-0.1.0b10.dist-info → baldertest-0.1.0b12.dist-info}/LICENSE +0 -0
- {baldertest-0.1.0b10.dist-info → baldertest-0.1.0b12.dist-info}/entry_points.txt +0 -0
- {baldertest-0.1.0b10.dist-info → baldertest-0.1.0b12.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from typing import Type, Union, List, Dict, TYPE_CHECKING
|
|
3
4
|
|
|
4
5
|
import inspect
|
|
5
6
|
import logging
|
|
7
|
+
from _balder.cnnrelations import OrConnectionRelation
|
|
6
8
|
from _balder.device import Device
|
|
7
9
|
from _balder.connection import Connection
|
|
10
|
+
from _balder.feature_replacement_mapping import FeatureReplacementMapping
|
|
8
11
|
from _balder.fixture_execution_level import FixtureExecutionLevel
|
|
9
12
|
from _balder.testresult import ResultState, BranchBodyResult, ResultSummary
|
|
10
13
|
from _balder.executor.basic_executable_executor import BasicExecutableExecutor
|
|
@@ -13,6 +16,7 @@ from _balder.executor.unresolved_parametrized_testcase_executor import Unresolve
|
|
|
13
16
|
from _balder.previous_executor_mark import PreviousExecutorMark
|
|
14
17
|
from _balder.routing_path import RoutingPath
|
|
15
18
|
from _balder.unmapped_vdevice import UnmappedVDevice
|
|
19
|
+
from _balder.feature_vdevice_mapping import FeatureVDeviceMapping
|
|
16
20
|
from _balder.controllers import DeviceController, VDeviceController, FeatureController, NormalScenarioSetupController
|
|
17
21
|
from _balder.exceptions import NotApplicableVariationException, UnclearAssignableFeatureConnectionError
|
|
18
22
|
|
|
@@ -20,7 +24,8 @@ if TYPE_CHECKING:
|
|
|
20
24
|
from _balder.setup import Setup
|
|
21
25
|
from _balder.feature import Feature
|
|
22
26
|
from _balder.scenario import Scenario
|
|
23
|
-
from _balder.
|
|
27
|
+
from _balder.controllers.scenario_controller import ScenarioController
|
|
28
|
+
from _balder.controllers.setup_controller import SetupController
|
|
24
29
|
from _balder.executor.scenario_executor import ScenarioExecutor
|
|
25
30
|
from _balder.fixture_manager import FixtureManager
|
|
26
31
|
|
|
@@ -45,12 +50,10 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
45
50
|
self._routings: Dict[Connection, List[RoutingPath]] = {}
|
|
46
51
|
# buffer variable to save the feature replacement after it was determined with
|
|
47
52
|
# `determine_feature_replacement_and_vdevice_mappings()`
|
|
48
|
-
self._feature_replacement:
|
|
49
|
-
Union[None, Dict[Type[Device], Dict[str, Tuple[Union[Feature, None], Feature]]]] = None
|
|
53
|
+
self._feature_replacement: Union[None, Dict[Type[Device], FeatureReplacementMapping]] = None
|
|
50
54
|
# buffer variable to save the feature replacement after it was determined with
|
|
51
55
|
# `determine_feature_replacement_and_vdevice_mappings()`
|
|
52
|
-
self._abs_setup_feature_vdevice_mappings:
|
|
53
|
-
Union[None, Dict[Type[Device], Dict[Feature, Dict[Type[VDevice], Type[Device]]]]] = None
|
|
56
|
+
self._abs_setup_feature_vdevice_mappings: Union[None, Dict[Type[Device], FeatureVDeviceMapping]] = None
|
|
54
57
|
|
|
55
58
|
# contains the absolute scenario device connections for the current variation
|
|
56
59
|
self._abs_variation_scenario_device_connections: Union[List[Connection], None] = None
|
|
@@ -62,8 +65,7 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
62
65
|
# contains the original active vdevice mappings for all scenario and setup devices (will be managed by
|
|
63
66
|
# `update_active_vdevice_device_mappings_in_scenario_and_setup_devices()` and
|
|
64
67
|
# `revert_active_vdevice_device_mappings_in_scenario_and_setup_devices()`)
|
|
65
|
-
self._original_active_vdevice_mappings:
|
|
66
|
-
Dict[Type[Device], Dict[Feature, Dict[Type[VDevice], Type[Device]]]] = {}
|
|
68
|
+
self._original_active_vdevice_mappings: Dict[Type[Device], FeatureVDeviceMapping] = {}
|
|
67
69
|
|
|
68
70
|
# is True if the applicability check was done
|
|
69
71
|
self._applicability_check_done = False
|
|
@@ -96,11 +98,25 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
96
98
|
"""property returns the current :class:`Scenario` for this variation"""
|
|
97
99
|
return self._parent_executor.base_scenario_class
|
|
98
100
|
|
|
101
|
+
@property
|
|
102
|
+
def cur_scenario_controller(self) -> ScenarioController:
|
|
103
|
+
"""
|
|
104
|
+
returns the current :class:`ScenarioController` for this variation
|
|
105
|
+
"""
|
|
106
|
+
return self._parent_executor.base_scenario_controller
|
|
107
|
+
|
|
99
108
|
@property
|
|
100
109
|
def cur_setup_class(self) -> Setup:
|
|
101
110
|
"""property returns the current :class:`Setup` for this variation"""
|
|
102
111
|
return self._parent_executor.parent_executor.base_setup_class
|
|
103
112
|
|
|
113
|
+
@property
|
|
114
|
+
def cur_setup_controller(self) -> SetupController:
|
|
115
|
+
"""
|
|
116
|
+
returns the current :class:`SetupController` for this variation
|
|
117
|
+
"""
|
|
118
|
+
return self._parent_executor.parent_executor.base_setup_controller
|
|
119
|
+
|
|
104
120
|
@property
|
|
105
121
|
def base_device_mapping(self) -> Dict[Type[Device], Type[Device]]:
|
|
106
122
|
"""
|
|
@@ -119,18 +135,17 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
119
135
|
return self._fixture_manager
|
|
120
136
|
|
|
121
137
|
@property
|
|
122
|
-
def feature_replacement(self) -> Dict[Type[Device],
|
|
138
|
+
def feature_replacement(self) -> Dict[Type[Device], FeatureReplacementMapping]:
|
|
123
139
|
"""
|
|
124
|
-
this property is a dictionary with every scenario device as key and
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
this property is a dictionary with every scenario device as key and feature-replacement-mapping as value - the
|
|
141
|
+
mappings hold at least information about the attribute name of the feature in scenario device, the old
|
|
142
|
+
scenario-feature the instantiated feature from the scenario if it exists, otherwise this is None) and the
|
|
143
|
+
new feature as second item (the feature of the related Setup-Device)
|
|
128
144
|
"""
|
|
129
145
|
return self._feature_replacement
|
|
130
146
|
|
|
131
147
|
@property
|
|
132
|
-
def abs_setup_feature_vdevice_mappings(self)
|
|
133
|
-
-> Dict[Type[Device], Dict[Feature, Dict[Type[VDevice], Type[Device]]]]:
|
|
148
|
+
def abs_setup_feature_vdevice_mappings(self) -> Dict[Type[Device], FeatureVDeviceMapping]:
|
|
134
149
|
"""returns the feature replacement that was determined with
|
|
135
150
|
`determine_feature_replacement_and_vdevice_mappings()`"""
|
|
136
151
|
return self._abs_setup_feature_vdevice_mappings
|
|
@@ -211,26 +226,22 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
211
226
|
vDevices-Mappings (so the mapped setup-devices) implements all features that are defined in the vDevices
|
|
212
227
|
"""
|
|
213
228
|
|
|
214
|
-
for cur_scenario_device,
|
|
229
|
+
for cur_scenario_device, cur_replacement_mapping in self.feature_replacement.items():
|
|
215
230
|
cur_setup_device = self.get_setup_device_for(scenario_device=cur_scenario_device)
|
|
216
231
|
all_inner_setup_features = \
|
|
217
232
|
DeviceController.get_for(cur_setup_device).get_all_instantiated_feature_objects()
|
|
218
233
|
|
|
219
|
-
# describes the mapping from the new setup feature (key) to the instantiated scenario feature (value)
|
|
220
|
-
# note that this dictionary only contains the required one
|
|
221
|
-
setup_to_scenario_feature_mapping: Dict[Type[Feature], Feature] = {
|
|
222
|
-
cur_replacement_tuple[1]: cur_replacement_tuple[0]
|
|
223
|
-
for cur_attr_name, cur_replacement_tuple in cur_replacement_dict.items()
|
|
224
|
-
if cur_replacement_tuple[0] is not None}
|
|
225
|
-
|
|
226
234
|
# now secure that all features are available in the corresponding setup device, that are defined in the
|
|
227
235
|
# mapped vDevice
|
|
228
236
|
for _, cur_setup_feature_obj in all_inner_setup_features.items():
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
237
|
+
related_scenario_feature_obj = \
|
|
238
|
+
cur_replacement_mapping.get_replaced_scenario_feature_for(cur_setup_feature_obj)
|
|
239
|
+
|
|
240
|
+
# only check if this feature is required by the scenario
|
|
241
|
+
if related_scenario_feature_obj is None:
|
|
242
|
+
# ignore this, because this feature is not used in the scenario
|
|
232
243
|
continue
|
|
233
|
-
|
|
244
|
+
|
|
234
245
|
# get vDevice and device mapping
|
|
235
246
|
partner_scenario_vdevice, partner_scenario_device = \
|
|
236
247
|
related_scenario_feature_obj.active_vdevice_device_mapping
|
|
@@ -239,7 +250,7 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
239
250
|
# ignore because no mapping exist here
|
|
240
251
|
continue
|
|
241
252
|
|
|
242
|
-
partner_setup_device = self.get_setup_device_for(scenario_device=
|
|
253
|
+
partner_setup_device = self.get_setup_device_for(scenario_device=partner_scenario_device)
|
|
243
254
|
# get the related vDevice on setup view that is currently active
|
|
244
255
|
mapped_setup_vdevices = [
|
|
245
256
|
cur_vdevice for cur_vdevice
|
|
@@ -284,6 +295,39 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
284
295
|
f'can not find a valid routing on setup level for the connection `{scenario_cnn.get_tree_str()}` '
|
|
285
296
|
f'between scenario devices `{scenario_cnn.from_device}` and `{scenario_cnn.to_device}`')
|
|
286
297
|
|
|
298
|
+
def _get_matching_setup_features_for(
|
|
299
|
+
self,
|
|
300
|
+
scenario_feature_obj: Feature,
|
|
301
|
+
in_setup_device: Type[Device]
|
|
302
|
+
) -> List[Feature]:
|
|
303
|
+
"""
|
|
304
|
+
Helper method that returns all matching setup features for the provided scenario feature in the provided setup
|
|
305
|
+
device.
|
|
306
|
+
"""
|
|
307
|
+
cur_setup_features = DeviceController.get_for(in_setup_device).get_all_instantiated_feature_objects()
|
|
308
|
+
|
|
309
|
+
replacing_feature_candidates = [
|
|
310
|
+
cur_setup_feature for cur_setup_feature in cur_setup_features.values()
|
|
311
|
+
if isinstance(cur_setup_feature, scenario_feature_obj.__class__)
|
|
312
|
+
]
|
|
313
|
+
active_scenario_vdev, mapped_scenario_dev = scenario_feature_obj.active_vdevice_device_mapping
|
|
314
|
+
|
|
315
|
+
replacing_features = replacing_feature_candidates.copy()
|
|
316
|
+
if mapped_scenario_dev is not None:
|
|
317
|
+
# get the related setup device for the mapped scenario device (on scenario level)
|
|
318
|
+
setup_dev_of_mapped_scenario_dev = self.get_setup_device_for(mapped_scenario_dev)
|
|
319
|
+
|
|
320
|
+
# now check if there is a mapping on setup level too
|
|
321
|
+
for cur_replacing_feature in replacing_feature_candidates:
|
|
322
|
+
mapped_setup_vdev, mapped_setup_dev = cur_replacing_feature.active_vdevice_device_mapping
|
|
323
|
+
if mapped_setup_vdev is not None and not issubclass(mapped_setup_vdev, active_scenario_vdev):
|
|
324
|
+
# drop this feature matching, because we have different vdevice mapped
|
|
325
|
+
replacing_features.remove(cur_replacing_feature)
|
|
326
|
+
elif mapped_setup_dev is not None and mapped_setup_dev != setup_dev_of_mapped_scenario_dev:
|
|
327
|
+
# drop this feature matching, because it is not applicable here
|
|
328
|
+
replacing_features.remove(cur_replacing_feature)
|
|
329
|
+
return replacing_features
|
|
330
|
+
|
|
287
331
|
# ---------------------------------- METHODS -----------------------------------------------------------------------
|
|
288
332
|
|
|
289
333
|
def testsummary(self) -> ResultSummary:
|
|
@@ -336,75 +380,58 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
336
380
|
:raises NotApplicableVariationError: will be thrown if this variation cannot be applied, because the setup-/
|
|
337
381
|
scenario-device-features can not be resolved
|
|
338
382
|
"""
|
|
339
|
-
feature_replacement = {
|
|
340
|
-
|
|
383
|
+
feature_replacement = {
|
|
384
|
+
scenario_dev: FeatureReplacementMapping() for scenario_dev in self.base_device_mapping.keys()
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
abs_setup_vdevice_mappings = {
|
|
388
|
+
setup_dev: FeatureVDeviceMapping() for setup_dev in self.base_device_mapping.values()
|
|
389
|
+
}
|
|
341
390
|
for cur_scenario_device, cur_setup_device in self.base_device_mapping.items():
|
|
342
391
|
cur_setup_features = DeviceController.get_for(cur_setup_device).get_all_instantiated_feature_objects()
|
|
343
392
|
|
|
344
|
-
|
|
345
|
-
|
|
393
|
+
all_assigned_setup_features = []
|
|
394
|
+
cur_scenario_device_features = \
|
|
395
|
+
DeviceController.get_for(cur_scenario_device).get_all_instantiated_feature_objects()
|
|
396
|
+
for cur_attr_name, cur_scenario_feature_obj in cur_scenario_device_features.items():
|
|
397
|
+
active_scenario_vdevice, mapped_scenario_device = cur_scenario_feature_obj.active_vdevice_device_mapping
|
|
346
398
|
|
|
347
|
-
|
|
348
|
-
|
|
399
|
+
cur_setup_feature_objs = self._get_matching_setup_features_for(
|
|
400
|
+
scenario_feature_obj=cur_scenario_feature_obj, in_setup_device=cur_setup_device
|
|
401
|
+
)
|
|
349
402
|
|
|
350
|
-
|
|
351
|
-
cur_scenario_device_orig_features = \
|
|
352
|
-
DeviceController.get_for(cur_scenario_device).get_original_instanced_feature_objects()
|
|
353
|
-
for cur_attr_name, cur_abstract_scenario_feature_obj in cur_scenario_device_orig_features.items():
|
|
354
|
-
replacing_features = [cur_setup_feature for _, cur_setup_feature in cur_setup_features.items()
|
|
355
|
-
if isinstance(cur_setup_feature, cur_abstract_scenario_feature_obj.__class__)]
|
|
356
|
-
used_scenario_vdevice, mapped_scenario_device = \
|
|
357
|
-
cur_abstract_scenario_feature_obj.active_vdevice_device_mapping
|
|
358
|
-
# check if there is a mapped device in scenario level
|
|
359
|
-
cleanup_replacing_features = replacing_features.copy()
|
|
360
|
-
if mapped_scenario_device is not None:
|
|
361
|
-
# get the related setup device for the mapped scenario device (on scenario level)
|
|
362
|
-
to_scenarios_vdevice_mapped_setup_device = self.get_setup_device_for(mapped_scenario_device)
|
|
363
|
-
|
|
364
|
-
# now check if there is a mapping on setup level too
|
|
365
|
-
for cur_replacing_feature in replacing_features:
|
|
366
|
-
mapped_setup_vdevice, mapped_setup_device = cur_replacing_feature.active_vdevice_device_mapping
|
|
367
|
-
if mapped_setup_vdevice is not None and \
|
|
368
|
-
not issubclass(mapped_setup_vdevice, used_scenario_vdevice):
|
|
369
|
-
# drop this feature matching, because we have different vdevice mapped
|
|
370
|
-
cleanup_replacing_features.remove(cur_replacing_feature)
|
|
371
|
-
elif mapped_setup_device is not None and \
|
|
372
|
-
mapped_setup_device != to_scenarios_vdevice_mapped_setup_device:
|
|
373
|
-
# drop this feature matching, because it is not applicable here
|
|
374
|
-
cleanup_replacing_features.remove(cur_replacing_feature)
|
|
375
|
-
|
|
376
|
-
if len(cleanup_replacing_features) != 1:
|
|
403
|
+
if len(cur_setup_feature_objs) != 1:
|
|
377
404
|
raise NotApplicableVariationException(
|
|
378
405
|
f'this variation can not be applicable because there was no setup feature implementation of '
|
|
379
|
-
f'`{
|
|
406
|
+
f'`{cur_scenario_feature_obj.__class__.__name__}` (used by scenario device '
|
|
380
407
|
f'`{cur_scenario_device.__name__}`) in setup device `{cur_setup_device.__name__}`')
|
|
408
|
+
cur_setup_feature_obj = cur_setup_feature_objs[0]
|
|
381
409
|
|
|
382
410
|
if mapped_scenario_device is None:
|
|
383
411
|
# we have exactly one matching candidate, but also no vDevice mapping
|
|
384
412
|
# check if the matching candidate has a vDevice mapping
|
|
385
|
-
_, mapped_setup_device =
|
|
386
|
-
cleanup_feature_controller = FeatureController.get_for(
|
|
413
|
+
_, mapped_setup_device = cur_setup_feature_obj.active_vdevice_device_mapping
|
|
414
|
+
cleanup_feature_controller = FeatureController.get_for(cur_setup_feature_obj.__class__)
|
|
387
415
|
if mapped_setup_device is None \
|
|
388
416
|
and len(cleanup_feature_controller.get_abs_inner_vdevice_classes()) > 0:
|
|
389
417
|
# there is no vDevice mapping on scenario and no vDevice mapping on setup level, but the
|
|
390
418
|
# feature defined vDevices -> NOT APPLICABLE
|
|
391
419
|
logger.warning(
|
|
392
420
|
f"missing vDevice mapping for feature "
|
|
393
|
-
f"`{
|
|
421
|
+
f"`{cur_scenario_feature_obj.__class__.__name__}` (used in scenario device "
|
|
394
422
|
f"`{cur_scenario_device.__name__}` and in setup device `{cur_setup_device.__name__}`) - "
|
|
395
423
|
f"VARIATION CAN NOT BE APPLIED")
|
|
396
424
|
raise NotApplicableVariationException(
|
|
397
|
-
f'this variation can not be
|
|
425
|
+
f'this variation can not be applied because there was no vDevice mapping given on '
|
|
398
426
|
f'scenario or on setup level for the feature '
|
|
399
|
-
f'`{
|
|
427
|
+
f'`{cur_scenario_feature_obj.__class__.__name__}` (used by scenario device '
|
|
400
428
|
f'`{cur_scenario_device.__name__}`) in setup device `{cur_setup_device.__name__}`')
|
|
401
429
|
|
|
402
|
-
all_assigned_setup_features.append(
|
|
403
|
-
if cur_attr_name not in feature_replacement[cur_scenario_device].
|
|
404
|
-
|
|
405
|
-
cleanup_feature_controller = FeatureController.get_for(cleanup_feature.__class__)
|
|
430
|
+
all_assigned_setup_features.append(cur_setup_feature_obj)
|
|
431
|
+
if cur_attr_name not in feature_replacement[cur_scenario_device].attr_names:
|
|
432
|
+
cleanup_feature_controller = FeatureController.get_for(cur_setup_feature_obj.__class__)
|
|
406
433
|
|
|
407
|
-
used_setup_vdevice, mapped_setup_device =
|
|
434
|
+
used_setup_vdevice, mapped_setup_device = cur_setup_feature_obj.active_vdevice_device_mapping
|
|
408
435
|
|
|
409
436
|
# if there is a vDevice mapping on scenario level, but not on setup level, so update the
|
|
410
437
|
# VDevice-Device-Mapping there
|
|
@@ -413,29 +440,44 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
413
440
|
# because check was already done in collector-stage)
|
|
414
441
|
setup_vdevices = [cur_vdevice for cur_vdevice
|
|
415
442
|
in cleanup_feature_controller.get_abs_inner_vdevice_classes()
|
|
416
|
-
if cur_vdevice.__name__ ==
|
|
443
|
+
if cur_vdevice.__name__ == active_scenario_vdevice.__name__]
|
|
417
444
|
used_setup_vdevice = setup_vdevices[0]
|
|
418
445
|
# set the mapping
|
|
419
|
-
abs_setup_vdevice_mappings[cur_setup_device]
|
|
420
|
-
|
|
446
|
+
abs_setup_vdevice_mappings[cur_setup_device].add(
|
|
447
|
+
feature=cur_setup_feature_obj,
|
|
448
|
+
mappings={
|
|
449
|
+
used_setup_vdevice: self.get_setup_device_for(mapped_scenario_device)
|
|
450
|
+
}
|
|
451
|
+
)
|
|
421
452
|
# if there is a vDevice mapping on setup level, but not on scenario level, so directly update the
|
|
422
453
|
# VDevice-Device-Mapping there
|
|
423
454
|
elif mapped_scenario_device is None and mapped_setup_device is not None:
|
|
424
|
-
abs_setup_vdevice_mappings[cur_setup_device]
|
|
425
|
-
|
|
455
|
+
abs_setup_vdevice_mappings[cur_setup_device].add(
|
|
456
|
+
feature=cur_setup_feature_obj,
|
|
457
|
+
mappings={
|
|
458
|
+
used_setup_vdevice: mapped_setup_device
|
|
459
|
+
}
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
feature_replacement[cur_scenario_device].add(attr_name=cur_attr_name,
|
|
463
|
+
scenario_feature=cur_scenario_feature_obj,
|
|
464
|
+
setup_feature=cur_setup_feature_obj)
|
|
426
465
|
|
|
427
|
-
feature_replacement[cur_scenario_device][cur_attr_name] = \
|
|
428
|
-
(cur_abstract_scenario_feature_obj, cleanup_feature)
|
|
429
466
|
# also add all setup features that are not assigned as autonomous features
|
|
430
|
-
for
|
|
467
|
+
for cur_setup_feature in cur_setup_features.values():
|
|
431
468
|
if cur_setup_feature not in all_assigned_setup_features:
|
|
432
469
|
# determine free name
|
|
433
470
|
idx = 0
|
|
434
471
|
autonomous_name = None
|
|
435
|
-
while autonomous_name is None
|
|
472
|
+
while (autonomous_name is None
|
|
473
|
+
or autonomous_name in feature_replacement[cur_scenario_device].attr_names):
|
|
436
474
|
autonomous_name = f"_autonomous_feat_{idx}"
|
|
437
475
|
idx += 1
|
|
438
|
-
feature_replacement[cur_scenario_device]
|
|
476
|
+
feature_replacement[cur_scenario_device].add(
|
|
477
|
+
attr_name=autonomous_name,
|
|
478
|
+
scenario_feature=None,
|
|
479
|
+
setup_feature=cur_setup_feature
|
|
480
|
+
)
|
|
439
481
|
|
|
440
482
|
# set the result to internal properties
|
|
441
483
|
self._feature_replacement = feature_replacement
|
|
@@ -501,20 +543,18 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
501
543
|
This method ensures that the (mostly abstract) feature instances of a scenario are exchanged with the
|
|
502
544
|
feature instances of the assigned setup devices
|
|
503
545
|
"""
|
|
504
|
-
for cur_scenario_device,
|
|
505
|
-
for
|
|
506
|
-
|
|
507
|
-
setattr(cur_scenario_device, cur_attr_name, new_feature_obj)
|
|
546
|
+
for cur_scenario_device, cur_replacement_mapping in self.feature_replacement.items():
|
|
547
|
+
for cur_feature_mapping in cur_replacement_mapping.mappings:
|
|
548
|
+
setattr(cur_scenario_device, cur_feature_mapping.attr_name, cur_feature_mapping.setup_feature)
|
|
508
549
|
|
|
509
550
|
def revert_scenario_device_feature_instances(self):
|
|
510
551
|
"""
|
|
511
552
|
This method ensures that all initialized feature instances of a scenario are set back to the initial given
|
|
512
553
|
features.
|
|
513
554
|
"""
|
|
514
|
-
for cur_scenario_device,
|
|
515
|
-
for
|
|
516
|
-
|
|
517
|
-
setattr(cur_scenario_device, cur_attr_name, old_instantiated_feature_obj)
|
|
555
|
+
for cur_scenario_device, cur_replacement_mapping in self.feature_replacement.items():
|
|
556
|
+
for cur_feature_mapping in cur_replacement_mapping.mappings:
|
|
557
|
+
setattr(cur_scenario_device, cur_feature_mapping.attr_name, cur_feature_mapping.scenario_feature)
|
|
518
558
|
|
|
519
559
|
def update_active_vdevice_device_mappings_in_all_features(self):
|
|
520
560
|
"""
|
|
@@ -522,28 +562,28 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
522
562
|
scenario-device classes are set correctly.
|
|
523
563
|
"""
|
|
524
564
|
|
|
525
|
-
for cur_setup_device,
|
|
565
|
+
for cur_setup_device, feature_vdevice_mapping in self.abs_setup_feature_vdevice_mappings.items():
|
|
526
566
|
if cur_setup_device not in self._original_active_vdevice_mappings.keys():
|
|
527
|
-
self._original_active_vdevice_mappings[cur_setup_device] =
|
|
528
|
-
for cur_setup_feature
|
|
567
|
+
self._original_active_vdevice_mappings[cur_setup_device] = FeatureVDeviceMapping()
|
|
568
|
+
for cur_setup_feature in feature_vdevice_mapping.features:
|
|
569
|
+
vdev_dev_mappings_of_setup_feat = feature_vdevice_mapping.get_mappings_for_feature(cur_setup_feature)
|
|
529
570
|
|
|
530
|
-
cur_setup_feature_vdevice =
|
|
531
|
-
cur_mapped_setup_device =
|
|
571
|
+
cur_setup_feature_vdevice = vdev_dev_mappings_of_setup_feat[0].vdevice
|
|
572
|
+
cur_mapped_setup_device = vdev_dev_mappings_of_setup_feat[0].device
|
|
532
573
|
|
|
533
574
|
# first save old value to revert it later
|
|
534
|
-
self._original_active_vdevice_mappings[cur_setup_device]
|
|
535
|
-
cur_setup_feature
|
|
575
|
+
self._original_active_vdevice_mappings[cur_setup_device].add(
|
|
576
|
+
feature=cur_setup_feature,
|
|
577
|
+
mappings=cur_setup_feature.active_vdevices
|
|
578
|
+
)
|
|
536
579
|
# now set new value
|
|
537
580
|
cur_setup_feature.active_vdevices = {cur_setup_feature_vdevice: cur_mapped_setup_device}
|
|
538
581
|
|
|
539
582
|
# now also determine the mapping for the scenario-feature (if there exists one)
|
|
540
583
|
cur_scenario_device = self.get_scenario_device_for(cur_setup_device)
|
|
541
|
-
cur_scenario_feature =
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if cur_replacement_setup_feature == cur_setup_feature:
|
|
545
|
-
cur_scenario_feature = cur_replacement_scenario_feature
|
|
546
|
-
break
|
|
584
|
+
cur_scenario_feature = self.feature_replacement[cur_scenario_device].get_replaced_scenario_feature_for(
|
|
585
|
+
cur_setup_feature
|
|
586
|
+
)
|
|
547
587
|
if cur_scenario_feature is None:
|
|
548
588
|
# there exists no scenario feature -> we can ignore this
|
|
549
589
|
pass
|
|
@@ -557,10 +597,12 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
557
597
|
# only if there exists exactly one scenario vdevice with the same name
|
|
558
598
|
|
|
559
599
|
if cur_scenario_device not in self._original_active_vdevice_mappings.keys():
|
|
560
|
-
self._original_active_vdevice_mappings[cur_scenario_device] =
|
|
600
|
+
self._original_active_vdevice_mappings[cur_scenario_device] = FeatureVDeviceMapping()
|
|
561
601
|
# first save old value to revert it later
|
|
562
|
-
self._original_active_vdevice_mappings[cur_scenario_device]
|
|
563
|
-
cur_scenario_feature
|
|
602
|
+
self._original_active_vdevice_mappings[cur_scenario_device].add(
|
|
603
|
+
feature=cur_scenario_feature,
|
|
604
|
+
mappings=cur_scenario_feature.active_vdevices
|
|
605
|
+
)
|
|
564
606
|
# now set new value
|
|
565
607
|
cur_scenario_feature.active_vdevices = \
|
|
566
608
|
{cur_scenario_feature_vdevice[0]: self.get_scenario_device_for(cur_mapped_setup_device)}
|
|
@@ -568,10 +610,14 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
568
610
|
def revert_active_vdevice_device_mappings_in_all_features(self):
|
|
569
611
|
"""
|
|
570
612
|
This method ensures that the `active_vdevices` property that was changed with
|
|
571
|
-
`
|
|
613
|
+
`update_active_vdevice_device_mappings_in_all_features()` will be reverted correctly.
|
|
572
614
|
"""
|
|
573
|
-
for
|
|
574
|
-
for cur_feature
|
|
615
|
+
for cur_feature_vdevice_mapping in self._original_active_vdevice_mappings.values():
|
|
616
|
+
for cur_feature in cur_feature_vdevice_mapping.features:
|
|
617
|
+
cur_original_mapping = {
|
|
618
|
+
mapping.vdevice:mapping.device
|
|
619
|
+
for mapping in cur_feature_vdevice_mapping.get_mappings_for_feature(cur_feature)
|
|
620
|
+
}
|
|
575
621
|
cur_feature.active_vdevices = cur_original_mapping
|
|
576
622
|
|
|
577
623
|
def exchange_unmapped_vdevice_references(self):
|
|
@@ -631,7 +677,7 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
631
677
|
cur_vdevice, cur_device = cur_feature.active_vdevice_device_mapping
|
|
632
678
|
if cur_vdevice is not None and cur_device is not None:
|
|
633
679
|
cur_vdevice_controller = VDeviceController.get_for(cur_vdevice)
|
|
634
|
-
cur_vdevice_all_features = cur_vdevice_controller.
|
|
680
|
+
cur_vdevice_all_features = cur_vdevice_controller.get_all_instantiated_feature_objects()
|
|
635
681
|
|
|
636
682
|
cur_device_controller = DeviceController.get_for(cur_device)
|
|
637
683
|
cur_device_all_features = cur_device_controller.get_all_instantiated_feature_objects()
|
|
@@ -679,116 +725,77 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
679
725
|
|
|
680
726
|
def determine_absolute_scenario_device_connections(self):
|
|
681
727
|
"""
|
|
682
|
-
This method determines the
|
|
683
|
-
|
|
728
|
+
This method determines the absolute connections for this variation and sets the internal properties
|
|
729
|
+
`_abs_variation_*_device_connections` with them. This will be used to determine the real connection-subtree
|
|
684
730
|
(that can be used for this variation) by the method `create_all_valid_routings()`.
|
|
685
731
|
|
|
686
732
|
The method re-executes the algorithm to determine the absolute connections for a scenario/setup (see the method
|
|
687
733
|
:meth:`Collector.determine_absolute_device_connections_for`), but it considers the real applied vDevice and
|
|
688
734
|
their feature restrictions too.
|
|
689
735
|
"""
|
|
690
|
-
abs_var_scenario_device_cnns = {}
|
|
691
|
-
|
|
692
736
|
# first determine all relevant absolute connection depending on the current scenario
|
|
693
|
-
|
|
694
|
-
cur_scenario_device_abs_cnns = \
|
|
695
|
-
DeviceController.get_for(cur_scenario_device).get_all_absolute_connections()
|
|
696
|
-
for _, cur_cnn_list in cur_scenario_device_abs_cnns.items():
|
|
697
|
-
for cur_cnn in cur_cnn_list:
|
|
698
|
-
if cur_scenario_device not in abs_var_scenario_device_cnns.keys():
|
|
699
|
-
abs_var_scenario_device_cnns[cur_scenario_device] = {}
|
|
700
|
-
|
|
701
|
-
cur_to_device, _ = cur_cnn.get_conn_partner_of(cur_scenario_device)
|
|
702
|
-
|
|
703
|
-
if cur_to_device not in abs_var_scenario_device_cnns[cur_scenario_device].keys():
|
|
704
|
-
abs_var_scenario_device_cnns[cur_scenario_device][cur_to_device] = []
|
|
705
|
-
|
|
706
|
-
abs_var_scenario_device_cnns[cur_scenario_device][cur_to_device].append(cur_cnn)
|
|
737
|
+
abs_var_scenario_device_cnns = self.cur_scenario_controller.get_all_abs_connections()
|
|
707
738
|
|
|
708
739
|
# now iterate over every feature, that is used by the scenario and determine the class-based feature connections
|
|
709
740
|
# of the mapped scenario feature (and its vDevice)
|
|
710
|
-
for cur_setup_device,
|
|
741
|
+
for cur_setup_device, feature_vdev_mapping in self.abs_setup_feature_vdevice_mappings.items():
|
|
711
742
|
cur_scenario_device = self.get_scenario_device_for(cur_setup_device)
|
|
712
|
-
for cur_setup_feature,
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
cur_setup_feature_vdevice = list(mapping_dict.keys())[0]
|
|
718
|
-
cur_mapped_setup_device = list(mapping_dict.values())[0]
|
|
743
|
+
for cur_setup_feature, vdev_mappings_of_setup_feature in feature_vdev_mapping.items():
|
|
744
|
+
cur_scenario_feature: Feature = (
|
|
745
|
+
self.feature_replacement[cur_scenario_device].get_replaced_scenario_feature_for(
|
|
746
|
+
setup_feature=cur_setup_feature)
|
|
747
|
+
)
|
|
719
748
|
|
|
720
|
-
if
|
|
749
|
+
if vdev_mappings_of_setup_feature[0].device not in self.base_device_mapping.values():
|
|
721
750
|
raise NotApplicableVariationException(
|
|
722
|
-
f'the mapped setup device `{
|
|
723
|
-
f'VDevice `{
|
|
751
|
+
f'the mapped setup device `{vdev_mappings_of_setup_feature[0].device.__qualname__}` which is '
|
|
752
|
+
f'mapped to the VDevice `{vdev_mappings_of_setup_feature[0].vdevice.__qualname__}` is no part '
|
|
753
|
+
f'of this variation')
|
|
724
754
|
|
|
725
|
-
cur_mapped_scenario_device = self.get_scenario_device_for(
|
|
755
|
+
cur_mapped_scenario_device = self.get_scenario_device_for(vdev_mappings_of_setup_feature[0].device)
|
|
726
756
|
|
|
727
757
|
# get relevant class based connections for the current feature on setup level (this is really be used
|
|
728
758
|
# here)
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
cur_setup_feature.__class__).get_abs_class_based_for_vdevice()[cur_setup_feature_vdevice]
|
|
759
|
+
feat_cnn = FeatureController.get_for(cur_setup_feature.__class__)\
|
|
760
|
+
.get_abs_class_based_for_vdevice()[vdev_mappings_of_setup_feature[0].vdevice]
|
|
732
761
|
# connection that are relevant for this feature
|
|
733
|
-
relevant_cnns =
|
|
734
|
-
|
|
735
|
-
|
|
762
|
+
relevant_cnns = [
|
|
763
|
+
cnn for cnn in abs_var_scenario_device_cnns
|
|
764
|
+
if (cnn.has_connection_from_to(cur_scenario_device, end_device=cur_mapped_scenario_device)
|
|
765
|
+
and max(single_feat_cnn.contained_in(cnn, ignore_metadata=True)
|
|
766
|
+
for single_feat_cnn in feat_cnn.get_singles())
|
|
767
|
+
)
|
|
768
|
+
]
|
|
736
769
|
|
|
737
770
|
if len(relevant_cnns) > 1:
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
f"the devices {cur_scenario_device.__name__} and "
|
|
747
|
-
f"{cur_mapped_scenario_device.__name__} have multiple parallel "
|
|
748
|
-
f"connections - the device `{cur_scenario_device.__name__}` uses a "
|
|
749
|
-
f"feature `{cur_scenario_feature.__class__.__name__}` that matches "
|
|
750
|
-
f"with the device `{cur_mapped_scenario_device.__name__}`, but it is "
|
|
751
|
-
f"not clear which of the parallel connection could be used"
|
|
752
|
-
)
|
|
753
|
-
relevant_device_cnn = cur_relevant_cnn
|
|
754
|
-
elif len(relevant_cnns) == 1:
|
|
755
|
-
relevant_device_cnn = relevant_cnns[0]
|
|
756
|
-
if relevant_device_cnn is None:
|
|
771
|
+
raise UnclearAssignableFeatureConnectionError(
|
|
772
|
+
f"the devices {cur_scenario_device.__name__} and {cur_mapped_scenario_device.__name__} have "
|
|
773
|
+
f"multiple parallel connections - the device `{cur_scenario_device.__name__}` uses a feature "
|
|
774
|
+
f"`{cur_scenario_feature.__class__.__name__}` that matches with the device "
|
|
775
|
+
f"`{cur_mapped_scenario_device.__name__}`, but it is not clear which of the parallel "
|
|
776
|
+
f"connection could be used")
|
|
777
|
+
|
|
778
|
+
if len(relevant_cnns) == 0:
|
|
757
779
|
# todo this does not map here
|
|
758
780
|
raise ValueError("can not find matching connection on scenario level")
|
|
759
781
|
|
|
782
|
+
relevant_device_cnn = relevant_cnns[0]
|
|
783
|
+
|
|
760
784
|
# now cleanup the scenario-device connection `relevant_device_cnn` according to the class-based feature
|
|
761
785
|
# connection
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
relevant_device_cnn)
|
|
773
|
-
abs_var_scenario_device_cnns[cur_scenario_device][cur_mapped_scenario_device].append(new_cnn_to_replace)
|
|
774
|
-
|
|
775
|
-
# also search the connection in the other direction
|
|
776
|
-
other_dir_relevant_device_cnn = None
|
|
777
|
-
for cur_cnn in abs_var_scenario_device_cnns[cur_mapped_scenario_device][cur_scenario_device]:
|
|
778
|
-
if cur_cnn.equal_with(relevant_device_cnn):
|
|
779
|
-
other_dir_relevant_device_cnn = cur_cnn
|
|
780
|
-
break
|
|
781
|
-
# and also replace it
|
|
782
|
-
abs_var_scenario_device_cnns[cur_mapped_scenario_device][cur_scenario_device].remove(
|
|
783
|
-
other_dir_relevant_device_cnn)
|
|
784
|
-
abs_var_scenario_device_cnns[cur_mapped_scenario_device][cur_scenario_device].append(new_cnn_to_replace)
|
|
786
|
+
new_cnn_to_replace = Connection.based_on(OrConnectionRelation(*[
|
|
787
|
+
cur_old_cnn_single for cur_old_cnn_single in relevant_device_cnn.get_singles()
|
|
788
|
+
if feat_cnn.contained_in(cur_old_cnn_single, ignore_metadata=True)
|
|
789
|
+
]))
|
|
790
|
+
new_cnn_to_replace.set_metadata_for_all_subitems(relevant_device_cnn.metadata)
|
|
791
|
+
|
|
792
|
+
abs_var_scenario_device_cnns.remove(relevant_device_cnn)
|
|
793
|
+
abs_var_scenario_device_cnns.append(new_cnn_to_replace)
|
|
794
|
+
|
|
795
|
+
# we do not need to check other direction because `has_connection_from_to()` returns both possibilities
|
|
785
796
|
|
|
786
797
|
# set the determined values in variation object
|
|
787
|
-
self._abs_variation_scenario_device_connections =
|
|
788
|
-
for _, from_device_dict in abs_var_scenario_device_cnns.items():
|
|
789
|
-
for _, cur_cnn_list in from_device_dict.items():
|
|
790
|
-
for cur_cnn in cur_cnn_list:
|
|
791
|
-
self._abs_variation_scenario_device_connections.append(cur_cnn)
|
|
798
|
+
self._abs_variation_scenario_device_connections = abs_var_scenario_device_cnns
|
|
792
799
|
|
|
793
800
|
def create_all_valid_routings(self):
|
|
794
801
|
"""
|
|
@@ -828,16 +835,18 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
828
835
|
if virtual_routing_cnns[cur_cnn] is None:
|
|
829
836
|
virtual_routing_cnns[cur_cnn] = Connection.based_on(virtual_cnn)
|
|
830
837
|
else:
|
|
831
|
-
virtual_routing_cnns[cur_cnn] = Connection.based_on(
|
|
838
|
+
virtual_routing_cnns[cur_cnn] = Connection.based_on(
|
|
839
|
+
OrConnectionRelation(virtual_routing_cnns[cur_cnn], virtual_cnn))
|
|
832
840
|
virtual_routing_cnns[cur_cnn].set_metadata_for_all_subitems(virtual_cnn.metadata)
|
|
833
841
|
|
|
834
842
|
self._abs_variation_connections = []
|
|
835
843
|
for cur_cnn in self._abs_variation_scenario_device_connections:
|
|
836
844
|
cur_virtual_cnn = virtual_routing_cnns[cur_cnn]
|
|
837
845
|
new_intersection = cur_cnn.intersection_with(cur_virtual_cnn)
|
|
838
|
-
new_intersection
|
|
839
|
-
|
|
840
|
-
|
|
846
|
+
if new_intersection:
|
|
847
|
+
new_intersection.set_metadata_for_all_subitems(None)
|
|
848
|
+
# always set the metadata for setup devices
|
|
849
|
+
new_intersection.set_metadata_for_all_subitems(cur_virtual_cnn.metadata)
|
|
841
850
|
self._abs_variation_connections.append(new_intersection)
|
|
842
851
|
|
|
843
852
|
def set_conn_dependent_methods(self):
|
|
@@ -873,11 +882,15 @@ class VariationExecutor(BasicExecutableExecutor):
|
|
|
873
882
|
relevant_abs_conn = []
|
|
874
883
|
for cur_cnn in self._abs_variation_connections:
|
|
875
884
|
if cur_cnn.has_connection_from_to(start_device=setup_device, end_device=mapped_setup_device):
|
|
876
|
-
|
|
885
|
+
# add the children
|
|
886
|
+
relevant_abs_conn.extend(
|
|
887
|
+
cur_cnn.based_on_elements.connections if cur_cnn.__class__ == Connection else [cur_cnn]
|
|
888
|
+
)
|
|
889
|
+
|
|
877
890
|
if len(relevant_abs_conn) is None:
|
|
878
891
|
raise RuntimeError(f"detect empty absolute connection between device `{setup_device.__name__}` "
|
|
879
892
|
f"and device `{mapped_setup_device.__name__}`")
|
|
880
|
-
absolute_feature_method_var_cnn = Connection.based_on(*relevant_abs_conn)
|
|
893
|
+
absolute_feature_method_var_cnn = Connection.based_on(OrConnectionRelation(*relevant_abs_conn))
|
|
881
894
|
cur_method_variation = cur_setup_feature_controller.get_method_variation(
|
|
882
895
|
of_method_name=cur_method_name, for_vdevice=mapped_vdevice,
|
|
883
896
|
with_connection=absolute_feature_method_var_cnn)
|