odxtools 9.6.1__py3-none-any.whl → 10.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.
- odxtools/additionalaudience.py +3 -3
- odxtools/addressing.py +8 -0
- odxtools/admindata.py +8 -8
- odxtools/audience.py +10 -10
- odxtools/basecomparam.py +7 -20
- odxtools/basevariantpattern.py +4 -5
- odxtools/basicstructure.py +12 -11
- odxtools/cli/_print_utils.py +35 -23
- odxtools/cli/browse.py +9 -9
- odxtools/cli/compare.py +24 -24
- odxtools/cli/decode.py +3 -4
- odxtools/cli/find.py +4 -5
- odxtools/cli/list.py +7 -7
- odxtools/cli/main.py +2 -2
- odxtools/cli/snoop.py +3 -3
- odxtools/codec.py +3 -186
- odxtools/commrelation.py +12 -19
- odxtools/commrelationvaluetype.py +9 -0
- odxtools/companydata.py +5 -5
- odxtools/companydocinfo.py +8 -8
- odxtools/companyrevisioninfo.py +5 -5
- odxtools/companyspecificinfo.py +5 -5
- odxtools/comparam.py +3 -3
- odxtools/comparaminstance.py +10 -10
- odxtools/comparamspec.py +3 -3
- odxtools/comparamsubset.py +5 -5
- odxtools/complexcomparam.py +7 -7
- odxtools/compositecodec.py +191 -0
- odxtools/compumethods/compucategory.py +13 -0
- odxtools/compumethods/compucodecompumethod.py +6 -5
- odxtools/compumethods/compuconst.py +4 -5
- odxtools/compumethods/compudefaultvalue.py +1 -2
- odxtools/compumethods/compuinternaltophys.py +6 -6
- odxtools/compumethods/compumethod.py +6 -17
- odxtools/compumethods/compuphystointernal.py +6 -6
- odxtools/compumethods/compurationalcoeffs.py +4 -4
- odxtools/compumethods/compuscale.py +9 -10
- odxtools/compumethods/createanycompumethod.py +1 -2
- odxtools/compumethods/identicalcompumethod.py +1 -2
- odxtools/compumethods/intervaltype.py +8 -0
- odxtools/compumethods/limit.py +13 -19
- odxtools/compumethods/linearcompumethod.py +4 -3
- odxtools/compumethods/linearsegment.py +14 -15
- odxtools/compumethods/ratfunccompumethod.py +5 -4
- odxtools/compumethods/ratfuncsegment.py +7 -8
- odxtools/compumethods/scalelinearcompumethod.py +10 -9
- odxtools/compumethods/scaleratfunccompumethod.py +6 -5
- odxtools/compumethods/tabintpcompumethod.py +19 -20
- odxtools/compumethods/texttablecompumethod.py +5 -4
- odxtools/createanycomparam.py +2 -4
- odxtools/createanydiagcodedtype.py +1 -2
- odxtools/database.py +9 -8
- odxtools/dataobjectproperty.py +10 -10
- odxtools/decodestate.py +5 -5
- odxtools/description.py +6 -22
- odxtools/determinenumberofitems.py +4 -4
- odxtools/diagclasstype.py +11 -0
- odxtools/diagcodedtype.py +7 -7
- odxtools/diagcomm.py +19 -42
- odxtools/diagdatadictionaryspec.py +6 -6
- odxtools/diaglayercontainer.py +4 -4
- odxtools/diaglayers/basevariant.py +10 -9
- odxtools/diaglayers/basevariantraw.py +9 -9
- odxtools/diaglayers/diaglayer.py +20 -19
- odxtools/diaglayers/diaglayerraw.py +10 -10
- odxtools/diaglayers/diaglayertype.py +1 -2
- odxtools/diaglayers/ecushareddata.py +4 -4
- odxtools/diaglayers/ecushareddataraw.py +6 -6
- odxtools/diaglayers/ecuvariant.py +11 -10
- odxtools/diaglayers/ecuvariantraw.py +9 -9
- odxtools/diaglayers/functionalgroup.py +8 -7
- odxtools/diaglayers/functionalgroupraw.py +7 -7
- odxtools/diaglayers/hierarchyelement.py +43 -49
- odxtools/diaglayers/hierarchyelementraw.py +4 -4
- odxtools/diaglayers/protocol.py +4 -4
- odxtools/diaglayers/protocolraw.py +6 -6
- odxtools/diagnostictroublecode.py +8 -8
- odxtools/diagservice.py +21 -97
- odxtools/diagvariable.py +14 -14
- odxtools/docrevision.py +11 -11
- odxtools/dopbase.py +6 -6
- odxtools/dtcconnector.py +45 -0
- odxtools/dtcdop.py +15 -56
- odxtools/dynamicendmarkerfield.py +5 -4
- odxtools/dynamiclengthfield.py +5 -4
- odxtools/dyndefinedspec.py +7 -159
- odxtools/dynenddopref.py +5 -5
- odxtools/dyniddefmodeinfo.py +161 -0
- odxtools/ecuvariantpattern.py +4 -5
- odxtools/element.py +5 -6
- odxtools/encodestate.py +11 -11
- odxtools/encoding.py +2 -3
- odxtools/endofpdufield.py +6 -6
- odxtools/envdataconnector.py +49 -0
- odxtools/environmentdata.py +3 -4
- odxtools/environmentdatadescription.py +11 -11
- odxtools/exceptions.py +5 -5
- odxtools/externalaccessmethod.py +22 -0
- odxtools/externaldoc.py +23 -0
- odxtools/field.py +9 -10
- odxtools/functionalclass.py +4 -4
- odxtools/inputparam.py +6 -6
- odxtools/internalconstr.py +4 -5
- odxtools/isotp_state_machine.py +12 -11
- odxtools/leadinglengthinfotype.py +2 -3
- odxtools/library.py +5 -5
- odxtools/linkeddtcdop.py +62 -0
- odxtools/loadfile.py +5 -6
- odxtools/matchingbasevariantparameter.py +2 -3
- odxtools/matchingparameter.py +7 -7
- odxtools/minmaxlengthtype.py +5 -11
- odxtools/modification.py +4 -4
- odxtools/multiplexer.py +11 -11
- odxtools/multiplexercase.py +6 -6
- odxtools/multiplexerdefaultcase.py +6 -6
- odxtools/multiplexerswitchkey.py +4 -4
- odxtools/nameditemlist.py +14 -14
- odxtools/negoutputparam.py +3 -3
- odxtools/obd.py +1 -2
- odxtools/odxcategory.py +6 -6
- odxtools/odxlink.py +19 -20
- odxtools/odxtypes.py +21 -18
- odxtools/outputparam.py +4 -4
- odxtools/parameterinfo.py +2 -2
- odxtools/parameters/codedconstparameter.py +5 -5
- odxtools/parameters/createanyparameter.py +1 -2
- odxtools/parameters/dynamicparameter.py +2 -3
- odxtools/parameters/lengthkeyparameter.py +5 -5
- odxtools/parameters/matchingrequestparameter.py +3 -4
- odxtools/parameters/nrcconstparameter.py +7 -7
- odxtools/parameters/parameter.py +11 -11
- odxtools/parameters/parameterwithdop.py +9 -9
- odxtools/parameters/physicalconstantparameter.py +4 -4
- odxtools/parameters/reservedparameter.py +3 -4
- odxtools/parameters/rowfragment.py +7 -0
- odxtools/parameters/systemparameter.py +2 -3
- odxtools/parameters/tableentryparameter.py +4 -9
- odxtools/parameters/tablekeyparameter.py +10 -10
- odxtools/parameters/tablestructparameter.py +7 -7
- odxtools/parameters/valueparameter.py +7 -7
- odxtools/paramlengthinfotype.py +5 -3
- odxtools/parentref.py +9 -9
- odxtools/physicaldimension.py +11 -11
- odxtools/physicaltype.py +4 -12
- odxtools/posresponsesuppressible.py +72 -0
- odxtools/preconditionstateref.py +7 -7
- odxtools/progcode.py +6 -6
- odxtools/protstack.py +4 -4
- odxtools/radix.py +9 -0
- odxtools/relateddiagcommref.py +22 -0
- odxtools/relateddoc.py +6 -6
- odxtools/request.py +14 -12
- odxtools/response.py +15 -13
- odxtools/scaleconstr.py +4 -12
- odxtools/servicebinner.py +5 -5
- odxtools/singleecujob.py +4 -4
- odxtools/snrefcontext.py +2 -2
- odxtools/specialdata.py +5 -5
- odxtools/specialdatagroup.py +9 -9
- odxtools/specialdatagroupcaption.py +3 -3
- odxtools/standardizationlevel.py +9 -0
- odxtools/standardlengthtype.py +12 -21
- odxtools/state.py +3 -3
- odxtools/statechart.py +4 -4
- odxtools/statemachine.py +4 -3
- odxtools/statetransition.py +5 -18
- odxtools/statetransitionref.py +18 -18
- odxtools/staticfield.py +5 -4
- odxtools/structure.py +2 -3
- odxtools/subcomponent.py +12 -245
- odxtools/subcomponentparamconnector.py +103 -0
- odxtools/subcomponentpattern.py +42 -0
- odxtools/swvariable.py +3 -4
- odxtools/table.py +17 -55
- odxtools/tablediagcommconnector.py +47 -0
- odxtools/tablerow.py +30 -30
- odxtools/tablerowconnector.py +46 -0
- odxtools/teammember.py +11 -11
- odxtools/templates/macros/printService.xml.jinja2 +2 -1
- odxtools/termination.py +8 -0
- odxtools/text.py +2 -3
- odxtools/transmode.py +9 -0
- odxtools/uds.py +2 -3
- odxtools/unit.py +9 -9
- odxtools/unitgroup.py +6 -11
- odxtools/unitgroupcategory.py +7 -0
- odxtools/unitspec.py +6 -6
- odxtools/usage.py +9 -0
- odxtools/utils.py +31 -2
- odxtools/validtype.py +9 -0
- odxtools/variablegroup.py +2 -2
- odxtools/variantmatcher.py +10 -10
- odxtools/variantpattern.py +3 -3
- odxtools/version.py +2 -2
- odxtools/writepdxfile.py +5 -5
- odxtools/xdoc.py +9 -9
- {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/METADATA +4 -5
- odxtools-10.0.0.dist-info/RECORD +264 -0
- odxtools-9.6.1.dist-info/RECORD +0 -238
- {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/WHEEL +0 -0
- {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/entry_points.txt +0 -0
- {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/licenses/LICENSE +0 -0
- {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/top_level.txt +0 -0
odxtools/comparamsubset.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, Any
|
3
|
+
from typing import TYPE_CHECKING, Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .comparam import Comparam
|
@@ -22,12 +22,12 @@ class ComparamSubset(OdxCategory):
|
|
22
22
|
comparams: NamedItemList[Comparam]
|
23
23
|
complex_comparams: NamedItemList[ComplexComparam]
|
24
24
|
data_object_props: NamedItemList[DataObjectProperty]
|
25
|
-
unit_spec:
|
26
|
-
category:
|
25
|
+
unit_spec: UnitSpec | None
|
26
|
+
category: str | None # mandatory in ODX 2.2, but non-existent in ODX 2.0
|
27
27
|
|
28
28
|
@staticmethod
|
29
29
|
def from_et(et_element: ElementTree.Element,
|
30
|
-
doc_frags:
|
30
|
+
doc_frags: list[OdxDocFragment]) -> "ComparamSubset":
|
31
31
|
|
32
32
|
category_attrib = et_element.attrib.get("CATEGORY")
|
33
33
|
|
@@ -64,7 +64,7 @@ class ComparamSubset(OdxCategory):
|
|
64
64
|
unit_spec=unit_spec,
|
65
65
|
**kwargs)
|
66
66
|
|
67
|
-
def _build_odxlinks(self) ->
|
67
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
68
68
|
odxlinks = super()._build_odxlinks()
|
69
69
|
|
70
70
|
for comparam in self.comparams:
|
odxtools/complexcomparam.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any,
|
3
|
+
from typing import Any, Union
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .basecomparam import BaseComparam
|
@@ -10,7 +10,7 @@ from .odxtypes import odxstr_to_bool
|
|
10
10
|
from .snrefcontext import SnRefContext
|
11
11
|
from .utils import dataclass_fields_asdict
|
12
12
|
|
13
|
-
ComplexValue =
|
13
|
+
ComplexValue = list[Union[str, "ComplexValue"]]
|
14
14
|
|
15
15
|
|
16
16
|
def create_complex_value_from_et(et_element: ElementTree.Element) -> ComplexValue:
|
@@ -26,8 +26,8 @@ def create_complex_value_from_et(et_element: ElementTree.Element) -> ComplexValu
|
|
26
26
|
@dataclass
|
27
27
|
class ComplexComparam(BaseComparam):
|
28
28
|
subparams: NamedItemList[BaseComparam]
|
29
|
-
physical_default_value:
|
30
|
-
allow_multiple_values_raw:
|
29
|
+
physical_default_value: ComplexValue | None
|
30
|
+
allow_multiple_values_raw: bool | None
|
31
31
|
|
32
32
|
@property
|
33
33
|
def allow_multiple_values(self) -> bool:
|
@@ -35,7 +35,7 @@ class ComplexComparam(BaseComparam):
|
|
35
35
|
|
36
36
|
@staticmethod
|
37
37
|
def from_et(et_element: ElementTree.Element,
|
38
|
-
doc_frags:
|
38
|
+
doc_frags: list[OdxDocFragment]) -> "ComplexComparam":
|
39
39
|
kwargs = dataclass_fields_asdict(BaseComparam.from_et(et_element, doc_frags))
|
40
40
|
|
41
41
|
# to avoid a cyclic import, create_any_comparam_from_et cannot
|
@@ -68,7 +68,7 @@ class ComplexComparam(BaseComparam):
|
|
68
68
|
# extract the complex physical default value. (what's the
|
69
69
|
# purpose of this? the sub-parameters can define their own
|
70
70
|
# default values if a default is desired...)
|
71
|
-
complex_physical_default_value:
|
71
|
+
complex_physical_default_value: ComplexValue | None = None
|
72
72
|
if (cpdv_elem := et_element.find("COMPLEX-PHYSICAL-DEFAULT-VALUE")) is not None:
|
73
73
|
complex_physical_default_value = create_complex_value_from_et(cpdv_elem)
|
74
74
|
|
@@ -80,7 +80,7 @@ class ComplexComparam(BaseComparam):
|
|
80
80
|
allow_multiple_values_raw=allow_multiple_values_raw,
|
81
81
|
**kwargs)
|
82
82
|
|
83
|
-
def _build_odxlinks(self) ->
|
83
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
84
84
|
odxlinks = super()._build_odxlinks()
|
85
85
|
for subparam in self.subparams:
|
86
86
|
odxlinks.update(subparam._build_odxlinks())
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
import typing
|
3
|
+
from typing import runtime_checkable
|
4
|
+
|
5
|
+
from .codec import Codec
|
6
|
+
from .decodestate import DecodeState
|
7
|
+
from .encodestate import EncodeState
|
8
|
+
from .exceptions import EncodeError, odxraise
|
9
|
+
from .odxtypes import ParameterValue
|
10
|
+
from .parameters.codedconstparameter import CodedConstParameter
|
11
|
+
from .parameters.matchingrequestparameter import MatchingRequestParameter
|
12
|
+
from .parameters.parameter import Parameter
|
13
|
+
from .parameters.physicalconstantparameter import PhysicalConstantParameter
|
14
|
+
|
15
|
+
|
16
|
+
@runtime_checkable
|
17
|
+
class CompositeCodec(Codec, typing.Protocol):
|
18
|
+
"""Any object which can be en- or decoded to be transferred over
|
19
|
+
the wire which is composed of multiple parameter implements this
|
20
|
+
API.
|
21
|
+
|
22
|
+
"""
|
23
|
+
|
24
|
+
@property
|
25
|
+
def parameters(self) -> list[Parameter]:
|
26
|
+
return []
|
27
|
+
|
28
|
+
@property
|
29
|
+
def required_parameters(self) -> list[Parameter]:
|
30
|
+
return []
|
31
|
+
|
32
|
+
@property
|
33
|
+
def free_parameters(self) -> list[Parameter]:
|
34
|
+
return []
|
35
|
+
|
36
|
+
|
37
|
+
# some helper functions useful for composite codec objects
|
38
|
+
def composite_codec_get_static_bit_length(codec: CompositeCodec) -> int | None:
|
39
|
+
"""Compute the length of a composite codec object in bits
|
40
|
+
|
41
|
+
This is basically the sum of the lengths of all parameters. If the
|
42
|
+
length of any parameter can only determined at runtime, `None` is
|
43
|
+
returned.
|
44
|
+
"""
|
45
|
+
|
46
|
+
cursor = 0
|
47
|
+
byte_length = 0
|
48
|
+
for param in codec.parameters:
|
49
|
+
param_bit_length = param.get_static_bit_length()
|
50
|
+
if param_bit_length is None:
|
51
|
+
# We were not able to calculate a static bit length
|
52
|
+
return None
|
53
|
+
elif param.byte_position is not None:
|
54
|
+
cursor = param.byte_position
|
55
|
+
|
56
|
+
cursor += ((param.bit_position or 0) + param_bit_length + 7) // 8
|
57
|
+
byte_length = max(byte_length, cursor)
|
58
|
+
|
59
|
+
return byte_length * 8
|
60
|
+
|
61
|
+
|
62
|
+
def composite_codec_get_required_parameters(codec: CompositeCodec) -> list[Parameter]:
|
63
|
+
"""Return the list of parameters which are required to be
|
64
|
+
specified for encoding the composite codec object
|
65
|
+
|
66
|
+
I.e., all free parameters that do not exhibit a default value.
|
67
|
+
"""
|
68
|
+
return [p for p in codec.parameters if p.is_required]
|
69
|
+
|
70
|
+
|
71
|
+
def composite_codec_get_free_parameters(codec: CompositeCodec) -> list[Parameter]:
|
72
|
+
"""Return the list of parameters which can be freely specified by
|
73
|
+
the user when encoding the composite codec object
|
74
|
+
|
75
|
+
This means all required parameters plus parameters that can be
|
76
|
+
omitted because they specify a default.
|
77
|
+
"""
|
78
|
+
return [p for p in codec.parameters if p.is_settable]
|
79
|
+
|
80
|
+
|
81
|
+
def composite_codec_get_coded_const_prefix(codec: CompositeCodec,
|
82
|
+
request_prefix: bytes = b'') -> bytes:
|
83
|
+
encode_state = EncodeState(coded_message=bytearray(), triggering_request=request_prefix)
|
84
|
+
|
85
|
+
for param in codec.parameters:
|
86
|
+
if (isinstance(param, MatchingRequestParameter) and param.request_byte_position < len(request_prefix)) or \
|
87
|
+
isinstance(param, CodedConstParameter|PhysicalConstantParameter) :
|
88
|
+
param.encode_into_pdu(physical_value=None, encode_state=encode_state)
|
89
|
+
else:
|
90
|
+
break
|
91
|
+
|
92
|
+
return encode_state.coded_message
|
93
|
+
|
94
|
+
|
95
|
+
def composite_codec_encode_into_pdu(codec: CompositeCodec, physical_value: ParameterValue | None,
|
96
|
+
encode_state: EncodeState) -> None:
|
97
|
+
from .parameters.lengthkeyparameter import LengthKeyParameter
|
98
|
+
from .parameters.tablekeyparameter import TableKeyParameter
|
99
|
+
|
100
|
+
if not isinstance(physical_value, dict):
|
101
|
+
odxraise(
|
102
|
+
f"Expected a dictionary for the values of {codec.short_name}, "
|
103
|
+
f"got {type(physical_value).__name__}", EncodeError)
|
104
|
+
elif encode_state.cursor_bit_position != 0:
|
105
|
+
odxraise(
|
106
|
+
f"Compositional codec objecs must be byte aligned, but "
|
107
|
+
f"{codec.short_name} requested to be at bit position "
|
108
|
+
f"{encode_state.cursor_bit_position}", EncodeError)
|
109
|
+
encode_state.bit_position = 0
|
110
|
+
|
111
|
+
orig_origin = encode_state.origin_byte_position
|
112
|
+
encode_state.origin_byte_position = encode_state.cursor_byte_position
|
113
|
+
|
114
|
+
orig_is_end_of_pdu = encode_state.is_end_of_pdu
|
115
|
+
encode_state.is_end_of_pdu = False
|
116
|
+
|
117
|
+
# ensure that no values for unknown parameters are specified.
|
118
|
+
if not encode_state.allow_unknown_parameters:
|
119
|
+
param_names = {param.short_name for param in codec.parameters}
|
120
|
+
for param_value_name in physical_value:
|
121
|
+
if param_value_name not in param_names:
|
122
|
+
odxraise(f"Value for unknown parameter '{param_value_name}' specified "
|
123
|
+
f"for composite codec object {codec.short_name}")
|
124
|
+
|
125
|
+
for param in codec.parameters:
|
126
|
+
if id(param) == id(codec.parameters[-1]):
|
127
|
+
# The last parameter of the composite codec object is at
|
128
|
+
# the end of the PDU if the codec object itself is at the
|
129
|
+
# end of the PDU.
|
130
|
+
#
|
131
|
+
# TODO: This assumes that the last parameter specified in
|
132
|
+
# the ODX is located last in the PDU...
|
133
|
+
encode_state.is_end_of_pdu = orig_is_end_of_pdu
|
134
|
+
|
135
|
+
if isinstance(param, LengthKeyParameter | TableKeyParameter):
|
136
|
+
# At this point, we encode a placeholder value for length-
|
137
|
+
# and table keys, since these can be specified
|
138
|
+
# implicitly (i.e., by means of parameters that use
|
139
|
+
# these keys). To avoid getting an "overlapping
|
140
|
+
# parameter" warning, we must encode a value of zero
|
141
|
+
# into the PDU here and add the real value of the
|
142
|
+
# parameter in a post-processing step.
|
143
|
+
param.encode_placeholder_into_pdu(
|
144
|
+
physical_value=physical_value.get(param.short_name), encode_state=encode_state)
|
145
|
+
|
146
|
+
continue
|
147
|
+
|
148
|
+
if param.is_required and param.short_name not in physical_value:
|
149
|
+
odxraise(f"No value for required parameter {param.short_name} specified", EncodeError)
|
150
|
+
|
151
|
+
param_phys_value = physical_value.get(param.short_name)
|
152
|
+
param.encode_into_pdu(physical_value=param_phys_value, encode_state=encode_state)
|
153
|
+
|
154
|
+
encode_state.journal.append((param, param_phys_value))
|
155
|
+
|
156
|
+
encode_state.is_end_of_pdu = False
|
157
|
+
|
158
|
+
# encode the length- and table keys. This cannot be done above
|
159
|
+
# because we allow these to be defined implicitly (i.e. they
|
160
|
+
# are defined by their respective users)
|
161
|
+
for param in codec.parameters:
|
162
|
+
if not isinstance(param, LengthKeyParameter | TableKeyParameter):
|
163
|
+
# the current parameter is neither a length- nor a table key
|
164
|
+
continue
|
165
|
+
|
166
|
+
# Encode the value of the key parameter into the message
|
167
|
+
param.encode_value_into_pdu(encode_state=encode_state)
|
168
|
+
|
169
|
+
encode_state.origin_byte_position = orig_origin
|
170
|
+
|
171
|
+
|
172
|
+
def composite_codec_decode_from_pdu(codec: CompositeCodec,
|
173
|
+
decode_state: DecodeState) -> ParameterValue:
|
174
|
+
# move the origin since positions specified by sub-parameters of
|
175
|
+
# composite codec objects are relative to the beginning of the
|
176
|
+
# object.
|
177
|
+
orig_origin = decode_state.origin_byte_position
|
178
|
+
decode_state.origin_byte_position = decode_state.cursor_byte_position
|
179
|
+
|
180
|
+
result = {}
|
181
|
+
for param in codec.parameters:
|
182
|
+
value = param.decode_from_pdu(decode_state)
|
183
|
+
|
184
|
+
decode_state.journal.append((param, value))
|
185
|
+
result[param.short_name] = value
|
186
|
+
|
187
|
+
# decoding of the composite codec object finished. go back the
|
188
|
+
# original origin.
|
189
|
+
decode_state.origin_byte_position = orig_origin
|
190
|
+
|
191
|
+
return result
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from enum import Enum
|
3
|
+
|
4
|
+
|
5
|
+
class CompuCategory(Enum):
|
6
|
+
IDENTICAL = "IDENTICAL"
|
7
|
+
LINEAR = "LINEAR"
|
8
|
+
SCALE_LINEAR = "SCALE-LINEAR"
|
9
|
+
TEXTTABLE = "TEXTTABLE"
|
10
|
+
COMPUCODE = "COMPUCODE"
|
11
|
+
TAB_INTP = "TAB-INTP"
|
12
|
+
RAT_FUNC = "RAT-FUNC"
|
13
|
+
SCALE_RAT_FUNC = "SCALE-RAT-FUNC"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
|
@@ -8,7 +8,8 @@ from ..odxlink import OdxDocFragment
|
|
8
8
|
from ..odxtypes import AtomicOdxType, DataType
|
9
9
|
from ..progcode import ProgCode
|
10
10
|
from ..utils import dataclass_fields_asdict
|
11
|
-
from .
|
11
|
+
from .compucategory import CompuCategory
|
12
|
+
from .compumethod import CompuMethod
|
12
13
|
|
13
14
|
|
14
15
|
@dataclass
|
@@ -19,21 +20,21 @@ class CompuCodeCompuMethod(CompuMethod):
|
|
19
20
|
"""
|
20
21
|
|
21
22
|
@property
|
22
|
-
def internal_to_phys_code(self) ->
|
23
|
+
def internal_to_phys_code(self) -> ProgCode | None:
|
23
24
|
if self.compu_internal_to_phys is None:
|
24
25
|
return None
|
25
26
|
|
26
27
|
return self.compu_internal_to_phys.prog_code
|
27
28
|
|
28
29
|
@property
|
29
|
-
def phys_to_internal_code(self) ->
|
30
|
+
def phys_to_internal_code(self) -> ProgCode | None:
|
30
31
|
if self.compu_phys_to_internal is None:
|
31
32
|
return None
|
32
33
|
|
33
34
|
return self.compu_phys_to_internal.prog_code
|
34
35
|
|
35
36
|
@staticmethod
|
36
|
-
def compu_method_from_et(et_element: ElementTree.Element, doc_frags:
|
37
|
+
def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
|
37
38
|
internal_type: DataType,
|
38
39
|
physical_type: DataType) -> "CompuCodeCompuMethod":
|
39
40
|
cm = CompuMethod.compu_method_from_et(
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Optional
|
4
3
|
from xml.etree import ElementTree
|
5
4
|
|
6
5
|
from ..odxtypes import AtomicOdxType, DataType
|
@@ -8,13 +7,13 @@ from ..odxtypes import AtomicOdxType, DataType
|
|
8
7
|
|
9
8
|
@dataclass
|
10
9
|
class CompuConst:
|
11
|
-
v:
|
12
|
-
vt:
|
10
|
+
v: str | None
|
11
|
+
vt: str | None
|
13
12
|
|
14
13
|
data_type: DataType
|
15
14
|
|
16
15
|
@property
|
17
|
-
def value(self) ->
|
16
|
+
def value(self) -> AtomicOdxType | None:
|
18
17
|
return self._value
|
19
18
|
|
20
19
|
@staticmethod
|
@@ -26,6 +25,6 @@ class CompuConst:
|
|
26
25
|
return CompuConst(v=v, vt=vt, data_type=data_type)
|
27
26
|
|
28
27
|
def __post_init__(self) -> None:
|
29
|
-
self._value:
|
28
|
+
self._value: AtomicOdxType | None = self.vt
|
30
29
|
if self.v is not None:
|
31
30
|
self._value = self.data_type.from_string(self.v)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Optional
|
4
3
|
from xml.etree import ElementTree
|
5
4
|
|
6
5
|
from ..odxtypes import DataType
|
@@ -11,7 +10,7 @@ from .compuinversevalue import CompuInverseValue
|
|
11
10
|
|
12
11
|
@dataclass
|
13
12
|
class CompuDefaultValue(CompuConst):
|
14
|
-
compu_inverse_value:
|
13
|
+
compu_inverse_value: CompuInverseValue | None
|
15
14
|
|
16
15
|
@staticmethod
|
17
16
|
def compuvalue_from_et(et_element: ElementTree.Element, *,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
@@ -13,13 +13,13 @@ from .compuscale import CompuScale
|
|
13
13
|
|
14
14
|
@dataclass
|
15
15
|
class CompuInternalToPhys:
|
16
|
-
compu_scales:
|
17
|
-
prog_code:
|
18
|
-
compu_default_value:
|
16
|
+
compu_scales: list[CompuScale]
|
17
|
+
prog_code: ProgCode | None
|
18
|
+
compu_default_value: CompuDefaultValue | None
|
19
19
|
|
20
20
|
@staticmethod
|
21
21
|
def compu_internal_to_phys_from_et(et_element: ElementTree.Element,
|
22
|
-
doc_frags:
|
22
|
+
doc_frags: list[OdxDocFragment], *, internal_type: DataType,
|
23
23
|
physical_type: DataType) -> "CompuInternalToPhys":
|
24
24
|
compu_scales = [
|
25
25
|
CompuScale.compuscale_from_et(
|
@@ -39,7 +39,7 @@ class CompuInternalToPhys:
|
|
39
39
|
return CompuInternalToPhys(
|
40
40
|
compu_scales=compu_scales, prog_code=prog_code, compu_default_value=compu_default_value)
|
41
41
|
|
42
|
-
def _build_odxlinks(self) ->
|
42
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
43
43
|
result = {}
|
44
44
|
|
45
45
|
if self.prog_code is not None:
|
@@ -1,28 +1,17 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from
|
4
|
-
from typing import Any, Dict, List, Optional
|
3
|
+
from typing import Any
|
5
4
|
from xml.etree import ElementTree
|
6
5
|
|
7
6
|
from ..exceptions import odxraise
|
8
7
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
9
8
|
from ..odxtypes import AtomicOdxType, DataType
|
10
9
|
from ..snrefcontext import SnRefContext
|
10
|
+
from .compucategory import CompuCategory
|
11
11
|
from .compuinternaltophys import CompuInternalToPhys
|
12
12
|
from .compuphystointernal import CompuPhysToInternal
|
13
13
|
|
14
14
|
|
15
|
-
class CompuCategory(Enum):
|
16
|
-
IDENTICAL = "IDENTICAL"
|
17
|
-
LINEAR = "LINEAR"
|
18
|
-
SCALE_LINEAR = "SCALE-LINEAR"
|
19
|
-
TEXTTABLE = "TEXTTABLE"
|
20
|
-
COMPUCODE = "COMPUCODE"
|
21
|
-
TAB_INTP = "TAB-INTP"
|
22
|
-
RAT_FUNC = "RAT-FUNC"
|
23
|
-
SCALE_RAT_FUNC = "SCALE-RAT-FUNC"
|
24
|
-
|
25
|
-
|
26
15
|
@dataclass
|
27
16
|
class CompuMethod:
|
28
17
|
"""A compu method translates between the internal representation
|
@@ -42,14 +31,14 @@ class CompuMethod:
|
|
42
31
|
"""
|
43
32
|
|
44
33
|
category: CompuCategory
|
45
|
-
compu_internal_to_phys:
|
46
|
-
compu_phys_to_internal:
|
34
|
+
compu_internal_to_phys: CompuInternalToPhys | None
|
35
|
+
compu_phys_to_internal: CompuPhysToInternal | None
|
47
36
|
|
48
37
|
physical_type: DataType
|
49
38
|
internal_type: DataType
|
50
39
|
|
51
40
|
@staticmethod
|
52
|
-
def compu_method_from_et(et_element: ElementTree.Element, doc_frags:
|
41
|
+
def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
|
53
42
|
internal_type: DataType, physical_type: DataType) -> "CompuMethod":
|
54
43
|
cat_text = et_element.findtext("CATEGORY")
|
55
44
|
if cat_text is None:
|
@@ -78,7 +67,7 @@ class CompuMethod:
|
|
78
67
|
physical_type=physical_type,
|
79
68
|
internal_type=internal_type)
|
80
69
|
|
81
|
-
def _build_odxlinks(self) ->
|
70
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
82
71
|
result = {}
|
83
72
|
|
84
73
|
if self.compu_internal_to_phys is not None:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
@@ -13,13 +13,13 @@ from .compuscale import CompuScale
|
|
13
13
|
|
14
14
|
@dataclass
|
15
15
|
class CompuPhysToInternal:
|
16
|
-
compu_scales:
|
17
|
-
prog_code:
|
18
|
-
compu_default_value:
|
16
|
+
compu_scales: list[CompuScale]
|
17
|
+
prog_code: ProgCode | None
|
18
|
+
compu_default_value: CompuDefaultValue | None
|
19
19
|
|
20
20
|
@staticmethod
|
21
21
|
def compu_phys_to_internal_from_et(et_element: ElementTree.Element,
|
22
|
-
doc_frags:
|
22
|
+
doc_frags: list[OdxDocFragment], *, internal_type: DataType,
|
23
23
|
physical_type: DataType) -> "CompuPhysToInternal":
|
24
24
|
compu_scales = [
|
25
25
|
CompuScale.compuscale_from_et(
|
@@ -39,7 +39,7 @@ class CompuPhysToInternal:
|
|
39
39
|
return CompuPhysToInternal(
|
40
40
|
compu_scales=compu_scales, prog_code=prog_code, compu_default_value=compu_default_value)
|
41
41
|
|
42
|
-
def _build_odxlinks(self) ->
|
42
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
43
43
|
result = {}
|
44
44
|
|
45
45
|
if self.prog_code is not None:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..exceptions import odxassert, odxrequire
|
@@ -12,11 +12,11 @@ from ..odxtypes import DataType
|
|
12
12
|
class CompuRationalCoeffs:
|
13
13
|
value_type: DataType
|
14
14
|
|
15
|
-
numerators:
|
16
|
-
denominators:
|
15
|
+
numerators: list[int | float]
|
16
|
+
denominators: list[int | float]
|
17
17
|
|
18
18
|
@staticmethod
|
19
|
-
def coeffs_from_et(et_element: ElementTree.Element, doc_frags:
|
19
|
+
def coeffs_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
|
20
20
|
value_type: DataType) -> "CompuRationalCoeffs":
|
21
21
|
odxassert(
|
22
22
|
value_type
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import List, Optional
|
4
3
|
from xml.etree import ElementTree
|
5
4
|
|
6
5
|
from ..description import Description
|
@@ -17,13 +16,13 @@ class CompuScale:
|
|
17
16
|
"""A COMPU-SCALE represents one value range of a COMPU-METHOD.
|
18
17
|
"""
|
19
18
|
|
20
|
-
short_label:
|
21
|
-
description:
|
22
|
-
lower_limit:
|
23
|
-
upper_limit:
|
24
|
-
compu_inverse_value:
|
25
|
-
compu_const:
|
26
|
-
compu_rational_coeffs:
|
19
|
+
short_label: str | None
|
20
|
+
description: Description | None
|
21
|
+
lower_limit: Limit | None
|
22
|
+
upper_limit: Limit | None
|
23
|
+
compu_inverse_value: CompuInverseValue | None
|
24
|
+
compu_const: CompuConst | None
|
25
|
+
compu_rational_coeffs: CompuRationalCoeffs | None
|
27
26
|
|
28
27
|
# the following two attributes are not specified for COMPU-SCALE
|
29
28
|
# tags in the XML, but they are required to do anything useful
|
@@ -38,7 +37,7 @@ class CompuScale:
|
|
38
37
|
range_type: DataType
|
39
38
|
|
40
39
|
@staticmethod
|
41
|
-
def compuscale_from_et(et_element: ElementTree.Element, doc_frags:
|
40
|
+
def compuscale_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
|
42
41
|
domain_type: DataType, range_type: DataType) -> "CompuScale":
|
43
42
|
short_label = et_element.findtext("SHORT-LABEL")
|
44
43
|
description = Description.from_et(et_element.find("DESC"), doc_frags)
|
@@ -56,7 +55,7 @@ class CompuScale:
|
|
56
55
|
if (cce := et_element.find("COMPU-CONST")) is not None:
|
57
56
|
compu_const = CompuConst.compuvalue_from_et(cce, data_type=range_type)
|
58
57
|
|
59
|
-
compu_rational_coeffs:
|
58
|
+
compu_rational_coeffs: CompuRationalCoeffs | None = None
|
60
59
|
if (crc_elem := et_element.find("COMPU-RATIONAL-COEFFS")) is not None:
|
61
60
|
compu_rational_coeffs = CompuRationalCoeffs.coeffs_from_et(
|
62
61
|
crc_elem, doc_frags, value_type=range_type)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from typing import List
|
3
2
|
from xml.etree import ElementTree
|
4
3
|
|
5
4
|
from ..exceptions import odxraise, odxrequire
|
@@ -17,7 +16,7 @@ from .texttablecompumethod import TexttableCompuMethod
|
|
17
16
|
|
18
17
|
|
19
18
|
def create_any_compu_method_from_et(et_element: ElementTree.Element,
|
20
|
-
doc_frags:
|
19
|
+
doc_frags: list[OdxDocFragment], *, internal_type: DataType,
|
21
20
|
physical_type: DataType) -> CompuMethod:
|
22
21
|
compu_category = odxrequire(et_element.findtext("CATEGORY"))
|
23
22
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import List
|
4
3
|
from xml.etree import ElementTree
|
5
4
|
|
6
5
|
from ..exceptions import odxassert
|
@@ -18,7 +17,7 @@ class IdenticalCompuMethod(CompuMethod):
|
|
18
17
|
"""
|
19
18
|
|
20
19
|
@staticmethod
|
21
|
-
def compu_method_from_et(et_element: ElementTree.Element, doc_frags:
|
20
|
+
def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
|
22
21
|
internal_type: DataType,
|
23
22
|
physical_type: DataType) -> "IdenticalCompuMethod":
|
24
23
|
cm = CompuMethod.compu_method_from_et(
|