Skip to content

Commit

Permalink
Merge pull request #394 from andlaus/base_variant_patterns
Browse files Browse the repository at this point in the history
Implement base variant patterns
  • Loading branch information
andlaus authored Feb 26, 2025
2 parents 924c08e + 1040df0 commit 5cc2c95
Show file tree
Hide file tree
Showing 21 changed files with 1,560 additions and 796 deletions.
1 change: 1 addition & 0 deletions examples/somersaultecu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,7 @@ class SomersaultSID(IntEnum):
variable_groups=NamedItemList(),
libraries=NamedItemList(),
sub_components=NamedItemList(),
base_variant_pattern=None,
dyn_defined_spec=None)
somersault_base_variant = BaseVariant(diag_layer_raw=somersault_base_variant_raw)

Expand Down
38 changes: 38 additions & 0 deletions odxtools/basevariantpattern.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-License-Identifier: MIT
from dataclasses import dataclass
from typing import List, Union
from xml.etree import ElementTree

from typing_extensions import override

from .exceptions import odxassert
from .matchingbasevariantparameter import MatchingBaseVariantParameter
from .matchingparameter import MatchingParameter
from .odxlink import OdxDocFragment
from .variantpattern import VariantPattern


@dataclass
class BaseVariantPattern(VariantPattern):
"""Base variant patterns are variant patterns used to identify the
base variant of an ECU.
"""
matching_base_variant_parameters: List[MatchingBaseVariantParameter]

@override
def get_matching_parameters(
self) -> Union[List[MatchingParameter], List[MatchingBaseVariantParameter]]:
return self.matching_base_variant_parameters

@staticmethod
def from_et(et_element: ElementTree.Element,
doc_frags: List[OdxDocFragment]) -> "BaseVariantPattern":

matching_base_variant_parameters = [
MatchingBaseVariantParameter.from_et(mbvp_el, doc_frags)
for mbvp_el in et_element.iterfind("MATCHING-BASE-VARIANT-PARAMETERS/"
"MATCHING-BASE-VARIANT-PARAMETER")
]

odxassert(len(matching_base_variant_parameters) > 0) # required by ISO 22901-1 Figure 141
return BaseVariantPattern(matching_base_variant_parameters=matching_base_variant_parameters)
18 changes: 0 additions & 18 deletions odxtools/createecuvariantpatterns.py

This file was deleted.

5 changes: 5 additions & 0 deletions odxtools/diaglayers/basevariant.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from typing_extensions import override

from ..basevariantpattern import BaseVariantPattern
from ..diagvariable import DiagVariable
from ..dyndefinedspec import DynDefinedSpec
from ..exceptions import odxassert
Expand Down Expand Up @@ -38,6 +39,10 @@ def diag_variables_raw(self) -> List[Union[DiagVariable, OdxLinkRef]]:
def dyn_defined_spec(self) -> Optional[DynDefinedSpec]:
return self.base_variant_raw.dyn_defined_spec

@property
def base_variant_pattern(self) -> Optional[BaseVariantPattern]:
return self.base_variant_raw.base_variant_pattern

@property
def parent_refs(self) -> List[ParentRef]:
return self.base_variant_raw.parent_refs
Expand Down
8 changes: 7 additions & 1 deletion odxtools/diaglayers/basevariantraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Any, Dict, List, Optional, Union
from xml.etree import ElementTree

from ..basevariantpattern import BaseVariantPattern
from ..diagvariable import DiagVariable
from ..dyndefinedspec import DynDefinedSpec
from ..exceptions import odxraise
Expand All @@ -23,7 +24,7 @@ class BaseVariantRaw(HierarchyElementRaw):
diag_variables_raw: List[Union[DiagVariable, OdxLinkRef]]
variable_groups: NamedItemList[VariableGroup]
dyn_defined_spec: Optional[DynDefinedSpec]
# TODO: base_variant_pattern: Optional[BaseVariantPattern]
base_variant_pattern: Optional[BaseVariantPattern]
parent_refs: List[ParentRef]

