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.
Files changed (203) hide show
  1. odxtools/additionalaudience.py +3 -3
  2. odxtools/addressing.py +8 -0
  3. odxtools/admindata.py +8 -8
  4. odxtools/audience.py +10 -10
  5. odxtools/basecomparam.py +7 -20
  6. odxtools/basevariantpattern.py +4 -5
  7. odxtools/basicstructure.py +12 -11
  8. odxtools/cli/_print_utils.py +35 -23
  9. odxtools/cli/browse.py +9 -9
  10. odxtools/cli/compare.py +24 -24
  11. odxtools/cli/decode.py +3 -4
  12. odxtools/cli/find.py +4 -5
  13. odxtools/cli/list.py +7 -7
  14. odxtools/cli/main.py +2 -2
  15. odxtools/cli/snoop.py +3 -3
  16. odxtools/codec.py +3 -186
  17. odxtools/commrelation.py +12 -19
  18. odxtools/commrelationvaluetype.py +9 -0
  19. odxtools/companydata.py +5 -5
  20. odxtools/companydocinfo.py +8 -8
  21. odxtools/companyrevisioninfo.py +5 -5
  22. odxtools/companyspecificinfo.py +5 -5
  23. odxtools/comparam.py +3 -3
  24. odxtools/comparaminstance.py +10 -10
  25. odxtools/comparamspec.py +3 -3
  26. odxtools/comparamsubset.py +5 -5
  27. odxtools/complexcomparam.py +7 -7
  28. odxtools/compositecodec.py +191 -0
  29. odxtools/compumethods/compucategory.py +13 -0
  30. odxtools/compumethods/compucodecompumethod.py +6 -5
  31. odxtools/compumethods/compuconst.py +4 -5
  32. odxtools/compumethods/compudefaultvalue.py +1 -2
  33. odxtools/compumethods/compuinternaltophys.py +6 -6
  34. odxtools/compumethods/compumethod.py +6 -17
  35. odxtools/compumethods/compuphystointernal.py +6 -6
  36. odxtools/compumethods/compurationalcoeffs.py +4 -4
  37. odxtools/compumethods/compuscale.py +9 -10
  38. odxtools/compumethods/createanycompumethod.py +1 -2
  39. odxtools/compumethods/identicalcompumethod.py +1 -2
  40. odxtools/compumethods/intervaltype.py +8 -0
  41. odxtools/compumethods/limit.py +13 -19
  42. odxtools/compumethods/linearcompumethod.py +4 -3
  43. odxtools/compumethods/linearsegment.py +14 -15
  44. odxtools/compumethods/ratfunccompumethod.py +5 -4
  45. odxtools/compumethods/ratfuncsegment.py +7 -8
  46. odxtools/compumethods/scalelinearcompumethod.py +10 -9
  47. odxtools/compumethods/scaleratfunccompumethod.py +6 -5
  48. odxtools/compumethods/tabintpcompumethod.py +19 -20
  49. odxtools/compumethods/texttablecompumethod.py +5 -4
  50. odxtools/createanycomparam.py +2 -4
  51. odxtools/createanydiagcodedtype.py +1 -2
  52. odxtools/database.py +9 -8
  53. odxtools/dataobjectproperty.py +10 -10
  54. odxtools/decodestate.py +5 -5
  55. odxtools/description.py +6 -22
  56. odxtools/determinenumberofitems.py +4 -4
  57. odxtools/diagclasstype.py +11 -0
  58. odxtools/diagcodedtype.py +7 -7
  59. odxtools/diagcomm.py +19 -42
  60. odxtools/diagdatadictionaryspec.py +6 -6
  61. odxtools/diaglayercontainer.py +4 -4
  62. odxtools/diaglayers/basevariant.py +10 -9
  63. odxtools/diaglayers/basevariantraw.py +9 -9
  64. odxtools/diaglayers/diaglayer.py +20 -19
  65. odxtools/diaglayers/diaglayerraw.py +10 -10
  66. odxtools/diaglayers/diaglayertype.py +1 -2
  67. odxtools/diaglayers/ecushareddata.py +4 -4
  68. odxtools/diaglayers/ecushareddataraw.py +6 -6
  69. odxtools/diaglayers/ecuvariant.py +11 -10
  70. odxtools/diaglayers/ecuvariantraw.py +9 -9
  71. odxtools/diaglayers/functionalgroup.py +8 -7
  72. odxtools/diaglayers/functionalgroupraw.py +7 -7
  73. odxtools/diaglayers/hierarchyelement.py +43 -49
  74. odxtools/diaglayers/hierarchyelementraw.py +4 -4
  75. odxtools/diaglayers/protocol.py +4 -4
  76. odxtools/diaglayers/protocolraw.py +6 -6
  77. odxtools/diagnostictroublecode.py +8 -8
  78. odxtools/diagservice.py +21 -97
  79. odxtools/diagvariable.py +14 -14
  80. odxtools/docrevision.py +11 -11
  81. odxtools/dopbase.py +6 -6
  82. odxtools/dtcconnector.py +45 -0
  83. odxtools/dtcdop.py +15 -56
  84. odxtools/dynamicendmarkerfield.py +5 -4
  85. odxtools/dynamiclengthfield.py +5 -4
  86. odxtools/dyndefinedspec.py +7 -159
  87. odxtools/dynenddopref.py +5 -5
  88. odxtools/dyniddefmodeinfo.py +161 -0
  89. odxtools/ecuvariantpattern.py +4 -5
  90. odxtools/element.py +5 -6
  91. odxtools/encodestate.py +11 -11
  92. odxtools/encoding.py +2 -3
  93. odxtools/endofpdufield.py +6 -6
  94. odxtools/envdataconnector.py +49 -0
  95. odxtools/environmentdata.py +3 -4
  96. odxtools/environmentdatadescription.py +11 -11
  97. odxtools/exceptions.py +5 -5
  98. odxtools/externalaccessmethod.py +22 -0
  99. odxtools/externaldoc.py +23 -0
  100. odxtools/field.py +9 -10
  101. odxtools/functionalclass.py +4 -4
  102. odxtools/inputparam.py +6 -6
  103. odxtools/internalconstr.py +4 -5
  104. odxtools/isotp_state_machine.py +12 -11
  105. odxtools/leadinglengthinfotype.py +2 -3
  106. odxtools/library.py +5 -5
  107. odxtools/linkeddtcdop.py +62 -0
  108. odxtools/loadfile.py +5 -6
  109. odxtools/matchingbasevariantparameter.py +2 -3
  110. odxtools/matchingparameter.py +7 -7
  111. odxtools/minmaxlengthtype.py +5 -11
  112. odxtools/modification.py +4 -4
  113. odxtools/multiplexer.py +11 -11
  114. odxtools/multiplexercase.py +6 -6
  115. odxtools/multiplexerdefaultcase.py +6 -6
  116. odxtools/multiplexerswitchkey.py +4 -4
  117. odxtools/nameditemlist.py +14 -14
  118. odxtools/negoutputparam.py +3 -3
  119. odxtools/obd.py +1 -2
  120. odxtools/odxcategory.py +6 -6
  121. odxtools/odxlink.py +19 -20
  122. odxtools/odxtypes.py +21 -18
  123. odxtools/outputparam.py +4 -4
  124. odxtools/parameterinfo.py +2 -2
  125. odxtools/parameters/codedconstparameter.py +5 -5
  126. odxtools/parameters/createanyparameter.py +1 -2
  127. odxtools/parameters/dynamicparameter.py +2 -3
  128. odxtools/parameters/lengthkeyparameter.py +5 -5
  129. odxtools/parameters/matchingrequestparameter.py +3 -4
  130. odxtools/parameters/nrcconstparameter.py +7 -7
  131. odxtools/parameters/parameter.py +11 -11
  132. odxtools/parameters/parameterwithdop.py +9 -9
  133. odxtools/parameters/physicalconstantparameter.py +4 -4
  134. odxtools/parameters/reservedparameter.py +3 -4
  135. odxtools/parameters/rowfragment.py +7 -0
  136. odxtools/parameters/systemparameter.py +2 -3
  137. odxtools/parameters/tableentryparameter.py +4 -9
  138. odxtools/parameters/tablekeyparameter.py +10 -10
  139. odxtools/parameters/tablestructparameter.py +7 -7
  140. odxtools/parameters/valueparameter.py +7 -7
  141. odxtools/paramlengthinfotype.py +5 -3
  142. odxtools/parentref.py +9 -9
  143. odxtools/physicaldimension.py +11 -11
  144. odxtools/physicaltype.py +4 -12
  145. odxtools/posresponsesuppressible.py +72 -0
  146. odxtools/preconditionstateref.py +7 -7
  147. odxtools/progcode.py +6 -6
  148. odxtools/protstack.py +4 -4
  149. odxtools/radix.py +9 -0
  150. odxtools/relateddiagcommref.py +22 -0
  151. odxtools/relateddoc.py +6 -6
  152. odxtools/request.py +14 -12
  153. odxtools/response.py +15 -13
  154. odxtools/scaleconstr.py +4 -12
  155. odxtools/servicebinner.py +5 -5
  156. odxtools/singleecujob.py +4 -4
  157. odxtools/snrefcontext.py +2 -2
  158. odxtools/specialdata.py +5 -5
  159. odxtools/specialdatagroup.py +9 -9
  160. odxtools/specialdatagroupcaption.py +3 -3
  161. odxtools/standardizationlevel.py +9 -0
  162. odxtools/standardlengthtype.py +12 -21
  163. odxtools/state.py +3 -3
  164. odxtools/statechart.py +4 -4
  165. odxtools/statemachine.py +4 -3
  166. odxtools/statetransition.py +5 -18
  167. odxtools/statetransitionref.py +18 -18
  168. odxtools/staticfield.py +5 -4
  169. odxtools/structure.py +2 -3
  170. odxtools/subcomponent.py +12 -245
  171. odxtools/subcomponentparamconnector.py +103 -0
  172. odxtools/subcomponentpattern.py +42 -0
  173. odxtools/swvariable.py +3 -4
  174. odxtools/table.py +17 -55
  175. odxtools/tablediagcommconnector.py +47 -0
  176. odxtools/tablerow.py +30 -30
  177. odxtools/tablerowconnector.py +46 -0
  178. odxtools/teammember.py +11 -11
  179. odxtools/templates/macros/printService.xml.jinja2 +2 -1
  180. odxtools/termination.py +8 -0
  181. odxtools/text.py +2 -3
  182. odxtools/transmode.py +9 -0
  183. odxtools/uds.py +2 -3
  184. odxtools/unit.py +9 -9
  185. odxtools/unitgroup.py +6 -11
  186. odxtools/unitgroupcategory.py +7 -0
  187. odxtools/unitspec.py +6 -6
  188. odxtools/usage.py +9 -0
  189. odxtools/utils.py +31 -2
  190. odxtools/validtype.py +9 -0
  191. odxtools/variablegroup.py +2 -2
  192. odxtools/variantmatcher.py +10 -10
  193. odxtools/variantpattern.py +3 -3
  194. odxtools/version.py +2 -2
  195. odxtools/writepdxfile.py +5 -5
  196. odxtools/xdoc.py +9 -9
  197. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/METADATA +4 -5
  198. odxtools-10.0.0.dist-info/RECORD +264 -0
  199. odxtools-9.6.1.dist-info/RECORD +0 -238
  200. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/WHEEL +0 -0
  201. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/entry_points.txt +0 -0
  202. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/licenses/LICENSE +0 -0
  203. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
