odxtools 6.6.1__py3-none-any.whl → 6.7.1__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 (81) hide show
  1. odxtools/__init__.py +5 -5
  2. odxtools/basicstructure.py +7 -8
  3. odxtools/cli/_parser_utils.py +15 -0
  4. odxtools/cli/_print_utils.py +4 -3
  5. odxtools/cli/browse.py +19 -14
  6. odxtools/cli/compare.py +24 -16
  7. odxtools/cli/decode.py +2 -1
  8. odxtools/cli/dummy_sub_parser.py +3 -1
  9. odxtools/cli/find.py +2 -1
  10. odxtools/cli/list.py +2 -1
  11. odxtools/cli/main.py +1 -0
  12. odxtools/cli/snoop.py +4 -1
  13. odxtools/comparaminstance.py +7 -5
  14. odxtools/compumethods/compumethod.py +2 -4
  15. odxtools/compumethods/compuscale.py +45 -5
  16. odxtools/compumethods/createanycompumethod.py +28 -36
  17. odxtools/compumethods/limit.py +70 -36
  18. odxtools/compumethods/linearcompumethod.py +68 -59
  19. odxtools/compumethods/tabintpcompumethod.py +19 -8
  20. odxtools/compumethods/texttablecompumethod.py +32 -36
  21. odxtools/dataobjectproperty.py +13 -10
  22. odxtools/decodestate.py +6 -3
  23. odxtools/determinenumberofitems.py +1 -1
  24. odxtools/diagcodedtype.py +5 -4
  25. odxtools/diagdatadictionaryspec.py +108 -83
  26. odxtools/diaglayer.py +75 -35
  27. odxtools/diaglayertype.py +17 -5
  28. odxtools/diagservice.py +1 -1
  29. odxtools/dopbase.py +4 -2
  30. odxtools/dtcdop.py +7 -5
  31. odxtools/dynamiclengthfield.py +6 -5
  32. odxtools/endofpdufield.py +4 -4
  33. odxtools/environmentdatadescription.py +4 -2
  34. odxtools/inputparam.py +1 -1
  35. odxtools/internalconstr.py +14 -5
  36. odxtools/isotp_state_machine.py +14 -6
  37. odxtools/message.py +1 -1
  38. odxtools/multiplexer.py +18 -13
  39. odxtools/multiplexercase.py +27 -5
  40. odxtools/multiplexerswitchkey.py +1 -1
  41. odxtools/nameditemlist.py +7 -6
  42. odxtools/odxlink.py +2 -2
  43. odxtools/odxtypes.py +56 -3
  44. odxtools/outputparam.py +2 -2
  45. odxtools/parameterinfo.py +12 -5
  46. odxtools/parameters/codedconstparameter.py +33 -12
  47. odxtools/parameters/createanyparameter.py +19 -193
  48. odxtools/parameters/dynamicparameter.py +21 -1
  49. odxtools/parameters/lengthkeyparameter.py +28 -4
  50. odxtools/parameters/matchingrequestparameter.py +27 -9
  51. odxtools/parameters/nrcconstparameter.py +34 -11
  52. odxtools/parameters/parameter.py +58 -32
  53. odxtools/parameters/parameterwithdop.py +28 -15
  54. odxtools/parameters/physicalconstantparameter.py +28 -4
  55. odxtools/parameters/reservedparameter.py +32 -18
  56. odxtools/parameters/systemparameter.py +25 -2
  57. odxtools/parameters/tableentryparameter.py +45 -6
  58. odxtools/parameters/tablekeyparameter.py +43 -10
  59. odxtools/parameters/tablestructparameter.py +36 -14
  60. odxtools/parameters/valueparameter.py +24 -2
  61. odxtools/paramlengthinfotype.py +4 -1
  62. odxtools/parentref.py +4 -1
  63. odxtools/scaleconstr.py +11 -5
  64. odxtools/statetransition.py +1 -1
  65. odxtools/staticfield.py +101 -0
  66. odxtools/table.py +2 -1
  67. odxtools/tablerow.py +11 -4
  68. odxtools/templates/macros/printDOP.xml.jinja2 +30 -34
  69. odxtools/templates/macros/printMux.xml.jinja2 +3 -2
  70. odxtools/templates/macros/printParam.xml.jinja2 +9 -9
  71. odxtools/templates/macros/printStaticField.xml.jinja2 +15 -0
  72. odxtools/templates/macros/printVariant.xml.jinja2 +8 -0
  73. odxtools/uds.py +2 -2
  74. odxtools/version.py +2 -2
  75. odxtools/write_pdx_file.py +3 -3
  76. {odxtools-6.6.1.dist-info → odxtools-6.7.1.dist-info}/METADATA +28 -16
  77. {odxtools-6.6.1.dist-info → odxtools-6.7.1.dist-info}/RECORD +81 -79
  78. {odxtools-6.6.1.dist-info → odxtools-6.7.1.dist-info}/WHEEL +1 -1
  79. {odxtools-6.6.1.dist-info → odxtools-6.7.1.dist-info}/LICENSE +0 -0
  80. {odxtools-6.6.1.dist-info → odxtools-6.7.1.dist-info}/entry_points.txt +0 -0
  81. {odxtools-6.6.1.dist-info → odxtools-6.7.1.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,19 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import warnings
3
3
  from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any, Dict, Optional
4
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional
5
+ from xml.etree import ElementTree
5
6
 
7
+ from typing_extensions import override
8
+
9
+ from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
6
10
  from ..decodestate import DecodeState
7
11
  from ..diagcodedtype import DiagCodedType
8
12
  from ..encodestate import EncodeState
9
- from ..exceptions import DecodeError
10
- from ..odxlink import OdxLinkDatabase, OdxLinkId
13
+ from ..exceptions import DecodeError, odxrequire
14
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
11
15
  from ..odxtypes import AtomicOdxType, DataType
16
+ from ..utils import dataclass_fields_asdict
12
17
  from .parameter import Parameter, ParameterType
13
18
 
14
19
  if TYPE_CHECKING:
@@ -21,10 +26,27 @@ class CodedConstParameter(Parameter):
21
26
  diag_coded_type: DiagCodedType
22
27
  coded_value: AtomicOdxType
23
28
 
29
+ @staticmethod
30
+ @override
31
+ def from_et(et_element: ElementTree.Element,
32
+ doc_frags: List[OdxDocFragment]) -> "CodedConstParameter":
33
+
34
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
35
+
36
+ dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
37
+ diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
38
+ coded_value = diag_coded_type.base_data_type.from_string(
39
+ odxrequire(et_element.findtext("CODED-VALUE")))
40
+
41
+ return CodedConstParameter(
42
+ diag_coded_type=diag_coded_type, coded_value=coded_value, **kwargs)
43
+
24
44
  @property
45
+ @override
25
46
  def parameter_type(self) -> ParameterType:
26
47
  return "CODED-CONST"
27
48
 
49
+ @override
28
50
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
29
51
  result = super()._build_odxlinks()
30
52
 
@@ -32,12 +54,15 @@ class CodedConstParameter(Parameter):
32
54
 
33
55
  return result
34
56
 
57
+ @override
35
58
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
36
59
  super()._resolve_odxlinks(odxlinks)
37
60
 
61
+ @override
38
62
  def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
39
63
  super()._resolve_snrefs(diag_layer)
40
64
 
65
+ @override
41
66
  def get_static_bit_length(self) -> Optional[int]:
42
67
  return self.diag_coded_type.get_static_bit_length()
43
68
 
@@ -46,13 +71,16 @@ class CodedConstParameter(Parameter):
46
71
  return self.diag_coded_type.base_data_type
47
72
 
48
73
  @property
74
+ @override
49
75
  def is_required(self) -> bool:
50
76
  return False
51
77
 
52
78
  @property
79
+ @override
53
80
  def is_settable(self) -> bool:
54
81
  return False
55
82
 
83
+ @override
56
84
  def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
57
85
  if (self.short_name in encode_state.parameter_values and
58
86
  encode_state.parameter_values[self.short_name] != self.coded_value):
@@ -62,13 +90,8 @@ class CodedConstParameter(Parameter):
62
90
  return self.diag_coded_type.convert_internal_to_bytes(
63
91
  self.coded_value, encode_state=encode_state, bit_position=bit_position_int)
64
92
 
65
- def decode_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
66
- # Extract coded values
67
- orig_cursor_pos = decode_state.cursor_byte_position
68
- if self.byte_position is not None:
69
- decode_state.cursor_byte_position = decode_state.origin_byte_position + self.byte_position
70
-
71
- decode_state.cursor_bit_position = self.bit_position or 0
93
+ @override
94
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
72
95
  coded_val = self.diag_coded_type.decode_from_pdu(decode_state)
73
96
 
74
97
  # Check if the coded value in the message is correct.
@@ -83,8 +106,6 @@ class CodedConstParameter(Parameter):
83
106
  stacklevel=1,
84
107
  )