@property
Expand Down Expand Up @@ -63,6 +64,10 @@ def from_et(et_element: ElementTree.Element,
if (dds_elem := et_element.find("DYN-DEFINED-SPEC")) is not None:
dyn_defined_spec = DynDefinedSpec.from_et(dds_elem, doc_frags)

base_variant_pattern = None
if (bvp_elem := et_element.find("BASE-VARIANT-PATTERN")) is not None:
base_variant_pattern = BaseVariantPattern.from_et(bvp_elem, doc_frags)

parent_refs = [
ParentRef.from_et(pr_elem, doc_frags)
for pr_elem in et_element.iterfind("PARENT-REFS/PARENT-REF")
Expand All @@ -72,6 +77,7 @@ def from_et(et_element: ElementTree.Element,
diag_variables_raw=diag_variables_raw,
variable_groups=variable_groups,
dyn_defined_spec=dyn_defined_spec,
base_variant_pattern=base_variant_pattern,
parent_refs=parent_refs,
**kwargs)

Expand Down
16 changes: 16 additions & 0 deletions odxtools/diaglayers/ecuvariant.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkRef
from ..parentref import ParentRef
from ..variablegroup import HasVariableGroups, VariableGroup
from .basevariant import BaseVariant
from .diaglayer import DiagLayer
from .ecuvariantraw import EcuVariantRaw
from .hierarchyelement import HierarchyElement
Expand All @@ -38,6 +39,21 @@ def dyn_defined_spec(self) -> Optional[DynDefinedSpec]:
def parent_refs(self) -> List[ParentRef]:
return self.ecu_variant_raw.parent_refs

@property
def base_variant(self) -> Optional[BaseVariant]:
"""Return the base variant for the ECU variant
The ODX specification allows at a single base variant for each
ECU variant, cf checker rule 50 of appendix B.2 of the
specification document.
"""
for pr in self.ecu_variant_raw.parent_refs:
if isinstance(pr.layer, BaseVariant):
return pr.layer

return None

@property
def ecu_variant_patterns(self) -> List[EcuVariantPattern]:
return self.ecu_variant_raw.ecu_variant_patterns
Expand Down
171 changes: 0 additions & 171 deletions odxtools/ecuvariantmatcher.py

This file was deleted.

29 changes: 20 additions & 9 deletions odxtools/ecuvariantpattern.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
# SPDX-License-Identifier: MIT
from dataclasses import dataclass
from typing import List
from typing import List, Union
from xml.etree import ElementTree

from .exceptions import odxassert, odxrequire
from typing_extensions import override

from .exceptions import odxassert
from .matchingbasevariantparameter import MatchingBaseVariantParameter
from .matchingparameter import MatchingParameter
from .odxlink import OdxDocFragment
from .variantpattern import VariantPattern


@dataclass
class EcuVariantPattern:
class EcuVariantPattern(VariantPattern):
"""ECU variant patterns are variant patterns used to identify the
concrete variant of an ECU.
"""
matching_parameters: List[MatchingParameter]

@override
def get_matching_parameters(
self) -> Union[List[MatchingParameter], List[MatchingBaseVariantParameter]]:
return self.matching_parameters

@staticmethod
def from_et(et_element: ElementTree.Element,
doc_frags: List[OdxDocFragment]) -> "EcuVariantPattern":

mp_collection_el = odxrequire(et_element.find("MATCHING-PARAMETERS"))

matching_params = [
matching_parameters = [
MatchingParameter.from_et(mp_el, doc_frags)
for mp_el in mp_collection_el.iterfind("MATCHING-PARAMETER")
for mp_el in et_element.iterfind("MATCHING-PARAMETERS/"
"MATCHING-PARAMETER")
]

odxassert(len(matching_params) > 0) # required by ISO 22901-1 Figure 141
return EcuVariantPattern(matching_params)
odxassert(len(matching_parameters) > 0) # required by ISO 22901-1 Figure 141
return EcuVariantPattern(matching_parameters=matching_parameters)
Loading

0 comments on commit 5cc2c95

Please sign in to comment.