@@ -14,12 +14,12 @@ class SpecialDataGroupCaption(IdentifiableElement):
14
14
 
15
15
  @staticmethod
16
16
  def from_et(et_element: ElementTree.Element,
17
- doc_frags: List[OdxDocFragment]) -> "SpecialDataGroupCaption":
17
+ doc_frags: list[OdxDocFragment]) -> "SpecialDataGroupCaption":
18
18
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
19
19
 
20
20
  return SpecialDataGroupCaption(**kwargs)
21
21
 
22
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
22
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
23
23
  result = {self.odx_id: self}
24
24
 
25
25
  result[self.odx_id] = self
@@ -0,0 +1,9 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from enum import Enum
3
+
4
+
5
+ class StandardizationLevel(Enum):
6
+ STANDARD = "STANDARD"
7
+ OEM_SPECIFIC = "OEM-SPECIFIC"
8
+ OPTIONAL = "OPTIONAL"
9
+ OEM_OPTIONAL = "OEM-OPTIONAL"
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Literal, Optional
3
+ from typing import Literal
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -11,15 +11,15 @@ from .encodestate import EncodeState
11
11
  from .exceptions import odxassert, odxraise, odxrequire
12
12
  from .odxlink import OdxDocFragment
13
13
  from .odxtypes import AtomicOdxType, BytesTypes, DataType, odxstr_to_bool