85
108
 
86
- decode_state.cursor_byte_position = max(orig_cursor_pos, decode_state.cursor_byte_position)
87
-
88
109
  return coded_val
89
110
 
90
111
  @property
@@ -2,13 +2,9 @@
2
2
  from typing import List
3
3
  from xml.etree import ElementTree
4
4
 
5
- from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
6
- from ..createsdgs import create_sdgs_from_et
7
- from ..element import NamedElement
8
- from ..exceptions import odxrequire
5
+ from ..exceptions import odxraise
9
6
  from ..globals import xsi
10
- from ..odxlink import OdxDocFragment, OdxLinkId, OdxLinkRef
11
- from ..utils import dataclass_fields_asdict
7
+ from ..odxlink import OdxDocFragment
12
8
  from .codedconstparameter import CodedConstParameter
13
9
  from .dynamicparameter import DynamicParameter
14
10
  from .lengthkeyparameter import LengthKeyParameter
@@ -27,203 +23,33 @@ from .valueparameter import ValueParameter
27
23
  def create_any_parameter_from_et(et_element: ElementTree.Element,
28
24
  doc_frags: List[OdxDocFragment]) \
29
25
  -> Parameter:
30
- kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
31
- semantic = et_element.get("SEMANTIC")
32
- byte_position_str = et_element.findtext("BYTE-POSITION")
33
- byte_position = int(byte_position_str) if byte_position_str is not None else None
34
- bit_position_str = et_element.findtext("BIT-POSITION")
35
- bit_position = None
36
- if bit_position_str is not None:
37
- bit_position = int(bit_position_str)
38
26
  parameter_type = et_element.get(f"{xsi}type")
