Skip to content

Commit

Permalink
Merge pull request #279 from andlaus/params_from_et
Browse files Browse the repository at this point in the history
Convert the parameter classes to the `.from_et()` pattern
  • Loading branch information
andlaus authored Mar 8, 2024
2 parents cda6e5e + 99de68a commit 076bbe3
Show file tree
Hide file tree
Showing 17 changed files with 399 additions and 236 deletions.
Binary file modified examples/somersault.pdx
Binary file not shown.
32 changes: 29 additions & 3 deletions odxtools/parameters/codedconstparameter.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
# SPDX-License-Identifier: MIT
import warnings
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Dict, Optional
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from xml.etree import ElementTree

from typing_extensions import override

from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
from ..decodestate import DecodeState
from ..diagcodedtype import DiagCodedType
from ..encodestate import EncodeState
from ..exceptions import DecodeError
from ..odxlink import OdxLinkDatabase, OdxLinkId
from ..exceptions import DecodeError, odxrequire
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
from ..odxtypes import AtomicOdxType, DataType
from ..utils import dataclass_fields_asdict
from .parameter import Parameter, ParameterType

if TYPE_CHECKING:
Expand All @@ -23,23 +26,43 @@ class CodedConstParameter(Parameter):
diag_coded_type: DiagCodedType
coded_value: AtomicOdxType

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

kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))

dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
coded_value = diag_coded_type.base_data_type.from_string(
odxrequire(et_element.findtext("CODED-VALUE")))

return CodedConstParameter(
diag_coded_type=diag_coded_type, coded_value=coded_value, **kwargs)

@property
@override
def parameter_type(self) -> ParameterType:
return "CODED-CONST"

@override
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
result = super()._build_odxlinks()

result.update(self.diag_coded_type._build_odxlinks())

return result

@override
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
super()._resolve_odxlinks(odxlinks)

@override
def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
super()._resolve_snrefs(diag_layer)

@override
def get_static_bit_length(self) -> Optional[int]:
return self.diag_coded_type.get_static_bit_length()

Expand All @@ -48,13 +71,16 @@ def internal_data_type(self) -> DataType:
return self.diag_coded_type.base_data_type

@property
@override
def is_required(self) -> bool:
return False

@property
@override
def is_settable(self) -> bool:
return False

@override
def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
if (self.short_name in encode_state.parameter_values and
encode_state.parameter_values[self.short_name] != self.coded_value):
Expand Down
214 changes: 19 additions & 195 deletions odxtools/parameters/createanyparameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
from typing import List
from xml.etree import ElementTree

from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
from ..createsdgs import create_sdgs_from_et
from ..element import NamedElement
from ..exceptions import odxrequire
from ..exceptions import odxraise
from ..globals import xsi
from ..odxlink import OdxDocFragment, OdxLinkId, OdxLinkRef
from ..utils import dataclass_fields_asdict
from ..odxlink import OdxDocFragment
from .codedconstparameter import CodedConstParameter
from .dynamicparameter import DynamicParameter
from .lengthkeyparameter import LengthKeyParameter
Expand All @@ -27,205 +23,33 @@
def create_any_parameter_from_et(et_element: ElementTree.Element,
doc_frags: List[OdxDocFragment]) \
-> Parameter:
kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
semantic = et_element.get("SEMANTIC")
byte_position_str = et_element.findtext("BYTE-POSITION")
byte_position = int(byte_position_str) if byte_position_str is not None else None
bit_position_str = et_element.findtext("BIT-POSITION")
bit_position = None
if bit_position_str is not None:
bit_position = int(bit_position_str)
parameter_type = et_element.get(f"{xsi}type")

sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)

# Which attributes are set depends on the type of the parameter.
dop_ref = None
dop_snref = None
if parameter_type in ["VALUE", "PHYS-CONST", "SYSTEM", "LENGTH-KEY"]:
dop_ref = OdxLinkRef.from_et(et_element.find("DOP-REF"), doc_frags)
dop_snref = None
if (dop_snref_elem := et_element.find("DOP-SNREF")) is not None:
dop_snref = odxrequire(dop_snref_elem.get("SHORT-NAME"))

if dop_ref is None and dop_snref is None:
raise ValueError(
f"A parameter of type {parameter_type} must reference a DOP! {dop_ref}, {dop_snref}"
)

if parameter_type == "VALUE":
physical_default_value_raw = (
et_element.findtext("PHYSICAL-DEFAULT-VALUE")
if et_element.find("PHYSICAL-DEFAULT-VALUE") is not None else None)

return ValueParameter(
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
dop_ref=dop_ref,
dop_snref=dop_snref,
physical_default_value_raw=physical_default_value_raw,
sdgs=sdgs,
**kwargs)

elif parameter_type == "PHYS-CONST":
physical_constant_value = odxrequire(et_element.findtext("PHYS-CONSTANT-VALUE"))

return PhysicalConstantParameter(
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
dop_ref=dop_ref,
dop_snref=dop_snref,
physical_constant_value_raw=physical_constant_value,
sdgs=sdgs,
**kwargs)

return ValueParameter.from_et(et_element, doc_frags)
elif parameter_type == "CODED-CONST":
dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
coded_value = diag_coded_type.base_data_type.from_string(
odxrequire(et_element.findtext("CODED-VALUE")))

return CodedConstParameter(
semantic=semantic,
diag_coded_type=diag_coded_type,
coded_value=coded_value,
byte_position=byte_position,
bit_position=bit_position,
sdgs=sdgs,
**kwargs)