14
- from .utils import dataclass_fields_asdict
14
+ from .utils import dataclass_fields_asdict, read_hex_binary
15
15
 
16
16
 
17
- @dataclass
17
+ @dataclass(kw_only=True)
18
18
  class StandardLengthType(DiagCodedType):
19
19
 
20
20
  bit_length: int
21
- bit_mask: Optional[int]
22
- is_condensed_raw: Optional[bool]
21
+ bit_mask: int | None = None
22
+ is_condensed_raw: bool | None = None
23
23
 
24
24
  @property
25
25
  def dct_type(self) -> DctType:
@@ -32,20 +32,11 @@ class StandardLengthType(DiagCodedType):
32
32
  @staticmethod
33
33
  @override
34
34
  def from_et(et_element: ElementTree.Element,
35
- doc_frags: List[OdxDocFragment]) -> "StandardLengthType":
35
+ doc_frags: list[OdxDocFragment]) -> "StandardLengthType":
36
36
  kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, doc_frags))
37
37
 
38
38
  bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
39
- bit_mask = None
40
- if (bit_mask_str := et_element.findtext("BIT-MASK")) is not None:
41
- # The XSD uses the type xsd:hexBinary
42
- # xsd:hexBinary allows for leading/trailing whitespace, empty strings, and it only allows an even
43
- # number of hex digits, while some of the examples shown in the ODX specification exhibit an
44
- # odd number of hex digits.
45
- # This causes a validation paradox, so we try to be flexible
46
- bit_mask_str = bit_mask_str.strip()
47
- if len(bit_mask_str):
48
- bit_mask = int(bit_mask_str, 16)
39
+ bit_mask = read_hex_binary(et_element.find("BIT-MASK"))
49
40
  is_condensed_raw = odxstr_to_bool(et_element.get("IS-CONDENSED"))