39
27
 
40
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
41
-
42
28
  # Which attributes are set depends on the type of the parameter.
43
- if parameter_type in ["VALUE", "PHYS-CONST", "SYSTEM", "LENGTH-KEY"]:
44
- dop_ref = OdxLinkRef.from_et(et_element.find("DOP-REF"), doc_frags)
45
- dop_snref = None
46
- if (dop_snref_elem := et_element.find("DOP-SNREF")) is not None:
47
- dop_snref = odxrequire(dop_snref_elem.get("SHORT-NAME"))
48
-
49
- if dop_ref is None and dop_snref is None:
50
- raise ValueError(
51
- f"A parameter of type {parameter_type} must reference a DOP! {dop_ref}, {dop_snref}"
52
- )
53
-
54
29
  if parameter_type == "VALUE":
55
- physical_default_value_raw = (
56
- et_element.findtext("PHYSICAL-DEFAULT-VALUE")
57
- if et_element.find("PHYSICAL-DEFAULT-VALUE") is not None else None)
58
-
59
- return ValueParameter(
60
- semantic=semantic,
61
- byte_position=byte_position,
62
- bit_position=bit_position,
63
- dop_ref=dop_ref,
64
- dop_snref=dop_snref,
65
- physical_default_value_raw=physical_default_value_raw,
66
- sdgs=sdgs,
67
- **kwargs)
68
-
69
- elif parameter_type == "PHYS-CONST":
70
- physical_constant_value = odxrequire(et_element.findtext("PHYS-CONSTANT-VALUE"))
71
-
72
- return PhysicalConstantParameter(
73
- semantic=semantic,
74
- byte_position=byte_position,
75
- bit_position=bit_position,
76
- dop_ref=dop_ref,
77
- dop_snref=dop_snref,
78
- physical_constant_value_raw=physical_constant_value,
79
- sdgs=sdgs,
80
- **kwargs)
81
-
30
+ return ValueParameter.from_et(et_element, doc_frags)
82
31
  elif parameter_type == "CODED-CONST":
