odxtools 7.1.1__py3-none-any.whl → 7.3.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.
Files changed (135) hide show
  1. odxtools/__init__.py +6 -4
  2. odxtools/additionalaudience.py +3 -5
  3. odxtools/admindata.py +5 -7
  4. odxtools/audience.py +3 -5
  5. odxtools/basecomparam.py +3 -5
  6. odxtools/basicstructure.py +19 -23
  7. odxtools/cli/_parser_utils.py +1 -1
  8. odxtools/cli/_print_utils.py +3 -2
  9. odxtools/cli/compare.py +1 -1
  10. odxtools/companydata.py +5 -7
  11. odxtools/companydocinfo.py +7 -8
  12. odxtools/companyrevisioninfo.py +3 -5
  13. odxtools/companyspecificinfo.py +8 -9
  14. odxtools/comparam.py +4 -6
  15. odxtools/comparaminstance.py +6 -8
  16. odxtools/comparamspec.py +14 -13
  17. odxtools/comparamsubset.py +17 -16
  18. odxtools/complexcomparam.py +5 -7
  19. odxtools/compumethods/compuconst.py +31 -0
  20. odxtools/compumethods/compudefaultvalue.py +27 -0
  21. odxtools/compumethods/compuinternaltophys.py +39 -0
  22. odxtools/compumethods/compuinversevalue.py +7 -0
  23. odxtools/compumethods/compumethod.py +67 -12
  24. odxtools/compumethods/compuphystointernal.py +39 -0
  25. odxtools/compumethods/compuscale.py +15 -26
  26. odxtools/compumethods/createanycompumethod.py +14 -160
  27. odxtools/compumethods/identicalcompumethod.py +31 -6
  28. odxtools/compumethods/linearcompumethod.py +69 -189
  29. odxtools/compumethods/linearsegment.py +191 -0
  30. odxtools/compumethods/scalelinearcompumethod.py +132 -26
  31. odxtools/compumethods/tabintpcompumethod.py +119 -99
  32. odxtools/compumethods/texttablecompumethod.py +107 -43
  33. odxtools/createanydiagcodedtype.py +10 -67
  34. odxtools/database.py +84 -72
  35. odxtools/dataobjectproperty.py +10 -19
  36. odxtools/decodestate.py +8 -2
  37. odxtools/description.py +47 -0
  38. odxtools/determinenumberofitems.py +4 -5
  39. odxtools/diagcodedtype.py +29 -12
  40. odxtools/diagcomm.py +10 -6
  41. odxtools/diagdatadictionaryspec.py +20 -21
  42. odxtools/diaglayer.py +39 -9
  43. odxtools/diaglayercontainer.py +17 -11
  44. odxtools/diaglayerraw.py +20 -21
  45. odxtools/diagnostictroublecode.py +8 -9
  46. odxtools/diagservice.py +42 -27
  47. odxtools/docrevision.py +5 -7
  48. odxtools/dopbase.py +7 -8
  49. odxtools/dtcdop.py +44 -22
  50. odxtools/dynamicendmarkerfield.py +22 -9
  51. odxtools/dynamiclengthfield.py +5 -11
  52. odxtools/element.py +4 -3
  53. odxtools/encodestate.py +14 -2
  54. odxtools/endofpdufield.py +0 -2
  55. odxtools/environmentdatadescription.py +137 -19
  56. odxtools/exceptions.py +11 -2
  57. odxtools/field.py +9 -9
  58. odxtools/functionalclass.py +3 -5
  59. odxtools/inputparam.py +3 -5
  60. odxtools/leadinglengthinfotype.py +15 -2
  61. odxtools/loadfile.py +64 -0
  62. odxtools/minmaxlengthtype.py +20 -2
  63. odxtools/modification.py +3 -5
  64. odxtools/multiplexer.py +98 -69
  65. odxtools/multiplexercase.py +10 -11
  66. odxtools/multiplexerdefaultcase.py +11 -12
  67. odxtools/multiplexerswitchkey.py +4 -5
  68. odxtools/negoutputparam.py +3 -5
  69. odxtools/odxlink.py +12 -26
  70. odxtools/odxtypes.py +1 -1
  71. odxtools/outputparam.py +3 -5
  72. odxtools/parameterinfo.py +5 -5
  73. odxtools/parameters/codedconstparameter.py +2 -14
  74. odxtools/parameters/lengthkeyparameter.py +3 -17
  75. odxtools/parameters/nrcconstparameter.py +29 -50
  76. odxtools/parameters/parameter.py +22 -22
  77. odxtools/parameters/parameterwithdop.py +6 -8
  78. odxtools/parameters/physicalconstantparameter.py +5 -8
  79. odxtools/parameters/reservedparameter.py +4 -3
  80. odxtools/parameters/systemparameter.py +1 -1
  81. odxtools/parameters/tablekeyparameter.py +6 -9
  82. odxtools/parameters/tablestructparameter.py +6 -8
  83. odxtools/parameters/valueparameter.py +5 -8
  84. odxtools/paramlengthinfotype.py +19 -6
  85. odxtools/parentref.py +15 -1
  86. odxtools/physicaldimension.py +3 -5
  87. odxtools/progcode.py +18 -7
  88. odxtools/protstack.py +3 -5
  89. odxtools/relateddoc.py +7 -9
  90. odxtools/request.py +8 -0
  91. odxtools/response.py +8 -0
  92. odxtools/scaleconstr.py +3 -3
  93. odxtools/singleecujob.py +12 -10
  94. odxtools/snrefcontext.py +29 -0
  95. odxtools/specialdata.py +3 -5
  96. odxtools/specialdatagroup.py +5 -7
  97. odxtools/specialdatagroupcaption.py +3 -6
  98. odxtools/standardlengthtype.py +27 -2
  99. odxtools/state.py +3 -5
  100. odxtools/statechart.py +9 -11
  101. odxtools/statetransition.py +4 -9
  102. odxtools/staticfield.py +4 -8
  103. odxtools/table.py +7 -8
  104. odxtools/tablerow.py +7 -6
  105. odxtools/teammember.py +3 -5
  106. odxtools/templates/comparam-spec.odx-c.xml.jinja2 +2 -5
  107. odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +2 -5
  108. odxtools/templates/macros/printCompanyData.xml.jinja2 +2 -5
  109. odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
  110. odxtools/templates/macros/printCompuMethod.xml.jinja2 +153 -0
  111. odxtools/templates/macros/printDOP.xml.jinja2 +10 -132
  112. odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
  113. odxtools/templates/macros/printElementId.xml.jinja2 +3 -3
  114. odxtools/templates/macros/printMux.xml.jinja2 +3 -2
  115. odxtools/templates/macros/printTable.xml.jinja2 +2 -3
  116. odxtools/unit.py +3 -5
  117. odxtools/unitgroup.py +3 -5
  118. odxtools/unitspec.py +9 -10
  119. odxtools/utils.py +1 -26
  120. odxtools/version.py +2 -2
  121. odxtools/{write_pdx_file.py → writepdxfile.py} +19 -10
  122. odxtools/xdoc.py +3 -5
  123. {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/METADATA +1 -1
  124. odxtools-7.3.0.dist-info/RECORD +192 -0
  125. {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/WHEEL +1 -1
  126. odxtools/createcompanydatas.py +0 -17
  127. odxtools/createsdgs.py +0 -19
  128. odxtools/load_file.py +0 -13
  129. odxtools/load_odx_d_file.py +0 -6
  130. odxtools/load_pdx_file.py +0 -8
  131. odxtools-7.1.1.dist-info/RECORD +0 -186
  132. /odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +0 -0
  133. {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/LICENSE +0 -0
  134. {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/entry_points.txt +0 -0
  135. {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import warnings
3
3
  from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
4
+ from typing import Any, Dict, List, Optional
5
5
  from xml.etree import ElementTree
6
6
 
7
7
  from typing_extensions import override
@@ -11,14 +11,11 @@ from ..decodestate import DecodeState
11
11
  from ..diagcodedtype import DiagCodedType
12
12
  from ..encodestate import EncodeState
13
13
  from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
14
- from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
14
+ from ..odxlink import OdxDocFragment, OdxLinkId
15
15
  from ..odxtypes import AtomicOdxType, DataType, ParameterValue
16
16
  from ..utils import dataclass_fields_asdict
17
17
  from .parameter import Parameter, ParameterType
18
18
 
19
- if TYPE_CHECKING:
20
- from ..diaglayer import DiagLayer
21
-
22
19
 
23
20
  @dataclass
24
21
  class CodedConstParameter(Parameter):
@@ -54,15 +51,6 @@ class CodedConstParameter(Parameter):
54
51
 
55
52
  return result
56
53
 
57
- @override
58
- def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
59
- super()._resolve_odxlinks(odxlinks)
60
-
61
- @override
62
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
63
- param_list: List[Parameter]) -> None:
64
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
65
-
66
54
  @override
67
55
  def get_static_bit_length(self) -> Optional[int]:
68
56
  return self.diag_coded_type.get_static_bit_length()
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import final, override
@@ -8,15 +8,12 @@ from typing_extensions import final, override
8
8
  from ..decodestate import DecodeState
9
9
  from ..encodestate import EncodeState
10
10
  from ..exceptions import EncodeError, odxraise, odxrequire
11
- from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
11
+ from ..odxlink import OdxDocFragment, OdxLinkId
12
12
  from ..odxtypes import ParameterValue
13
13
  from ..utils import dataclass_fields_asdict
14
- from .parameter import Parameter, ParameterType
14
+ from .parameter import ParameterType
15
15
  from .parameterwithdop import ParameterWithDOP
16
16
 
17
- if TYPE_CHECKING:
18
- from ..diaglayer import DiagLayer
19
-
20
17
 
21
18
  @dataclass
22
19
  class LengthKeyParameter(ParameterWithDOP):
@@ -55,15 +52,6 @@ class LengthKeyParameter(ParameterWithDOP):
55
52
 
56
53
  return result
57
54
 
58
- @override
59
- def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
60
- super()._resolve_odxlinks(odxlinks)
61
-
62
- @override
63
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
64
- param_list: List[Parameter]) -> None:
65
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
66
-
67
55
  @property
68
56
  @override
69
57
  def is_required(self) -> bool:
@@ -107,7 +95,6 @@ class LengthKeyParameter(ParameterWithDOP):
107
95
 
108
96
  encode_state.length_keys[self.short_name] = physical_value
109
97
 
110
- orig_cursor = encode_state.cursor_byte_position
111
98
  pos = encode_state.cursor_byte_position
112
99
  if self.byte_position is not None:
113
100
  pos = encode_state.origin_byte_position + self.byte_position
@@ -120,7 +107,6 @@ class LengthKeyParameter(ParameterWithDOP):
120
107
  tmp_val = b'\x00' * ((n + 7) // 8)
121
108
  encode_state.emplace_bytes(tmp_val, obj_used_mask=tmp_val)
122
109
 
123
- encode_state.cursor_byte_position = max(encode_state.cursor_byte_position, orig_cursor)
124
110
  encode_state.cursor_bit_position = 0
125
111
 
126
112
  def encode_value_into_pdu(self, encode_state: EncodeState) -> None:
@@ -1,7 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
- import warnings
3
2
  from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
3
+ from typing import Any, Dict, List, Optional
5
4
  from xml.etree import ElementTree
6
5
 
7
6
  from typing_extensions import override
@@ -10,19 +9,17 @@ from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
10
9
  from ..decodestate import DecodeState
11
10
  from ..diagcodedtype import DiagCodedType
12
11
  from ..encodestate import EncodeState
13
- from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
14
- from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
12
+ from ..exceptions import DecodeMismatch, EncodeError, odxraise, odxrequire
13
+ from ..odxlink import OdxDocFragment, OdxLinkId
15
14
  from ..odxtypes import AtomicOdxType, DataType, ParameterValue
16
15
  from ..utils import dataclass_fields_asdict
17
16
  from .parameter import Parameter, ParameterType
18
17
 
19
- if TYPE_CHECKING:
20
- from ..diaglayer import DiagLayer
21
-
22
18
 
23
19
  @dataclass
24
20
  class NrcConstParameter(Parameter):
25
- """A param of type NRC-CONST defines a set of values to be matched for a negative response to apply.
21
+ """A parameter of type NRC-CONST defines a set of values to be
22
+ matched for a negative response object to apply
26
23
 
27
24
  The behaviour of NRC-CONST parameters is similar to CODED-CONST
28
25
  parameters in that they allow to specify which coding objects
@@ -70,15 +67,6 @@ class NrcConstParameter(Parameter):
70
67
 
71
68
  return result
72
69
 
73
- @override
74
- def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
75
- super()._resolve_odxlinks(odxlinks)
76
-
77
- @override
78
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
79
- param_list: List[Parameter]) -> None:
80
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
81
-
82
70
  @override
83
71
  def get_static_bit_length(self) -> Optional[int]:
84
72
  return self.diag_coded_type.get_static_bit_length()
@@ -100,49 +88,40 @@ class NrcConstParameter(Parameter):
100
88
  @override
101
89
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
102
90
  encode_state: EncodeState) -> None:
103
- coded_value: ParameterValue
91
+ # NRC-CONST parameters are not encoding any value on its
92
+ # own. instead, it is supposed to overlap with a value
93
+ # parameter.
104
94
  if physical_value is not None:
105
- if physical_value not in self.coded_values:
106
- odxraise(
107
- f"The value of parameter '{self.short_name}' must "
108
- f" be one of {self.coded_values} (is: {physical_value!r})", EncodeError)
109
- coded_value = self.coded_values[0]
110
- else:
111
- coded_value = physical_value
112
- else:
113
- # If the user did not select a value, the value of the
114
- # this parameter is set by another parameter which
115
- # overlaps with it. We thus just move the cursor.
116
- bit_pos = encode_state.cursor_bit_position
117
- bit_len = self.diag_coded_type.get_static_bit_length()
118
-
119
- if bit_len is None:
120
- odxraise("The diag coded type of NRC-CONST parameters must "
121
- "exhibit a static size")
122
- return
123
-
124
- encode_state.cursor_byte_position += (bit_pos + bit_len + 7) // 8
125
- encode_state.cursor_bit_position = 0
95
+ odxraise("The value of NRC-CONST parameters cannot be set directly!", EncodeError)
96
+
97
+ # TODO (?): extract the parameter and check if it is one of
98
+ # the values of self.coded_values. if not, throw an
99
+ # EncodeMismatch exception! This is probably a bad idea
100
+ # because the parameter which determines the value of the
101
+ # NRC-CONST might possibly be specified after the NRC-CONST.
102
+
103
+ # move the cursor forward by the size of the parameter
104
+ bit_pos = encode_state.cursor_bit_position
105
+ bit_len = self.diag_coded_type.get_static_bit_length()
106
+
107
+ if bit_len is None:
108
+ odxraise("The diag coded type of NRC-CONST parameters must "
109
+ "exhibit a static size")
126
110
  return
127
111
 
128
- self.diag_coded_type.encode_into_pdu(cast(AtomicOdxType, coded_value), encode_state)
112
+ encode_state.cursor_byte_position += (bit_pos + bit_len + 7) // 8
113
+ encode_state.cursor_bit_position = 0
114
+
115
+ encode_state.emplace_bytes(b'', self.short_name)
129
116
 
130
117
  @override
131
118
  def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
132
- # Extract coded values
119
+ # Extract coded value
133
120
  coded_value = self.diag_coded_type.decode_from_pdu(decode_state)
134
121
 
135
122
  # Check if the coded value in the message is correct.
136
123
  if coded_value not in self.coded_values:
137
- warnings.warn(
138
- f"Coded constant parameter does not match! "
139
- f"The parameter {self.short_name} expected a coded "
140
- f"value in {str(self.coded_values)} but got {str(coded_value)} "
141
- f"at byte position {decode_state.cursor_byte_position} "
142
- f"in coded message {decode_state.coded_message.hex()}.",
143
- DecodeError,
144
- stacklevel=1,
145
- )
124
+ raise DecodeMismatch(f"NRC-CONST parameter {self.short_name} does not apply")
146
125
 
147
126
  return coded_value
148
127
 
@@ -1,22 +1,19 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional
3
+ from typing import Any, Dict, List, Literal, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import final, override
7
7
 
8
- from ..createsdgs import create_sdgs_from_et
9
8
  from ..decodestate import DecodeState
10
9
  from ..element import NamedElement
11
10
  from ..encodestate import EncodeState
12
11
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
13
12
  from ..odxtypes import ParameterValue
13
+ from ..snrefcontext import SnRefContext
14
14
  from ..specialdatagroup import SpecialDataGroup
15
15
  from ..utils import dataclass_fields_asdict
16
16
 
17
- if TYPE_CHECKING:
18
- from ..diaglayer import DiagLayer
19
-
20
17
  ParameterType = Literal[
21
18
  "CODED-CONST",
22
19
  "DYNAMIC",
@@ -55,7 +52,9 @@ class Parameter(NamedElement):
55
52
  kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
56
53
 
57
54
  semantic = et_element.get("SEMANTIC")
58
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
55
+ sdgs = [
56
+ SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
57
+ ]
59
58
 
60
59
  byte_position_str = et_element.findtext("BYTE-POSITION")
61
60
  bit_position_str = et_element.findtext("BIT-POSITION")
@@ -82,15 +81,9 @@ class Parameter(NamedElement):
82
81
  for sdg in self.sdgs:
83
82
  sdg._resolve_odxlinks(odxlinks)
84
83
 
85
- @final
86
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
87
- raise RuntimeError("Calling _resolve_snrefs() is not allowed for parameters. "
88
- "Use _parameter_resolve_snrefs() instead.")
89
-
90
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
91
- param_list: List["Parameter"]) -> None:
84
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
92
85
  for sdg in self.sdgs:
93
- sdg._resolve_snrefs(diag_layer)
86
+ sdg._resolve_snrefs(context)
94
87
 
95
88
  @property
96
89
  def parameter_type(self) -> ParameterType:
@@ -126,14 +119,15 @@ class Parameter(NamedElement):
126
119
  @final
127
120
  def encode_into_pdu(self, physical_value: Optional[ParameterValue],
128
121
  encode_state: EncodeState) -> None:
129
- """Convert a physical value into its encoded form and place it into the PDU
122
+ """Convert a physical value into its encoded form and place it
123
+ into the PDU
124
+
125
+ Also, adapt the `encode_state` so that it points to where the
126
+ next parameter is located (if the next parameter does not
127
+ explicitly specify a position)
130
128
 
131
- Also, adapt the `encode_state` so that it points to where the next
132
- parameter is located (if the parameter does not explicitly specify a
133
- position)
134
129
  """
135
130
 
136
- orig_cursor = encode_state.cursor_byte_position
137
131
  if self.byte_position is not None:
138
132
  encode_state.cursor_byte_position = encode_state.origin_byte_position + self.byte_position
139
133
 
@@ -141,7 +135,6 @@ class Parameter(NamedElement):
141
135
 
142
136
  self._encode_positioned_into_pdu(physical_value, encode_state)
143
137
 
144
- encode_state.cursor_byte_position = max(encode_state.cursor_byte_position, orig_cursor)
145
138
  encode_state.cursor_bit_position = 0
146
139
 
147
140
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
@@ -155,7 +148,15 @@ class Parameter(NamedElement):
155
148
 
156
149
  @final
157
150
  def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
158
- orig_cursor = decode_state.cursor_byte_position
151
+ """Retrieve the raw data for the parameter from the PDU and
152
+ convert it to its physical interpretation
153
+
154
+ Also, adapt the `encode_state` so that it points to where the
155
+ next parameter is located (if the next parameter does not
156
+ explicitly specify a position)
157
+
158
+ """
159
+
159
160
  if self.byte_position is not None:
160
161
  decode_state.cursor_byte_position = decode_state.origin_byte_position + self.byte_position
161
162
 
@@ -163,7 +164,6 @@ class Parameter(NamedElement):
163
164
 
164
165
  result = self._decode_positioned_from_pdu(decode_state)
165
166
 
166
- decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
167
167
  decode_state.cursor_bit_position = 0
168
168
 
169
169
  return result
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
3
+ from typing import Any, Dict, List, Optional, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -14,12 +14,10 @@ from ..exceptions import odxassert, odxrequire
14
14
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
15
15
  from ..odxtypes import AtomicOdxType, ParameterValue
16
16
  from ..physicaltype import PhysicalType
17
+ from ..snrefcontext import SnRefContext
17
18
  from ..utils import dataclass_fields_asdict
18
19
  from .parameter import Parameter
19
20
 
20
- if TYPE_CHECKING:
21
- from ..diaglayer import DiagLayer
22
-
23
21
 
24
22
  @dataclass
25
23
  class ParameterWithDOP(Parameter):
@@ -58,12 +56,12 @@ class ParameterWithDOP(Parameter):
58
56
  self._dop = odxlinks.resolve(self.dop_ref)
59
57
 
60
58
  @override
61
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
62
- param_list: List[Parameter]) -> None:
63
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
59
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
60
+ super()._resolve_snrefs(context)
64
61
 
65
62
  if self.dop_snref:
66
- all_dops = diag_layer.diag_data_dictionary_spec.all_data_object_properties
63
+ all_dops = odxrequire(
64
+ context.diag_layer).diag_data_dictionary_spec.all_data_object_properties
67
65
  self._dop = resolve_snref(self.dop_snref, all_dops, DopBase)
68
66
 
69
67
  @property
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -11,13 +11,11 @@ from ..encodestate import EncodeState
11
11
  from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
12
12
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
13
13
  from ..odxtypes import ParameterValue
14
+ from ..snrefcontext import SnRefContext
14
15
  from ..utils import dataclass_fields_asdict
15
- from .parameter import Parameter, ParameterType
16
+ from .parameter import ParameterType
16
17
  from .parameterwithdop import ParameterWithDOP
17
18
 
18
- if TYPE_CHECKING:
19
- from ..diaglayer import DiagLayer
20
-
21
19
 
22
20
  @dataclass
23
21
  class PhysicalConstantParameter(ParameterWithDOP):
@@ -50,9 +48,8 @@ class PhysicalConstantParameter(ParameterWithDOP):
50
48
  super()._resolve_odxlinks(odxlinks)
51
49
 
52
50
  @override
53
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
54
- param_list: List[Parameter]) -> None:
55
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
51
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
52
+ super()._resolve_snrefs(context)
56
53
 
57
54
  dop = odxrequire(self.dop)
58
55
  if not isinstance(dop, DataObjectProperty):
@@ -51,9 +51,10 @@ class ReservedParameter(Parameter):
51
51
  @override
52
52
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
53
53
  encode_state: EncodeState) -> None:
54
- raw_data = (0).to_bytes((encode_state.cursor_bit_position + self.bit_length + 7) // 8,
55
- "big")
56
- encode_state.emplace_bytes(raw_data, self.short_name)
54
+ encode_state.cursor_byte_position += (encode_state.cursor_bit_position + self.bit_length +
55
+ 7) // 8
56
+ encode_state.cursor_bit_position = 0
57
+ encode_state.emplace_bytes(b'', self.short_name)
57
58
 
58
59
  @override
59
60
  def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
@@ -26,7 +26,7 @@ class SystemParameter(ParameterWithDOP):
26
26
 
27
27
  kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
28
28
 
29
- sysparam = odxrequire(et_element.findtext("SYSPARAM"))
29
+ sysparam = odxrequire(et_element.get("SYSPARAM"))
30
30
 
31
31
  return SystemParameter(sysparam=sysparam, **kwargs)
32
32
 
@@ -10,11 +10,11 @@ from ..encodestate import EncodeState
10
10
  from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
11
11
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
12
12
  from ..odxtypes import ParameterValue
13
+ from ..snrefcontext import SnRefContext
13
14
  from ..utils import dataclass_fields_asdict
14
15
  from .parameter import Parameter, ParameterType
15
16
 
16
17
  if TYPE_CHECKING:
17
- from ..diaglayer import DiagLayer
18
18
  from ..table import Table
19
19
  from ..tablerow import TableRow
20
20
 
@@ -56,8 +56,8 @@ class TableKeyParameter(Parameter):
56
56
  **kwargs)
57
57
 
58
58
  def __post_init__(self) -> None:
59
- self._table: "Table"
60
- self._table_row: Optional["TableRow"] = None
59
+ self._table: Table
60
+ self._table_row: Optional[TableRow] = None
61
61
  if self.table_ref is None and self.table_snref is None and \
62
62
  self.table_row_ref is None and self.table_row_snref is None:
63
63
  odxraise("Either a table or a table row must be defined.")
@@ -94,12 +94,11 @@ class TableKeyParameter(Parameter):
94
94
  self._table = self._table_row.table
95
95
 
96
96
  @override
97
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
98
- param_list: List[Parameter]) -> None:
99
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
97
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
98
+ super()._resolve_snrefs(context)
100
99
 
101
100
  if self.table_snref is not None:
102
- tables = diag_layer.diag_data_dictionary_spec.tables
101
+ tables = odxrequire(context.diag_layer).diag_data_dictionary_spec.tables
103
102
  self._table = resolve_snref(self.table_snref, tables, Table)
104
103
  if self.table_row_snref is not None:
105
104
  # make sure that we know the table to which the table row
@@ -165,7 +164,6 @@ class TableKeyParameter(Parameter):
165
164
 
166
165
  encode_state.table_keys[self.short_name] = physical_value
167
166
 
168
- orig_pos = encode_state.cursor_byte_position
169
167
  pos = encode_state.cursor_byte_position
170
168
  if self.byte_position is not None:
171
169
  pos = encode_state.origin_byte_position + self.byte_position
@@ -189,7 +187,6 @@ class TableKeyParameter(Parameter):
189
187
  tmp_val = b'\x00' * ((n + 7) // 8)
190
188
  encode_state.emplace_bytes(tmp_val, obj_used_mask=tmp_val)
191
189
 
192
- encode_state.cursor_byte_position = max(orig_pos, encode_state.cursor_byte_position)
193
190
  encode_state.cursor_bit_position = 0
194
191
 
195
192
  def encode_value_into_pdu(self, encode_state: EncodeState) -> None:
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
3
+ from typing import Any, Dict, List, Optional, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -10,13 +10,11 @@ from ..encodestate import EncodeState
10
10
  from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
11
11
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
12
12
  from ..odxtypes import ParameterValue
13
+ from ..snrefcontext import SnRefContext
13
14
  from ..utils import dataclass_fields_asdict
14
15
  from .parameter import Parameter, ParameterType
15
16
  from .tablekeyparameter import TableKeyParameter
16
17
 
17
- if TYPE_CHECKING:
18
- from ..diaglayer import DiagLayer
19
-
20
18
 
21
19
  @dataclass
22
20
  class TableStructParameter(Parameter):
@@ -60,12 +58,12 @@ class TableStructParameter(Parameter):
60
58
  self._table_key = odxlinks.resolve(self.table_key_ref, TableKeyParameter)
61
59
 
62
60
  @override
63
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
64
- param_list: List[Parameter]) -> None:
65
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
61
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
62
+ super()._resolve_snrefs(context)
66
63
 
67
64
  if self.table_key_snref is not None:
68
- self._table_key = resolve_snref(self.table_key_snref, param_list, TableKeyParameter)
65
+ self._table_key = resolve_snref(self.table_key_snref, odxrequire(context.parameters),
66
+ TableKeyParameter)
69
67
 
70
68
  @property
71
69
  def table_key(self) -> TableKeyParameter:
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -10,13 +10,11 @@ from ..encodestate import EncodeState
10
10
  from ..exceptions import EncodeError, odxraise, odxrequire
11
11
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
12
12
  from ..odxtypes import AtomicOdxType, ParameterValue
13
+ from ..snrefcontext import SnRefContext
13
14
  from ..utils import dataclass_fields_asdict
14
- from .parameter import Parameter, ParameterType
15
+ from .parameter import ParameterType
15
16
  from .parameterwithdop import ParameterWithDOP
16
17
 
17
- if TYPE_CHECKING:
18
- from ..diaglayer import DiagLayer
19
-
20
18
 
21
19
  @dataclass
22
20
  class ValueParameter(ParameterWithDOP):
@@ -50,9 +48,8 @@ class ValueParameter(ParameterWithDOP):
50
48
  super()._resolve_odxlinks(odxlinks)
51
49
 
52
50
  @override
53
- def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
54
- param_list: List[Parameter]) -> None:
55
- super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
51
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
52
+ super()._resolve_snrefs(context)
56
53
 
57
54
  if self.physical_default_value_raw is not None:
58
55
  dop = odxrequire(self.dop)
@@ -1,18 +1,20 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, cast
3
+ from typing import TYPE_CHECKING, Any, Dict, List, cast
4
+ from xml.etree import ElementTree
4
5
 
5
6
  from typing_extensions import override
6
7
 
7
8
  from .decodestate import DecodeState
8
9
  from .diagcodedtype import DctType, DiagCodedType
9
10
  from .encodestate import EncodeState
10
- from .exceptions import EncodeError, odxraise
11
- from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
11
+ from .exceptions import EncodeError, odxraise, odxrequire
12
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
12
13
  from .odxtypes import AtomicOdxType, DataType
14
+ from .snrefcontext import SnRefContext
15
+ from .utils import dataclass_fields_asdict
13
16
 
14
17
  if TYPE_CHECKING:
15
- from .diaglayer import DiagLayer
16
18
  from .parameters.lengthkeyparameter import LengthKeyParameter
17
19
 
18
20
 
@@ -21,6 +23,17 @@ class ParamLengthInfoType(DiagCodedType):
21
23
 
22
24
  length_key_ref: OdxLinkRef
23
25
 
26
+ @staticmethod
27
+ @override
28
+ def from_et(et_element: ElementTree.Element,
29
+ doc_frags: List[OdxDocFragment]) -> "ParamLengthInfoType":
30
+ kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, doc_frags))
31
+
32
+ length_key_ref = odxrequire(
33
+ OdxLinkRef.from_et(et_element.find("LENGTH-KEY-REF"), doc_frags))
34
+
35
+ return ParamLengthInfoType(length_key_ref=length_key_ref, **kwargs)
36
+
24
37
  @property
25
38
  def dct_type(self) -> DctType:
26
39
  return "PARAM-LENGTH-INFO-TYPE"
@@ -37,9 +50,9 @@ class ParamLengthInfoType(DiagCodedType):
37
50
  else:
38
51
  self._length_key = odxlinks.resolve(self.length_key_ref)
39
52
 
40
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
53
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
41
54
  """Recursively resolve any short-name references"""
42
- super()._resolve_snrefs(diag_layer)
55
+ super()._resolve_snrefs(context)
43
56
 
44
57
  @property
45
58
  def length_key(self) -> "LengthKeyParameter":
odxtools/parentref.py CHANGED
@@ -1,10 +1,13 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ from copy import deepcopy
2
3
  from dataclasses import dataclass
3
4
  from typing import TYPE_CHECKING, Any, Dict, List
4
5
  from xml.etree import ElementTree
5
6
 
6
7
  from .exceptions import odxrequire
7
8
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
9
+ from .snrefcontext import SnRefContext
10
+ from .utils import dataclass_fields_asdict
8
11
 
9
12
  if TYPE_CHECKING:
10
13
  from .diaglayer import DiagLayer
@@ -76,5 +79,16 @@ class ParentRef:
76
79
  else:
77
80
  self._layer = odxlinks.resolve(self.layer_ref)
78
81
 
79
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
82
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
80
83
  pass
84
+
85
+ def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
86
+ cls = self.__class__
87
+ result = cls.__new__(cls)
88
+ memo[id(self)] = result
89
+
90
+ fields = dataclass_fields_asdict(self)
91
+ for name, value in fields.items():
92
+ setattr(result, name, deepcopy(value))
93
+
94
+ return result
@@ -1,15 +1,13 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
7
7
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
8
+ from .snrefcontext import SnRefContext
8
9
  from .utils import dataclass_fields_asdict
9
10
 
10
- if TYPE_CHECKING:
11
- from .diaglayer import DiagLayer
12
-
13
11
 
14
12
  @dataclass
15
13
  class PhysicalDimension(IdentifiableElement):
@@ -89,5 +87,5 @@ class PhysicalDimension(IdentifiableElement):
89
87
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
90
88
  pass
91
89
 
92
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
90
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
93
91
  pass