50
41
 
51
42
  return StandardLengthType(
@@ -59,7 +50,7 @@ class StandardLengthType(DiagCodedType):
59
50
  'Can not apply a bit_mask on a value of type {self.base_data_type}',
60
51
  )
61
52
 
62
- def __get_used_mask(self, internal_value: AtomicOdxType) -> Optional[bytes]:
53
+ def __get_used_mask(self, internal_value: AtomicOdxType) -> bytes | None:
63
54
  """Returns a byte field where all bits that are used by the
64
55
  DiagCoded type are set and all unused ones are not set.
65
56
 
@@ -127,7 +118,7 @@ class StandardLengthType(DiagCodedType):
127
118
  mask_bit += 1
128
119
 
129
120
  if isinstance(internal_value, BytesTypes):
130
- return result.to_bytes(len(internal_value), 'big')
121
+ return result.to_bytes(len(bytes(internal_value)), 'big')
131
122
 
132
123
  return result
133
124
 
@@ -165,7 +156,7 @@ class StandardLengthType(DiagCodedType):
165
156
  mask_bit += 1
166
157
 
167
158
  if isinstance(raw_value, BytesTypes):
168
- return result.to_bytes(len(raw_value), 'big')
159
+ return result.to_bytes(len(bytes(raw_value)), 'big')
169
160
 
170
161
  return result
171
162
  if isinstance(raw_value, int):
@@ -173,12 +164,12 @@ class StandardLengthType(DiagCodedType):
173
164
  if isinstance(raw_value, BytesTypes):
174
165
  int_value = int.from_bytes(raw_value, 'big')
175
166
  int_value &= self.bit_mask
176
- return int_value.to_bytes(len(raw_value), 'big')
167
+ return int_value.to_bytes(len(bytes(raw_value)), 'big')
177
168
 
178
169
  odxraise(f'Can not apply a bit_mask on a value of type {type(raw_value)}')
179
170
  return raw_value
180
171
 
181
- def get_static_bit_length(self) -> Optional[int]:
172
+ def get_static_bit_length(self) -> int | None:
182
173
  if self.bit_mask is not None and self.is_condensed:
183
174
  # TODO: this is pretty slow. replace it by
184
175
  # `self.bit_mask.bit_count()` once we require python >=
odxtools/state.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
@@ -16,12 +16,12 @@ class State(IdentifiableElement):
16
16
  """