83
- dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
84
- diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
85
- coded_value = diag_coded_type.base_data_type.from_string(
86
- odxrequire(et_element.findtext("CODED-VALUE")))
87
-
88
- return CodedConstParameter(
89
- semantic=semantic,
90
- diag_coded_type=diag_coded_type,
91
- coded_value=coded_value,
92
- byte_position=byte_position,
93
- bit_position=bit_position,
94
- sdgs=sdgs,
95
- **kwargs)
96
-
32
+ return CodedConstParameter.from_et(et_element, doc_frags)
33
+ elif parameter_type == "PHYS-CONST":
34
+ return PhysicalConstantParameter.from_et(et_element, doc_frags)
35
+ elif parameter_type == "SYSTEM":
36
+ return SystemParameter.from_et(et_element, doc_frags)
37
+ elif parameter_type == "LENGTH-KEY":
38
+ return LengthKeyParameter.from_et(et_element, doc_frags)
97
39
  elif parameter_type == "NRC-CONST":
98
- diag_coded_type = create_any_diag_coded_type_from_et(
99
- odxrequire(et_element.find("DIAG-CODED-TYPE")), doc_frags)
100
- coded_values = [
101
- diag_coded_type.base_data_type.from_string(odxrequire(val.text))
102
- for val in et_element.iterfind("CODED-VALUES/CODED-VALUE")
103
- ]
104
-
105
- return NrcConstParameter(
106
- semantic=semantic,
107
- diag_coded_type=diag_coded_type,
108
- coded_values=coded_values,
109
- byte_position=byte_position,
110
- bit_position=bit_position,
111
- sdgs=sdgs,
112
- **kwargs)
113
-
40
+ return NrcConstParameter.from_et(et_element, doc_frags)
114
41
  elif parameter_type == "RESERVED":
115
- bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
116
-
117
- return ReservedParameter(
118
- bit_length=bit_length,
119
- semantic=semantic,
120
- byte_position=byte_position,
121
- bit_position=bit_position,
122
- sdgs=sdgs,
123
- **kwargs)
124
-
42
+ return ReservedParameter.from_et(et_element, doc_frags)
125
43
  elif parameter_type == "MATCHING-REQUEST-PARAM":