return CodedConstParameter.from_et(et_element, doc_frags)
elif parameter_type == "PHYS-CONST":
return PhysicalConstantParameter.from_et(et_element, doc_frags)
elif parameter_type == "SYSTEM":
return SystemParameter.from_et(et_element, doc_frags)
elif parameter_type == "LENGTH-KEY":
return LengthKeyParameter.from_et(et_element, doc_frags)
elif parameter_type == "NRC-CONST":
diag_coded_type = create_any_diag_coded_type_from_et(
odxrequire(et_element.find("DIAG-CODED-TYPE")), doc_frags)
coded_values = [
diag_coded_type.base_data_type.from_string(odxrequire(val.text))
for val in et_element.iterfind("CODED-VALUES/CODED-VALUE")
]

return NrcConstParameter(
semantic=semantic,
diag_coded_type=diag_coded_type,
coded_values=coded_values,
byte_position=byte_position,
bit_position=bit_position,
sdgs=sdgs,
**kwargs)

return NrcConstParameter.from_et(et_element, doc_frags)
elif parameter_type == "RESERVED":
bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))

return ReservedParameter(
bit_length=bit_length,
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
sdgs=sdgs,
**kwargs)

return ReservedParameter.from_et(et_element, doc_frags)
elif parameter_type == "MATCHING-REQUEST-PARAM":
byte_length = int(odxrequire(et_element.findtext("BYTE-LENGTH")))
request_byte_pos = int(odxrequire(et_element.findtext("REQUEST-BYTE-POS")))

return MatchingRequestParameter(
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
request_byte_position=request_byte_pos,
byte_length=byte_length,
sdgs=sdgs,
**kwargs)

elif parameter_type == "SYSTEM":
sysparam = odxrequire(et_element.get("SYSPARAM"))

return SystemParameter(
sysparam=sysparam,
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
dop_ref=dop_ref,
dop_snref=dop_snref,
sdgs=sdgs,
**kwargs)

elif parameter_type == "LENGTH-KEY":
odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))

return LengthKeyParameter(
odx_id=odx_id,
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
dop_ref=dop_ref,
dop_snref=dop_snref,
sdgs=sdgs,
**kwargs)

return MatchingRequestParameter.from_et(et_element, doc_frags)
elif parameter_type == "DYNAMIC":

return DynamicParameter(
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
sdgs=sdgs,
**kwargs)

return DynamicParameter.from_et(et_element, doc_frags)
elif parameter_type == "TABLE-STRUCT":
key_ref = OdxLinkRef.from_et(et_element.find("TABLE-KEY-REF"), doc_frags)
if (key_snref_elem := et_element.find("TABLE-KEY-SNREF")) is not None:
key_snref = odxrequire(key_snref_elem.get("SHORT-NAME"))
else:
key_snref = None

return TableStructParameter(
table_key_ref=key_ref,
table_key_snref=key_snref,
semantic=semantic,
byte_position=byte_position,
bit_position=bit_position,
sdgs=sdgs,
**kwargs)

return TableStructParameter.from_et(et_element, doc_frags)
elif parameter_type == "TABLE-KEY":

parameter_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
table_ref = OdxLinkRef.from_et(et_element.find("TABLE-REF"), doc_frags)
if (table_snref_elem := et_element.find("TABLE-SNREF")) is not None:
table_snref = odxrequire(table_snref_elem.get("SHORT-NAME"))
else:
table_snref = None

table_row_ref = OdxLinkRef.from_et(et_element.find("TABLE-ROW-REF"), doc_frags)
if (table_row_snref_elem := et_element.find("TABLE-ROW-SNREF")) is not None:
table_row_snref = odxrequire(table_row_snref_elem.get("SHORT-NAME"))
else:
table_row_snref = None

return TableKeyParameter(
table_ref=table_ref,
table_snref=table_snref,
table_row_snref=table_row_snref,
table_row_ref=table_row_ref,
odx_id=parameter_id,
byte_position=byte_position,
bit_position=bit_position,
semantic=semantic,
sdgs=sdgs,
**kwargs)

return TableKeyParameter.from_et(et_element, doc_frags)
elif parameter_type == "TABLE-ENTRY":
target = odxrequire(et_element.findtext("TARGET"))
table_row_ref = odxrequire(OdxLinkRef.from_et(et_element.find("TABLE-ROW-REF"), doc_frags))

return TableEntryParameter(
target=target,
table_row_ref=table_row_ref,
byte_position=byte_position,
bit_position=bit_position,
semantic=semantic,
sdgs=sdgs,
**kwargs)
return TableEntryParameter.from_et(et_element, doc_frags)

raise NotImplementedError(f"I don't know about parameters of type {parameter_type}")
odxraise(f"I don't know about parameters of type {parameter_type}", NotImplementedError)
return Parameter.from_et(et_element, doc_frags)
17 changes: 17 additions & 0 deletions odxtools/parameters/dynamicparameter.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
# SPDX-License-Identifier: MIT
from dataclasses import dataclass
from typing import List
from xml.etree import ElementTree

from typing_extensions import override

from ..decodestate import DecodeState
from ..encodestate import EncodeState
from ..odxlink import OdxDocFragment
from ..odxtypes import ParameterValue
from ..utils import dataclass_fields_asdict
from .parameter import Parameter, ParameterType


@dataclass
class DynamicParameter(Parameter):

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

kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))

return DynamicParameter(**kwargs)

@property
@override
def parameter_type(self) -> ParameterType:
return "DYNAMIC"

@property
@override
def is_required(self) -> bool:
raise NotImplementedError(".is_required for a DynamicParameter")

@property
@override
def is_settable(self) -> bool:
raise NotImplementedError(".is_settable for a DynamicParameter")

@override
def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
raise NotImplementedError("Encoding a DynamicParameter is not implemented yet.")

Expand Down
Loading

0 comments on commit 076bbe3

Please sign in to comment.