17
17
 
18
18
  @staticmethod
19
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "State":
19
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "State":
20
20
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
21
21
 
22
22
  return State(**kwargs)
23
23
 
24
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
24
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
25
25
  return {self.odx_id: self}
26
26
 
27
27
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/statechart.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
@@ -19,7 +19,7 @@ class StateChart(IdentifiableElement):
19
19
  Corresponds to STATE-CHART.
20
20
  """
21
21
  semantic: str
22
- state_transitions: List[StateTransition]
22
+ state_transitions: list[StateTransition]
23
23
  start_state_snref: str
24
24
  states: NamedItemList[State]
25
25
 
@@ -28,7 +28,7 @@ class StateChart(IdentifiableElement):
28
28
  return self._start_state
29
29
 
30
30
  @staticmethod
31
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "StateChart":
31
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "StateChart":
32
32
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
33
33
 
34
34
  semantic: str = odxrequire(et_element.findtext("SEMANTIC"))
@@ -52,7 +52,7 @@ class StateChart(IdentifiableElement):
52
52
  states=NamedItemList(states),
53
53
  **kwargs)
54
54
 
55
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
55
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
56
56
  odxlinks = {self.odx_id: self}
57
57
 
58
58
  for strans in self.state_transitions:
odxtools/statemachine.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ from collections.abc import Generator
2
3
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Generator, Union
4
+ from typing import TYPE_CHECKING, Any
4
5
 
5
6
  from .exceptions import odxraise
6
7
  from .odxtypes import ParameterValueDict
@@ -97,7 +98,7 @@ class StateMachine:
97
98
  self._active_state = state_chart.start_state
98
99
 
99
100
  def execute(self, service: "DiagService", **service_params: Any
100
- ) -> Generator[bytes, Union[bytes, bytearray, ParameterValueDict], None]:
101
+ ) -> Generator[bytes, bytes | bytearray | ParameterValueDict, None]:
101
102
  """Run a diagnostic service and update the state machine
102
103
  depending on the outcome.
103
104
 
@@ -159,7 +160,7 @@ class StateMachine:
159
160
 
160
161
  if raw_resp is None:
161
162
  raise RuntimeError("The calling code must send back a reply")
162
- elif isinstance(raw_resp, (bytes, bytearray)):
163
+ elif isinstance(raw_resp, bytes | bytearray):
163
164
  for decoded_resp_msg in self.diag_layer.decode_response(raw_resp, raw_req):
164
165
  for stransref in service.state_transition_refs:
165
166
  # we only execute the first applicable state
@@ -1,30 +1,17 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
7
7
  from .exceptions import odxrequire
8
+ from .externalaccessmethod import ExternalAccessMethod
8
9
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, resolve_snref
9
10
  from .snrefcontext import SnRefContext
10
11
  from .state import State
11
12
  from .utils import dataclass_fields_asdict
12
13
 
13
14
 
14
- @dataclass
15
- class ExternalAccessMethod(IdentifiableElement):
16
- method: str
17
-
18
- @staticmethod
19
- def from_et(et_element: ElementTree.Element,
20
- doc_frags: List[OdxDocFragment]) -> "ExternalAccessMethod":
21
- kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
22
-
23
- method = odxrequire(et_element.findtext("METHOD"))
24
-
25
- return ExternalAccessMethod(method=method, **kwargs)
26
-
27
-
28
15
  @dataclass
29
16
  class StateTransition(IdentifiableElement):