126
- byte_length = int(odxrequire(et_element.findtext("BYTE-LENGTH")))
127
- request_byte_pos = int(odxrequire(et_element.findtext("REQUEST-BYTE-POS")))
128
-
129
- return MatchingRequestParameter(
130
- semantic=semantic,
131
- byte_position=byte_position,
132
- bit_position=bit_position,
133
- request_byte_position=request_byte_pos,
134
- byte_length=byte_length,
135
- sdgs=sdgs,
136
- **kwargs)
137
-
138
- elif parameter_type == "SYSTEM":
139
- sysparam = odxrequire(et_element.get("SYSPARAM"))
140
-
141
- return SystemParameter(
142
- sysparam=sysparam,
143
- semantic=semantic,
144
- byte_position=byte_position,
145
- bit_position=bit_position,
146
- dop_ref=dop_ref,
147
- dop_snref=dop_snref,
148
- sdgs=sdgs,
149
- **kwargs)
150
-
151
- elif parameter_type == "LENGTH-KEY":
152
- odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
153
-
154
- return LengthKeyParameter(
155
- odx_id=odx_id,
156
- semantic=semantic,
157
- byte_position=byte_position,
158
- bit_position=bit_position,
159
- dop_ref=dop_ref,
160
- dop_snref=dop_snref,
161
- sdgs=sdgs,
162
- **kwargs)
163
-
44
+ return MatchingRequestParameter.from_et(et_element, doc_frags)
164
45
  elif parameter_type == "DYNAMIC":
165
-
166
- return DynamicParameter(
167
- semantic=semantic,
168
- byte_position=byte_position,
169
- bit_position=bit_position,
170
- sdgs=sdgs,
171
- **kwargs)
172
-
46
+ return DynamicParameter.from_et(et_element, doc_frags)
173
47
  elif parameter_type == "TABLE-STRUCT":
174
- key_ref = OdxLinkRef.from_et(et_element.find("TABLE-KEY-REF"), doc_frags)
175
- if (key_snref_elem := et_element.find("TABLE-KEY-SNREF")) is not None:
176
- key_snref = odxrequire(key_snref_elem.get("SHORT-NAME"))
177
- else:
178
- key_snref = None
179
-
180
- return TableStructParameter(
181
- table_key_ref=key_ref,
182
- table_key_snref=key_snref,
183
- semantic=semantic,
184
- byte_position=byte_position,
185
- bit_position=bit_position,
186
- sdgs=sdgs,
187
- **kwargs)
188
-
48
+ return TableStructParameter.from_et(et_element, doc_frags)
189
49
  elif parameter_type == "TABLE-KEY":
190
-
191
- parameter_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
192
- table_ref = OdxLinkRef.from_et(et_element.find("TABLE-REF"), doc_frags)
193
- if (table_snref_elem := et_element.find("TABLE-SNREF")) is not None:
194
- table_snref = odxrequire(table_snref_elem.get("SHORT-NAME"))
195
- else:
196
- table_snref = None
197
-
198
- table_row_ref = OdxLinkRef.from_et(et_element.find("TABLE-ROW-REF"), doc_frags)
199
- if (table_row_snref_elem := et_element.find("TABLE-ROW-SNREF")) is not None:
200
- table_row_snref = odxrequire(table_row_snref_elem.get("SHORT-NAME"))
201
- else:
202
- table_row_snref = None
203
-
204
- return TableKeyParameter(
205
- table_ref=table_ref,
206
- table_snref=table_snref,
207
- table_row_snref=table_row_snref,
208
- table_row_ref=table_row_ref,
209
- odx_id=parameter_id,
210
- byte_position=byte_position,
211
- bit_position=bit_position,
212
- semantic=semantic,
213
- sdgs=sdgs,
214
- **kwargs)
215
-
50
+ return TableKeyParameter.from_et(et_element, doc_frags)
216
51
  elif parameter_type == "TABLE-ENTRY":
217
- target = odxrequire(et_element.findtext("TARGET"))
218
- table_row_ref = odxrequire(OdxLinkRef.from_et(et_element.find("TABLE-ROW-REF"), doc_frags))
219
-
220
- return TableEntryParameter(
221
- target=target,
222
- table_row_ref=table_row_ref,
223
- byte_position=byte_position,
224
- bit_position=bit_position,
225
- semantic=semantic,
226
- sdgs=sdgs,
227
- **kwargs)
52
+ return TableEntryParameter.from_et(et_element, doc_frags)
228
53
 