30
17
  """
@@ -32,7 +19,7 @@ class StateTransition(IdentifiableElement):
32
19
  """
33
20
  source_snref: str
34
21
  target_snref: str
35
- external_access_method: Optional[ExternalAccessMethod]
22
+ external_access_method: ExternalAccessMethod | None
36
23
 
37
24
  @property
38
25
  def source_state(self) -> State:
@@ -44,7 +31,7 @@ class StateTransition(IdentifiableElement):
44
31
 
45
32
  @staticmethod
46
33
  def from_et(et_element: ElementTree.Element,
47
- doc_frags: List[OdxDocFragment]) -> "StateTransition":
34
+ doc_frags: list[OdxDocFragment]) -> "StateTransition":
48
35
 
49
36
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
50
37
 
@@ -63,7 +50,7 @@ class StateTransition(IdentifiableElement):
63
50
  external_access_method=external_access_method,
64
51
  **kwargs)
65
52
 
66
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
53
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
67
54
  return {self.odx_id: self}
68
55
 
69
56
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> 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, Tuple, Union
3
+ from typing import TYPE_CHECKING, Any, Union
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .basicstructure import BasicStructure
@@ -27,11 +27,11 @@ if TYPE_CHECKING:
27
27
 
28
28
 
29
29
  def _resolve_in_param(
30
- in_param_if_snref: Optional[str],
31
- in_param_if_snpathref: Optional[str],
32
- params: List[Parameter],
30
+ in_param_if_snref: str | None,
31
+ in_param_if_snpathref: str | None,
32
+ params: list[Parameter],
33
33
  param_dict: ParameterValueDict,
34
- ) -> Tuple[Optional[Parameter], Optional[ParameterValue]]:
34
+ ) -> tuple[Parameter | None, ParameterValue | None]:
35
35
 
36
36
  if in_param_if_snref is not None:
37
37
  path_chunks = [in_param_if_snref]
@@ -44,10 +44,10 @@ def _resolve_in_param(
44
44
 
45
45
 
46
46
  def _resolve_in_param_helper(
47
- params: List[Parameter],
47
+ params: list[Parameter],
48
48
  param_dict: ParameterValueDict,
49
- path_chunks: List[str],
50
- ) -> Tuple[Optional[Parameter], Optional[ParameterValue]]:
49
+ path_chunks: list[str],
50
+ ) -> tuple[Parameter | None, ParameterValue | None]:
51
51
 
52
52
  inner_param = resolve_snref(path_chunks[0], params, Parameter, lenient=True)
53
53
  if inner_param is None:
@@ -90,7 +90,7 @@ def _resolve_in_param_helper(
90
90
 
91
91
  def _check_applies(ref: Union["StateTransitionRef",
92
92
  "PreConditionStateRef"], state_machine: "StateMachine",
93
- params: List[Parameter], param_value_dict: ParameterValueDict) -> bool:
93
+ params: list[Parameter], param_value_dict: ParameterValueDict) -> bool:
94
94
  if state_machine.active_state != ref.state:
95
95
  # if the active state of the state machine is not the
96
96
  # specified one, the precondition does not apply