229
- raise NotImplementedError(f"I don't know about parameters of type {parameter_type}")
54
+ odxraise(f"I don't know about parameters of type {parameter_type}", NotImplementedError)
55
+ return Parameter.from_et(et_element, doc_frags)
@@ -1,29 +1,49 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
+ from typing import List
4
+ from xml.etree import ElementTree
5
+
6
+ from typing_extensions import override
3
7
 
4
8
  from ..decodestate import DecodeState
5
9
  from ..encodestate import EncodeState
10
+ from ..odxlink import OdxDocFragment
6
11
  from ..odxtypes import ParameterValue
12
+ from ..utils import dataclass_fields_asdict
7
13
  from .parameter import Parameter, ParameterType
8
14
 
9
15
 
10
16
  @dataclass
11
17
  class DynamicParameter(Parameter):
12
18
 
19
+ @staticmethod
20
+ @override
21
+ def from_et(et_element: ElementTree.Element,
22
+ doc_frags: List[OdxDocFragment]) -> "DynamicParameter":
23
+
24
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
25
+
26
+ return DynamicParameter(**kwargs)
27
+
13
28
  @property
29
+ @override
14
30
  def parameter_type(self) -> ParameterType:
15
31
  return "DYNAMIC"
16
32
 
17
33
  @property
34
+ @override
18
35
  def is_required(self) -> bool:
19
36
  raise NotImplementedError(".is_required for a DynamicParameter")
20
37
 
21
38
  @property
39
+ @override
22
40
  def is_settable(self) -> bool:
23
41
  raise NotImplementedError(".is_settable for a DynamicParameter")
24
42
 
43
+ @override
25
44
  def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
26
45
  raise NotImplementedError("Encoding a DynamicParameter is not implemented yet.")
27
46
 
28
- def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
47
+ @override
48
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
29
49
  raise NotImplementedError("Decoding a DynamicParameter is not implemented yet.")
@@ -1,12 +1,16 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict
3
+ from typing import TYPE_CHECKING, Any, Dict, List
4
+ from xml.etree import ElementTree
5
+
6
+ from typing_extensions import override
4
7
 
5
8
  from ..decodestate import DecodeState
6
9
  from ..encodestate import EncodeState
7
10
  from ..exceptions import odxraise, odxrequire
8
- from ..odxlink import OdxLinkDatabase, OdxLinkId
11
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
9
12
  from ..odxtypes import ParameterValue
13
+ from ..utils import dataclass_fields_asdict
10
14
  from .parameter import ParameterType
11
15
  from .parameterwithdop import ParameterWithDOP
12
16
 
@@ -27,10 +31,23 @@ class LengthKeyParameter(ParameterWithDOP):
27
31
 
28
32
  odx_id: OdxLinkId
29
33
 
34
+ @staticmethod
35
+ @override
36
+ def from_et(et_element: ElementTree.Element,
37
+ doc_frags: List[OdxDocFragment]) -> "LengthKeyParameter":
38
+
39
+ kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
40
+
41
+ odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
42
+
43
+ return LengthKeyParameter(odx_id=odx_id, **kwargs)
44
+
30
45
  @property
46
+ @override
31
47
  def parameter_type(self) -> ParameterType:
32
48
  return "LENGTH-KEY"
33
49
 
50
+ @override
34
51
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
35
52
  result = super()._build_odxlinks()
36
53
 
@@ -38,23 +55,28 @@ class LengthKeyParameter(ParameterWithDOP):
38
55
 
39
56
  return result
40
57
 
58
+ @override
41
59
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
42
60
  super()._resolve_odxlinks(odxlinks)
43
61
 
62
+ @override
44
63
  def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
45
64
  super()._resolve_snrefs(diag_layer)
46
65
 
47
66
  @property
67
+ @override
48
68
  def is_required(self) -> bool:
49
69
  return False
50
70
 
51
71
  @property
72
+ @override
52
73
  def is_settable(self) -> bool:
53
74
  # length keys can be explicitly set, but they do not need to
54
75
  # be because they can be implicitly determined by the length
55
76
  # of the corresponding field
56
77
  return True