@@ -108,13 +108,13 @@ def _check_applies(ref: Union["StateTransitionRef",
108
108
  return False
109
109
  elif not isinstance(
110
110
  param,
111
- (CodedConstParameter, PhysicalConstantParameter, TableKeyParameter, ValueParameter)):
111
+ CodedConstParameter | PhysicalConstantParameter | TableKeyParameter | ValueParameter):
112
112
  # see checker rule 194 in section B.2 of the spec
113
113
  odxraise(f"Parameter referenced by state transition ref is of "
114
114
  f"invalid type {type(param).__name__}")
115
115
  return False
116
- elif isinstance(param, (CodedConstParameter, PhysicalConstantParameter,
117
- TableKeyParameter)) and ref.value is not None:
116
+ elif isinstance(param, CodedConstParameter | PhysicalConstantParameter
117
+ | TableKeyParameter) and ref.value is not None:
118
118
  # see checker rule 193 in section B.2 of the spec. Why can
119
119
  # no values for constant parameters be specified? (This
120
120
  # seems to be rather inconvenient...)
@@ -155,10 +155,10 @@ class StateTransitionRef(OdxLinkRef):
155
155
  may also be conditional on the observed response of the ECU.
156
156
 
157
157
  """
158
- value: Optional[str]
158
+ value: str | None
159
159
 
160
- in_param_if_snref: Optional[str]
161
- in_param_if_snpathref: Optional[str]
160
+ in_param_if_snref: str | None
161
+ in_param_if_snpathref: str | None
162
162
 
163
163
  @property
164
164
  def state_transition(self) -> StateTransition:
@@ -171,7 +171,7 @@ class StateTransitionRef(OdxLinkRef):
171
171
  @staticmethod
172
172
  def from_et( # type: ignore[override]
173
173
  et_element: ElementTree.Element,
174
- doc_frags: List[OdxDocFragment]) -> "StateTransitionRef":
174
+ doc_frags: list[OdxDocFragment]) -> "StateTransitionRef":
175
175
  kwargs = dataclass_fields_asdict(OdxLinkRef.from_et(et_element, doc_frags))
176
176
 
177
177
  value = et_element.findtext("VALUE")
@@ -195,7 +195,7 @@ class StateTransitionRef(OdxLinkRef):
195
195
  odxassert(self.in_param_if_snref is not None or self.in_param_if_snref is not None,
196
196
  "If VALUE is specified, a parameter must be referenced")
197
197
 
198
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
198
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
199
199
  return {}
200
200
 
201
201
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
@@ -204,7 +204,7 @@ class StateTransitionRef(OdxLinkRef):
204
204
  def _resolve_snrefs(self, context: SnRefContext) -> None:
205
205
  pass
206
206
 
207
- def execute(self, state_machine: StateMachine, params: List[Parameter],
207
+ def execute(self, state_machine: StateMachine, params: list[Parameter],
208
208
  param_value_dict: ParameterValueDict) -> bool:
209
209
  """Update a StateMachine object if the state transition ought
210
210
  to be executed based on the response received after executing a
odxtools/staticfield.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ from collections.abc import Sequence
2
3
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Sequence
4
+ from typing import Any
4
5
  from xml.etree import ElementTree
5
6
 
6
7
  from typing_extensions import override
@@ -23,7 +24,7 @@ class StaticField(Field):
23
24
 
24
25
  @staticmethod
25
26
  @override
26
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "StaticField":
27
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "StaticField":
27
28
  kwargs = dataclass_fields_asdict(Field.from_et(et_element, doc_frags))
28
29
 
29
30
  fixed_number_of_items = int(odxrequire(et_element.findtext('FIXED-NUMBER-OF-ITEMS')))
@@ -33,7 +34,7 @@ class StaticField(Field):
33
34
  fixed_number_of_items=fixed_number_of_items, item_byte_size=item_byte_size, **kwargs)
34
35
 
35
36
  @override
36
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
37
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
37
38
  odxlinks = super()._build_odxlinks()
38
39
  return odxlinks
39
40
 
@@ -89,7 +90,7 @@ class StaticField(Field):
89
90
  orig_origin = decode_state.origin_byte_position
90
91
  decode_state.origin_byte_position = decode_state.cursor_byte_position
91
92
 
92
- result: List[ParameterValue] = []
93
+ result: list[ParameterValue] = []
93
94
  for _ in range(self.fixed_number_of_items):
94
95
  orig_cursor = decode_state.cursor_byte_position
95
96
 
odxtools/structure.py CHANGED
@@ -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 .basicstructure import BasicStructure
@@ -11,14 +10,14 @@ from .utils import dataclass_fields_asdict
11
10
 
12
11
  @dataclass
13
12
  class Structure(BasicStructure):
14
- is_visible_raw: Optional[bool]
13
+ is_visible_raw: bool | None
15
14
 
16
15
  @property
17
16
  def is_visible(self) -> bool:
18
17
  return self.is_visible_raw in (True, None)
19
18
 
20
19
  @staticmethod
21
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Structure":
20
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "Structure":
22
21
  """Read a STRUCTURE element from XML."""
23
22
  kwargs = dataclass_fields_asdict(BasicStructure.from_et(et_element, doc_frags))
24
23