57
78
 
79
+ @override
58
80
  def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
59
81
  physical_value = encode_state.parameter_values.get(self.short_name, 0)
60
82
 
@@ -63,11 +85,13 @@ class LengthKeyParameter(ParameterWithDOP):
63
85
  f"A DOP is required for length key parameter {self.short_name}")
64
86
  return dop.convert_physical_to_bytes(physical_value, encode_state, bit_position=bit_pos)
65
87
 
88
+ @override
66
89
  def encode_into_pdu(self, encode_state: EncodeState) -> bytes:
67
90
  return super().encode_into_pdu(encode_state)
68
91
 
69
- def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
70
- phys_val = super().decode_from_pdu(decode_state)
92
+ @override
93
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
94
+ phys_val = super()._decode_positioned_from_pdu(decode_state)
71
95
 
72
96
  if not isinstance(phys_val, int):
73
97
  odxraise(f"The pysical type of length keys must be an integer, "
@@ -1,11 +1,16 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Optional
3
+ from typing import List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from typing_extensions import override
4
7
 
5
8
  from ..decodestate import DecodeState
6
9
  from ..encodestate import EncodeState
7
- from ..exceptions import EncodeError
10
+ from ..exceptions import EncodeError, odxrequire
11
+ from ..odxlink import OdxDocFragment
8
12
  from ..odxtypes import DataType, ParameterValue
13
+ from ..utils import dataclass_fields_asdict
9
14
  from .parameter import Parameter, ParameterType
10
15
 
11
16
 
@@ -14,21 +19,39 @@ class MatchingRequestParameter(Parameter):
14
19
  request_byte_position: int
15
20
  byte_length: int
16
21
 
22
+ @staticmethod
23
+ @override
24
+ def from_et(et_element: ElementTree.Element,
25
+ doc_frags: List[OdxDocFragment]) -> "MatchingRequestParameter":
26
+
27
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
28
+
29
+ request_byte_position = int(odxrequire(et_element.findtext("REQUEST-BYTE-POS")))
30
+ byte_length = int(odxrequire(et_element.findtext("BYTE-LENGTH")))
31
+
32
+ return MatchingRequestParameter(
33
+ request_byte_position=request_byte_position, byte_length=byte_length, **kwargs)
34
+
17
35
  @property
36
+ @override
18
37
  def parameter_type(self) -> ParameterType:
19
38
  return "MATCHING-REQUEST-PARAM"
20
39
 
40
+ @override
21
41
  def get_static_bit_length(self) -> Optional[int]:
22
42
  return 8 * self.byte_length
23
43
 
24
44
  @property
45
+ @override
25
46
  def is_required(self) -> bool:
26
47
  return False
27
48
 
28
49
  @property
50
+ @override
29
51
  def is_settable(self) -> bool:
30
52
  return False
31
53
 
54
+ @override
32
55
  def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
33
56
  if not encode_state.triggering_request:
34
57
  raise EncodeError(f"Parameter '{self.short_name}' is of matching request type,"
@@ -37,16 +60,11 @@ class MatchingRequestParameter(Parameter):
37
60
  .request_byte_position:self.request_byte_position +
38
61
  self.byte_length]
39
62
 
40
- def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
41
- orig_cursor = decode_state.cursor_byte_position
42
- if self.byte_position is not None:
43
- decode_state.cursor_byte_position = decode_state.origin_byte_position + self.byte_position
44
-
63
+ @override
64
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
45
65
  result = decode_state.extract_atomic_value(
46
66
  bit_length=self.byte_length * 8,
47
67
  base_data_type=DataType.A_UINT32,
48
68
  is_highlow_byte_order=False)
49
69
 
50
- decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
51
-
52
70
  return result
@@ -2,13 +2,18 @@
2
2
  import warnings
3
3
  from dataclasses import dataclass
4
4
  from typing import TYPE_CHECKING, Any, Dict, List, Optional
5
+ from xml.etree import ElementTree
5
6
 
7
+ from typing_extensions import override
8
+
9
+ from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
6
10
  from ..decodestate import DecodeState
7
11
  from ..diagcodedtype import DiagCodedType
8
12
  from ..encodestate import EncodeState
9
- from ..exceptions import DecodeError, EncodeError
10
- from ..odxlink import OdxLinkDatabase, OdxLinkId
13
+ from ..exceptions import DecodeError, EncodeError, odxrequire
14
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
11
15
  from ..odxtypes import AtomicOdxType, DataType
16
+ from ..utils import dataclass_fields_asdict
12
17
  from .parameter import Parameter, ParameterType
13
18
 
14
19
  if TYPE_CHECKING:
@@ -29,10 +34,29 @@ class NrcConstParameter(Parameter):
29
34
  diag_coded_type: DiagCodedType
30
35
  coded_values: List[AtomicOdxType]
31
36
 
37
+ @staticmethod
38
+ @override
39
+ def from_et(et_element: ElementTree.Element,
40
+ doc_frags: List[OdxDocFragment]) -> "NrcConstParameter":
41
+
42
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
43
+
44
+ dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
45
+ diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
46
+ coded_values = [
47
+ diag_coded_type.base_data_type.from_string(odxrequire(val.text))
48
+ for val in et_element.iterfind("CODED-VALUES/CODED-VALUE")
49
+ ]
50
+
51
+ return NrcConstParameter(
52
+ diag_coded_type=diag_coded_type, coded_values=coded_values, **kwargs)
53
+
32
54
  @property
55
+ @override
33
56
  def parameter_type(self) -> ParameterType:
34
57
  return "NRC-CONST"
35
58
 
59
+ @override
36
60
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
37
61
  result = super()._build_odxlinks()
38
62
 
@@ -40,12 +64,15 @@ class NrcConstParameter(Parameter):
40
64
 
41
65
  return result
42
66
 
67
+ @override
43
68
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
44
69
  super()._resolve_odxlinks(odxlinks)
45
70
 
71
+ @override
46
72
  def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
47
73
  super()._resolve_snrefs(diag_layer)
48
74
 
75
+ @override
49
76
  def get_static_bit_length(self) -> Optional[int]:
50
77
  return self.diag_coded_type.get_static_bit_length()
51
78
 
@@ -54,13 +81,16 @@ class NrcConstParameter(Parameter):
54
81
  return self.diag_coded_type.base_data_type
55
82
 
56
83
  @property
84
+ @override
57
85
  def is_required(self) -> bool:
58
86
  return False
59
87
 
60
88
  @property
89
+ @override
61
90
  def is_settable(self) -> bool:
62
91
  return False
63
92
 
93
+ @override
64
94
  def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
65
95
  if self.short_name in encode_state.parameter_values:
66
96
  if encode_state.parameter_values[self.short_name] not in self.coded_values:
@@ -77,14 +107,9 @@ class NrcConstParameter(Parameter):
77
107
  return self.diag_coded_type.convert_internal_to_bytes(
78
108
  coded_value, encode_state, bit_position=bit_position_int)
79
109
 
80
- def decode_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
81
- orig_cursor = decode_state.cursor_byte_position
82
- if self.byte_position is not None:
83
- # Update cursor position
84
- decode_state.cursor_byte_position = decode_state.origin_byte_position + self.byte_position
85
-
110
+ @override
111
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
86
112
  # Extract coded values
87
- decode_state.cursor_bit_position = self.bit_position or 0
88
113
  coded_value = self.diag_coded_type.decode_from_pdu(decode_state)
89
114
 
90
115
  # Check if the coded value in the message is correct.
@@ -99,8 +124,6 @@ class NrcConstParameter(Parameter):
99
124
  stacklevel=1,
100
125
  )
101
126
 
102
- decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
103
-
104
127
  return coded_value
105
128
 
106
129
  def get_description_of_valid_values(self) -> str: