odxtools 9.7.0__py3-none-any.whl → 10.1.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 (193) hide show
  1. odxtools/additionalaudience.py +7 -7
  2. odxtools/admindata.py +14 -13
  3. odxtools/audience.py +17 -17
  4. odxtools/basecomparam.py +9 -8
  5. odxtools/basevariantpattern.py +9 -10
  6. odxtools/basicstructure.py +15 -15
  7. odxtools/cli/_print_utils.py +34 -22
  8. odxtools/cli/browse.py +8 -8
  9. odxtools/cli/compare.py +24 -24
  10. odxtools/cli/decode.py +3 -4
  11. odxtools/cli/find.py +4 -5
  12. odxtools/cli/list.py +6 -6
  13. odxtools/cli/main.py +2 -2
  14. odxtools/cli/snoop.py +3 -3
  15. odxtools/codec.py +3 -3
  16. odxtools/commrelation.py +18 -17
  17. odxtools/companydata.py +13 -13
  18. odxtools/companydocinfo.py +15 -17
  19. odxtools/companyrevisioninfo.py +9 -9
  20. odxtools/companyspecificinfo.py +11 -13
  21. odxtools/comparam.py +8 -7
  22. odxtools/comparaminstance.py +14 -14
  23. odxtools/comparamspec.py +10 -11
  24. odxtools/comparamsubset.py +17 -25
  25. odxtools/complexcomparam.py +14 -14
  26. odxtools/complexdop.py +1 -1
  27. odxtools/compositecodec.py +8 -8
  28. odxtools/compumethods/compucodecompumethod.py +7 -7
  29. odxtools/compumethods/compuconst.py +5 -6
  30. odxtools/compumethods/compudefaultvalue.py +2 -3
  31. odxtools/compumethods/compuinternaltophys.py +13 -12
  32. odxtools/compumethods/compumethod.py +10 -9
  33. odxtools/compumethods/compuphystointernal.py +13 -12
  34. odxtools/compumethods/compurationalcoeffs.py +7 -7
  35. odxtools/compumethods/compuscale.py +15 -16
  36. odxtools/compumethods/createanycompumethod.py +12 -13
  37. odxtools/compumethods/identicalcompumethod.py +4 -5
  38. odxtools/compumethods/limit.py +14 -14
  39. odxtools/compumethods/linearcompumethod.py +5 -5
  40. odxtools/compumethods/linearsegment.py +10 -11
  41. odxtools/compumethods/ratfunccompumethod.py +6 -6
  42. odxtools/compumethods/ratfuncsegment.py +7 -8
  43. odxtools/compumethods/scalelinearcompumethod.py +9 -9
  44. odxtools/compumethods/scaleratfunccompumethod.py +7 -7
  45. odxtools/compumethods/tabintpcompumethod.py +10 -13
  46. odxtools/compumethods/texttablecompumethod.py +6 -6
  47. odxtools/createanycomparam.py +5 -7
  48. odxtools/createanydiagcodedtype.py +7 -8
  49. odxtools/database.py +34 -31
  50. odxtools/dataobjectproperty.py +19 -20
  51. odxtools/decodestate.py +5 -5
  52. odxtools/description.py +9 -9
  53. odxtools/determinenumberofitems.py +8 -7
  54. odxtools/diagcodedtype.py +10 -10
  55. odxtools/diagcomm.py +29 -30
  56. odxtools/diagdatadictionaryspec.py +36 -36
  57. odxtools/diaglayercontainer.py +35 -34
  58. odxtools/diaglayers/basevariant.py +14 -12
  59. odxtools/diaglayers/basevariantraw.py +22 -23
  60. odxtools/diaglayers/diaglayer.py +24 -22
  61. odxtools/diaglayers/diaglayerraw.py +43 -52
  62. odxtools/diaglayers/diaglayertype.py +1 -2
  63. odxtools/diaglayers/ecushareddata.py +9 -9
  64. odxtools/diaglayers/ecushareddataraw.py +15 -16
  65. odxtools/diaglayers/ecuvariant.py +15 -13
  66. odxtools/diaglayers/ecuvariantraw.py +21 -22
  67. odxtools/diaglayers/functionalgroup.py +12 -11
  68. odxtools/diaglayers/functionalgroupraw.py +17 -18
  69. odxtools/diaglayers/hierarchyelement.py +48 -54
  70. odxtools/diaglayers/hierarchyelementraw.py +10 -11
  71. odxtools/diaglayers/protocol.py +7 -7
  72. odxtools/diaglayers/protocolraw.py +13 -14
  73. odxtools/diagnostictroublecode.py +15 -17
  74. odxtools/diagservice.py +28 -27
  75. odxtools/diagvariable.py +24 -25
  76. odxtools/docrevision.py +18 -17
  77. odxtools/dopbase.py +13 -14
  78. odxtools/dtcconnector.py +8 -7
  79. odxtools/dtcdop.py +24 -20
  80. odxtools/dynamicendmarkerfield.py +10 -9
  81. odxtools/dynamiclengthfield.py +10 -9
  82. odxtools/dyndefinedspec.py +10 -10
  83. odxtools/dynenddopref.py +9 -9
  84. odxtools/dyniddefmodeinfo.py +21 -21
  85. odxtools/ecuvariantpattern.py +8 -10
  86. odxtools/element.py +12 -13
  87. odxtools/encodestate.py +11 -11
  88. odxtools/encoding.py +2 -3
  89. odxtools/endofpdufield.py +9 -10
  90. odxtools/envdataconnector.py +8 -8
  91. odxtools/environmentdata.py +7 -9
  92. odxtools/environmentdatadescription.py +18 -17
  93. odxtools/exceptions.py +5 -5
  94. odxtools/externalaccessmethod.py +4 -6
  95. odxtools/externaldoc.py +6 -6
  96. odxtools/field.py +15 -15
  97. odxtools/functionalclass.py +9 -9
  98. odxtools/inputparam.py +11 -10
  99. odxtools/internalconstr.py +10 -11
  100. odxtools/isotp_state_machine.py +12 -11
  101. odxtools/leadinglengthinfotype.py +4 -6
  102. odxtools/library.py +9 -8
  103. odxtools/linkeddtcdop.py +9 -8
  104. odxtools/loadfile.py +5 -6
  105. odxtools/matchingbasevariantparameter.py +5 -6
  106. odxtools/matchingparameter.py +10 -10
  107. odxtools/message.py +1 -1
  108. odxtools/minmaxlengthtype.py +6 -7
  109. odxtools/modification.py +7 -6
  110. odxtools/multiplexer.py +54 -18
  111. odxtools/multiplexercase.py +13 -13
  112. odxtools/multiplexerdefaultcase.py +11 -10
  113. odxtools/multiplexerswitchkey.py +8 -8
  114. odxtools/nameditemlist.py +13 -13
  115. odxtools/negoutputparam.py +8 -8
  116. odxtools/obd.py +1 -2
  117. odxtools/odxcategory.py +14 -26
  118. odxtools/odxdoccontext.py +16 -0
  119. odxtools/odxlink.py +23 -25
  120. odxtools/odxtypes.py +18 -15
  121. odxtools/outputparam.py +9 -8
  122. odxtools/parameterinfo.py +1 -1
  123. odxtools/parameters/codedconstparameter.py +10 -10
  124. odxtools/parameters/createanyparameter.py +15 -16
  125. odxtools/parameters/dynamicparameter.py +5 -7
  126. odxtools/parameters/lengthkeyparameter.py +10 -10
  127. odxtools/parameters/matchingrequestparameter.py +6 -7
  128. odxtools/parameters/nrcconstparameter.py +13 -13
  129. odxtools/parameters/parameter.py +17 -18
  130. odxtools/parameters/parameterwithdop.py +13 -13
  131. odxtools/parameters/physicalconstantparameter.py +8 -7
  132. odxtools/parameters/reservedparameter.py +6 -8
  133. odxtools/parameters/systemparameter.py +5 -7
  134. odxtools/parameters/tableentryparameter.py +8 -8
  135. odxtools/parameters/tablekeyparameter.py +17 -17
  136. odxtools/parameters/tablestructparameter.py +11 -11
  137. odxtools/parameters/valueparameter.py +11 -11
  138. odxtools/paramlengthinfotype.py +10 -9
  139. odxtools/parentref.py +15 -13
  140. odxtools/physicaldimension.py +15 -15
  141. odxtools/physicaltype.py +5 -6
  142. odxtools/posresponsesuppressible.py +11 -12
  143. odxtools/preconditionstateref.py +11 -11
  144. odxtools/progcode.py +11 -10
  145. odxtools/protstack.py +10 -9
  146. odxtools/relateddiagcommref.py +5 -6
  147. odxtools/relateddoc.py +11 -10
  148. odxtools/request.py +18 -19
  149. odxtools/response.py +19 -20
  150. odxtools/scaleconstr.py +8 -9
  151. odxtools/servicebinner.py +5 -5
  152. odxtools/singleecujob.py +16 -15
  153. odxtools/snrefcontext.py +3 -3
  154. odxtools/specialdata.py +8 -7
  155. odxtools/specialdatagroup.py +17 -17
  156. odxtools/specialdatagroupcaption.py +7 -6
  157. odxtools/standardlengthtype.py +14 -22
  158. odxtools/state.py +7 -6
  159. odxtools/statechart.py +12 -11
  160. odxtools/statemachine.py +4 -3
  161. odxtools/statetransition.py +9 -9
  162. odxtools/statetransitionref.py +19 -19
  163. odxtools/staticfield.py +9 -7
  164. odxtools/structure.py +5 -6
  165. odxtools/subcomponent.py +20 -18
  166. odxtools/subcomponentparamconnector.py +10 -9
  167. odxtools/subcomponentpattern.py +9 -9
  168. odxtools/swvariable.py +6 -7
  169. odxtools/table.py +25 -26
  170. odxtools/tablediagcommconnector.py +9 -8
  171. odxtools/tablerow.py +64 -43
  172. odxtools/tablerowconnector.py +8 -8
  173. odxtools/teammember.py +16 -15
  174. odxtools/templates/macros/printParentRef.xml.jinja2 +3 -1
  175. odxtools/text.py +4 -5
  176. odxtools/uds.py +2 -3
  177. odxtools/unit.py +14 -13
  178. odxtools/unitgroup.py +11 -10
  179. odxtools/unitspec.py +18 -19
  180. odxtools/utils.py +3 -3
  181. odxtools/variablegroup.py +5 -6
  182. odxtools/variantmatcher.py +10 -10
  183. odxtools/variantpattern.py +5 -6
  184. odxtools/version.py +2 -2
  185. odxtools/writepdxfile.py +5 -24
  186. odxtools/xdoc.py +13 -12
  187. {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/METADATA +4 -5
  188. odxtools-10.1.0.dist-info/RECORD +265 -0
  189. {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/WHEEL +1 -1
  190. odxtools-9.7.0.dist-info/RECORD +0 -264
  191. {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/entry_points.txt +0 -0
  192. {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/licenses/LICENSE +0 -0
  193. {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/top_level.txt +0 -0
@@ -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
@@ -11,13 +12,14 @@ from .dynenddopref import DynEndDopRef
11
12
  from .encodestate import EncodeState
12
13
  from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
13
14
  from .field import Field
14
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
15
+ from .odxdoccontext import OdxDocContext
16
+ from .odxlink import OdxLinkDatabase, OdxLinkId
15
17
  from .odxtypes import AtomicOdxType, ParameterValue
16
18
  from .snrefcontext import SnRefContext
17
19
  from .utils import dataclass_fields_asdict
18
20
 
19
21
 
20
- @dataclass
22
+ @dataclass(kw_only=True)
21
23
  class DynamicEndmarkerField(Field):
22
24
  """Array of a structure with variable length determined by a termination sequence"""
23
25
 
@@ -32,18 +34,17 @@ class DynamicEndmarkerField(Field):
32
34
  return self._termination_value
33
35
 
34
36
  @staticmethod
35
- def from_et(et_element: ElementTree.Element,
36
- doc_frags: List[OdxDocFragment]) -> "DynamicEndmarkerField":
37
- kwargs = dataclass_fields_asdict(Field.from_et(et_element, doc_frags))
37
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DynamicEndmarkerField":
38
+ kwargs = dataclass_fields_asdict(Field.from_et(et_element, context))
38
39
 
39
40
  # ODX 2.0 uses DATA-OBJECT-PROP-REF
40
41
  # ODX 2.2 uses DYN-END-DOP-REF
41
42
  dop_ref = et_element.find("DYN-END-DOP-REF") or et_element.find("DATA-OBJECT-PROP-REF")
42
- dyn_end_dop_ref = DynEndDopRef.from_et(odxrequire(dop_ref), doc_frags)
43
+ dyn_end_dop_ref = DynEndDopRef.from_et(odxrequire(dop_ref), context)
43
44
 
44
45
  return DynamicEndmarkerField(dyn_end_dop_ref=dyn_end_dop_ref, **kwargs)
45
46
 
46
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
47
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
47
48
  odxlinks = super()._build_odxlinks()
48
49
  return odxlinks
49
50
 
@@ -102,7 +103,7 @@ class DynamicEndmarkerField(Field):
102
103
  orig_origin = decode_state.origin_byte_position
103
104
  decode_state.origin_byte_position = decode_state.cursor_byte_position
104
105
 
105
- result: List[ParameterValue] = []
106
+ result: list[ParameterValue] = []
106
107
  while True:
107
108
  # check if we're at the end of the PDU
108
109
  if decode_state.cursor_byte_position == len(decode_state.coded_message):
@@ -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
@@ -10,33 +11,33 @@ from .determinenumberofitems import DetermineNumberOfItems
10
11
  from .encodestate import EncodeState
11
12
  from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
12
13
  from .field import Field
13
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
14
+ from .odxdoccontext import OdxDocContext
15
+ from .odxlink import OdxLinkDatabase, OdxLinkId
14
16
  from .odxtypes import ParameterValue
15
17
  from .snrefcontext import SnRefContext
16
18
  from .utils import dataclass_fields_asdict
17
19
 
18
20
 
19
- @dataclass
21
+ @dataclass(kw_only=True)
20
22
  class DynamicLengthField(Field):
21
23
  """Array of structure with length field"""
22
24
  offset: int
23
25
  determine_number_of_items: DetermineNumberOfItems
24
26
 
25
27
  @staticmethod
26
- def from_et(et_element: ElementTree.Element,
27
- doc_frags: List[OdxDocFragment]) -> "DynamicLengthField":
28
- kwargs = dataclass_fields_asdict(Field.from_et(et_element, doc_frags))
28
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DynamicLengthField":
29
+ kwargs = dataclass_fields_asdict(Field.from_et(et_element, context))
29
30
 
30
31
  offset = int(odxrequire(et_element.findtext('OFFSET')))
31
32
  determine_number_of_items = DetermineNumberOfItems.from_et(
32
33
  odxrequire(et_element.find('DETERMINE-NUMBER-OF-ITEMS')),
33
- doc_frags,
34
+ context,
34
35
  )
35
36
 
36
37
  return DynamicLengthField(
37
38
  offset=offset, determine_number_of_items=determine_number_of_items, **kwargs)
38
39
 
39
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
40
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
40
41
  odxlinks = super()._build_odxlinks()
41
42
  odxlinks.update(self.determine_number_of_items._build_odxlinks())
42
43
  return odxlinks
@@ -106,7 +107,7 @@ class DynamicLengthField(Field):
106
107
  decode_state.cursor_bit_position = det_num_items.bit_position or 0
107
108
 
108
109
  n = det_num_items.dop.decode_from_pdu(decode_state)
109
- result: List[ParameterValue] = []
110
+ result: list[ParameterValue] = []
110
111
 
111
112
  if not isinstance(n, int):
112
113
  odxraise(f"Number of items specified by a dynamic length field {self.short_name} "
@@ -1,28 +1,28 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
3
- from typing import Any, Dict, List
2
+ from dataclasses import dataclass, field
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .dyniddefmodeinfo import DynIdDefModeInfo
7
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
7
+ from .odxdoccontext import OdxDocContext
8
+ from .odxlink import OdxLinkDatabase, OdxLinkId
8
9
  from .snrefcontext import SnRefContext
9
10
 
10
11
 
11
- @dataclass
12
+ @dataclass(kw_only=True)
12
13
  class DynDefinedSpec:
13
- dyn_id_def_mode_infos: List[DynIdDefModeInfo]
14
+ dyn_id_def_mode_infos: list[DynIdDefModeInfo] = field(default_factory=list)
14
15
 
15
16
  @staticmethod
16
- def from_et(et_element: ElementTree.Element,
17
- doc_frags: List[OdxDocFragment]) -> "DynDefinedSpec":
17
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DynDefinedSpec":
18
18
  dyn_id_def_mode_infos = [
19
- DynIdDefModeInfo.from_et(x, doc_frags)
19
+ DynIdDefModeInfo.from_et(x, context)
20
20
  for x in et_element.iterfind("DYN-ID-DEF-MODE-INFOS/DYN-ID-DEF-MODE-INFO")
21
21
  ]
22
22
  return DynDefinedSpec(dyn_id_def_mode_infos=dyn_id_def_mode_infos)
23
23
 
24
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
25
- result: Dict[OdxLinkId, Any] = {}
24
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
25
+ result: dict[OdxLinkId, Any] = {}
26
26
 
27
27
  for didmi in self.dyn_id_def_mode_infos:
28
28
  result.update(didmi._build_odxlinks())
odxtools/dynenddopref.py CHANGED
@@ -1,37 +1,37 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional, overload
3
+ from typing import Optional, overload
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .exceptions import odxraise, odxrequire
7
- from .odxlink import OdxDocFragment, OdxLinkRef
7
+ from .odxdoccontext import OdxDocContext
8
+ from .odxlink import OdxLinkRef
8
9
  from .utils import dataclass_fields_asdict
9
10
 
10
11
 
11
- @dataclass
12
+ @dataclass(kw_only=True)
12
13
  class DynEndDopRef(OdxLinkRef):
13
14
  termination_value_raw: str
14
15
 
15
16
  @staticmethod
16
17
  @overload
17
- def from_et(et_element: None, source_doc_frags: List[OdxDocFragment]) -> None:
18
+ def from_et(et_element: None, context: OdxDocContext) -> None:
18
19
  ...
19
20
 
20
21
  @staticmethod
21
22
  @overload
22
- def from_et(et_element: ElementTree.Element,
23
- source_doc_frags: List[OdxDocFragment]) -> "DynEndDopRef":
23
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DynEndDopRef":
24
24
  ...
25
25
 
26
26
  @staticmethod
27
- def from_et(et_element: Optional[ElementTree.Element],
28
- source_doc_frags: List[OdxDocFragment]) -> Optional["DynEndDopRef"]:
27
+ def from_et(et_element: ElementTree.Element | None,
28
+ context: OdxDocContext) -> Optional["DynEndDopRef"]:
29
29
 
30
30
  if et_element is None:
31
31
  odxraise("Mandatory DYN-END-DOP-REF tag is missing")
32
32
  return None
33
33
 
34
- kwargs = dataclass_fields_asdict(OdxLinkRef.from_et(et_element, source_doc_frags))
34
+ kwargs = dataclass_fields_asdict(OdxLinkRef.from_et(et_element, context))
35
35
 
36
36
  termination_value_raw = odxrequire(et_element.findtext("TERMINATION-VALUE"))
37
37
 
@@ -1,32 +1,33 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional, Union
2
+ from dataclasses import dataclass, field
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .diagclasstype import DiagClassType
7
7
  from .diagcomm import DiagComm
8
8
  from .exceptions import odxassert, odxraise, odxrequire
9
9
  from .nameditemlist import NamedItemList
10
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
10
+ from .odxdoccontext import OdxDocContext
11
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
11
12
  from .snrefcontext import SnRefContext
12
13
  from .table import Table
13
14
 
14
15
 
15
- @dataclass
16
+ @dataclass(kw_only=True)
16
17
  class DynIdDefModeInfo:
17
18
  def_mode: str
18
19
 
19
- clear_dyn_def_message_ref: Optional[OdxLinkRef]
20
- clear_dyn_def_message_snref: Optional[str]
20
+ clear_dyn_def_message_ref: OdxLinkRef | None = None
21
+ clear_dyn_def_message_snref: str | None = None
21
22
 
22
- read_dyn_def_message_ref: Optional[OdxLinkRef]
23
- read_dyn_def_message_snref: Optional[str]
23
+ read_dyn_def_message_ref: OdxLinkRef | None = None
24
+ read_dyn_def_message_snref: str | None = None
24
25
 
25
- dyn_def_message_ref: Optional[OdxLinkRef]
26
- dyn_def_message_snref: Optional[str]
26
+ dyn_def_message_ref: OdxLinkRef | None = None
27
+ dyn_def_message_snref: str | None = None
27
28
 
28
- supported_dyn_ids: List[bytes]
29
- selection_table_refs: List[Union[OdxLinkRef, str]]
29
+ supported_dyn_ids: list[bytes] = field(default_factory=list)
30
+ selection_table_refs: list[OdxLinkRef | str] = field(default_factory=list)
30
31
 
31
32
  @property
32
33
  def clear_dyn_def_message(self) -> DiagComm:
@@ -45,23 +46,22 @@ class DynIdDefModeInfo:
45
46
  return self._selection_tables
46
47
 
47
48
  @staticmethod
48
- def from_et(et_element: ElementTree.Element,
49
- doc_frags: List[OdxDocFragment]) -> "DynIdDefModeInfo":
49
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DynIdDefModeInfo":
50
50
  def_mode = odxrequire(et_element.findtext("DEF-MODE"))
51
51
 
52
52
  clear_dyn_def_message_ref = OdxLinkRef.from_et(
53
- et_element.find("CLEAR-DYN-DEF-MESSAGE-REF"), doc_frags)
53
+ et_element.find("CLEAR-DYN-DEF-MESSAGE-REF"), context)
54
54
  clear_dyn_def_message_snref = None
55
55
  if (snref_elem := et_element.find("CLEAR-DYN-DEF-MESSAGE-SNREF")) is not None:
56
56
  clear_dyn_def_message_snref = odxrequire(snref_elem.attrib.get("SHORT-NAME"))
57
57
 
58
58
  read_dyn_def_message_ref = OdxLinkRef.from_et(
59
- et_element.find("READ-DYN-DEF-MESSAGE-REF"), doc_frags)
59
+ et_element.find("READ-DYN-DEF-MESSAGE-REF"), context)
60
60
  read_dyn_def_message_snref = None
61
61
  if (snref_elem := et_element.find("READ-DYN-DEF-MESSAGE-SNREF")) is not None:
62
62
  read_dyn_def_message_snref = odxrequire(snref_elem.attrib.get("SHORT-NAME"))
63
63
 
64
- dyn_def_message_ref = OdxLinkRef.from_et(et_element.find("DYN-DEF-MESSAGE-REF"), doc_frags)
64
+ dyn_def_message_ref = OdxLinkRef.from_et(et_element.find("DYN-DEF-MESSAGE-REF"), context)
65
65
  dyn_def_message_snref = None
66
66
  if (snref_elem := et_element.find("DYN-DEF-MESSAGE-SNREF")) is not None:
67
67
  dyn_def_message_snref = odxrequire(snref_elem.attrib.get("SHORT-NAME"))
@@ -71,11 +71,11 @@ class DynIdDefModeInfo:
71
71
  for x in et_element.iterfind("SUPPORTED-DYN-IDS/SUPPORTED-DYN-ID")
72
72
  ]
73
73
 
74
- selection_table_refs: List[Union[OdxLinkRef, str]] = []
74
+ selection_table_refs: list[OdxLinkRef | str] = []
75
75
  if (st_elems := et_element.find("SELECTION-TABLE-REFS")) is not None:
76
76
  for st_elem in st_elems:
77
77
  if st_elem.tag == "SELECTION-TABLE-REF":
78
- selection_table_refs.append(OdxLinkRef.from_et(st_elem, doc_frags))
78
+ selection_table_refs.append(OdxLinkRef.from_et(st_elem, context))
79
79
  elif st_elem.tag == "SELECTION-TABLE-SNREF":
80
80
  selection_table_refs.append(odxrequire(st_elem.get("SHORT-NAME")))
81
81
  else:
@@ -104,8 +104,8 @@ class DynIdDefModeInfo:
104
104
  odxassert(self.dyn_def_message_ref is not None or self.dyn_def_message_snref is not None,
105
105
  "A DYN-DEF-MESSAGE must be specified")
106
106
 
107
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
108
- result: Dict[OdxLinkId, Any] = {}
107
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
108
+ result: dict[OdxLinkId, Any] = {}
109
109
 
110
110
  return result
111
111
 
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
3
- from typing import List, Union
2
+ from dataclasses import dataclass, field
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from typing_extensions import override
@@ -8,28 +7,27 @@ from typing_extensions import override
8
7
  from .exceptions import odxassert
9
8
  from .matchingbasevariantparameter import MatchingBaseVariantParameter
10
9
  from .matchingparameter import MatchingParameter
11
- from .odxlink import OdxDocFragment
10
+ from .odxdoccontext import OdxDocContext
12
11
  from .variantpattern import VariantPattern
13
12
 
14
13
 
15
- @dataclass
14
+ @dataclass(kw_only=True)
16
15
  class EcuVariantPattern(VariantPattern):
17
16
  """ECU variant patterns are variant patterns used to identify the
18
17
  concrete variant of an ECU.
19
18
  """
20
- matching_parameters: List[MatchingParameter]
19
+ matching_parameters: list[MatchingParameter] = field(default_factory=list)
21
20
 
22
21
  @override
23
- def get_matching_parameters(
24
- self) -> Union[List[MatchingParameter], List[MatchingBaseVariantParameter]]:
22
+ def get_matching_parameters(self
23
+ ) -> list[MatchingParameter] | list[MatchingBaseVariantParameter]:
25
24
  return self.matching_parameters
26
25
 
27
26
  @staticmethod
28
- def from_et(et_element: ElementTree.Element,
29
- doc_frags: List[OdxDocFragment]) -> "EcuVariantPattern":
27
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EcuVariantPattern":
30
28
 
31
29
  matching_parameters = [
32
- MatchingParameter.from_et(mp_el, doc_frags)
30
+ MatchingParameter.from_et(mp_el, context)
33
31
  for mp_el in et_element.iterfind("MATCHING-PARAMETERS/"
34
32
  "MATCHING-PARAMETER")
35
33
  ]
odxtools/element.py CHANGED
@@ -1,41 +1,40 @@
1
1
  from dataclasses import dataclass
2
- from typing import List, Optional
3
2
  from xml.etree import ElementTree
4
3
 
5
4
  from .description import Description
6
5
  from .exceptions import odxrequire
7
- from .odxlink import OdxDocFragment, OdxLinkId
6
+ from .odxdoccontext import OdxDocContext
7
+ from .odxlink import OdxLinkId
8
8
  from .utils import dataclass_fields_asdict
9
9
 
10
10
 
11
- @dataclass
11
+ @dataclass(kw_only=True)
12
12
  class NamedElement:
13
13
  short_name: str
14
- long_name: Optional[str]
15
- description: Optional[Description]
14
+ long_name: str | None = None
15
+ description: Description | None = None
16
16
 
17
17
  @staticmethod
18
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "NamedElement":
18
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "NamedElement":
19
19
 
20
20
  return NamedElement(
21
21
  short_name=odxrequire(et_element.findtext("SHORT-NAME")),
22
22
  long_name=et_element.findtext("LONG-NAME"),
23
- description=Description.from_et(et_element.find("DESC"), doc_frags),
23
+ description=Description.from_et(et_element.find("DESC"), context),
24
24
  )
25
25
 
26
26
 
27
- @dataclass
27
+ @dataclass(kw_only=True)
28
28
  class IdentifiableElement(NamedElement):
29
29
  odx_id: OdxLinkId
30
- oid: Optional[str]
30
+ oid: str | None = None
31
31
 
32
32
  @staticmethod
33
- def from_et(et_element: ElementTree.Element,
34
- doc_frags: List[OdxDocFragment]) -> "IdentifiableElement":
33
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "IdentifiableElement":
35
34
 
36
- kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
35
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, context))
37
36
 
38
- odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
37
+ odx_id = odxrequire(OdxLinkId.from_et(et_element, context))
39
38
  oid = et_element.get("OID")
40
39
 
41
40
  return IdentifiableElement(**kwargs, odx_id=odx_id, oid=oid)
odxtools/encodestate.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import warnings
3
3
  from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
4
+ from typing import TYPE_CHECKING
5
5
 
6
6
  from .encoding import Encoding, get_string_encoding
7
7
  from .exceptions import EncodeError, OdxWarning, odxassert, odxraise
@@ -41,20 +41,20 @@ class EncodeState:
41
41
  cursor_bit_position: int = 0
42
42
 
43
43
  #: If encoding a response: request that triggered the response
44
- triggering_request: Optional[bytes] = None
44
+ triggering_request: bytes | None = None
45
45
 
46
46
  #: Mapping from the short name of a length-key parameter to bit
47
47
  #: lengths (specified by LengthKeyParameter)
48
- length_keys: Dict[str, int] = field(default_factory=dict)
48
+ length_keys: dict[str, int] = field(default_factory=dict)
49
49
 
50
50
  #: Mapping from the short name of a table-key parameter to the
51
51
  #: short name of the corresponding row of the table (specified by
52
52
  #: TableKeyParameter)
53
- table_keys: Dict[str, str] = field(default_factory=dict)
53
+ table_keys: dict[str, str] = field(default_factory=dict)
54
54
 
55
55
  #: The cursor position where a given length- or table key is located
56
56
  #: in the PDU
57
- key_pos: Dict[str, int] = field(default_factory=dict)
57
+ key_pos: dict[str, int] = field(default_factory=dict)
58
58
 
59
59
  #: Flag whether we are currently the last parameter of the PDU
60
60
  #: (needed for MinMaxLengthType, EndOfPduField, etc.)
@@ -63,7 +63,7 @@ class EncodeState:
63
63
  #: list of parameters that have been encoded so far. The journal
64
64
  #: is used by some types of parameters which depend on the values of
65
65
  #: other parameters; e.g., environment data description parameters
66
- journal: List[Tuple["Parameter", Optional[ParameterValue]]] = field(default_factory=list)
66
+ journal: list[tuple["Parameter", ParameterValue | None]] = field(default_factory=list)
67
67
 
68
68
  #: If this is True, specifying unknown parameters for encoding
69
69
  #: will raise an OdxError exception in strict mode.
@@ -87,9 +87,9 @@ class EncodeState:
87
87
  internal_value: AtomicOdxType,
88
88
  bit_length: int,
89
89
  base_data_type: DataType,
90
- base_type_encoding: Optional[Encoding],
90
+ base_type_encoding: Encoding | None,
91
91
  is_highlow_byte_order: bool,
92
- used_mask: Optional[bytes],
92
+ used_mask: bytes | None,
93
93
  ) -> None:
94
94
  """Convert the internal_value to bytes and emplace this into the PDU"""
95
95
 
@@ -220,7 +220,7 @@ class EncodeState:
220
220
  odxraise(f"Illegal bit length for a float64 object ({bit_length})")
221
221
  bit_length = 64
222
222
 
223
- raw_value = float(internal_value)
223
+ raw_value = float(internal_value) # type: ignore[arg-type]
224
224
 
225
225
  # If the bit length is zero, encode an empty value
226
226
  if bit_length == 0:
@@ -260,8 +260,8 @@ class EncodeState:
260
260
 
261
261
  def emplace_bytes(self,
262
262
  new_data: bytes,
263
- obj_name: Optional[str] = None,
264
- obj_used_mask: Optional[bytes] = None) -> None:
263
+ obj_name: str | None = None,
264
+ obj_used_mask: bytes | None = None) -> None:
265
265
  if self.cursor_bit_position != 0:
266
266
  odxraise("EncodeState.emplace_bytes can only be called "
267
267
  "for a bit position of 0!", RuntimeError)
odxtools/encoding.py CHANGED
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from enum import Enum
3
- from typing import Optional
4
3
 
5
4
  from .exceptions import odxraise
6
5
  from .odxtypes import DataType
@@ -23,8 +22,8 @@ class Encoding(Enum):
23
22
  NONE = "NONE"
24
23
 
25
24
 
26
- def get_string_encoding(base_data_type: DataType, base_type_encoding: Optional[Encoding],
27
- is_highlow_byte_order: bool) -> Optional[str]:
25
+ def get_string_encoding(base_data_type: DataType, base_type_encoding: Encoding | None,
26
+ is_highlow_byte_order: bool) -> str | None:
28
27
  """If the encoding is for a string, return the value for
29
28
  `str.encode()`/`str.decode()` to convert the string object
30
29
  to/from a byte array
odxtools/endofpdufield.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ from collections.abc import Sequence
2
3
  from dataclasses import dataclass
3
- from typing import List, Optional, Sequence
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -9,21 +9,20 @@ from .decodestate import DecodeState
9
9
  from .encodestate import EncodeState
10
10
  from .exceptions import EncodeError, odxassert, odxraise
11
11
  from .field import Field
12
- from .odxlink import OdxDocFragment
12
+ from .odxdoccontext import OdxDocContext
13
13
  from .odxtypes import ParameterValue
14
14
  from .utils import dataclass_fields_asdict
15
15
 
16
16
 
17
- @dataclass
17
+ @dataclass(kw_only=True)
18
18
  class EndOfPduField(Field):
19
19
  """End of PDU fields are structures that are repeated until the end of the PDU"""
20
- max_number_of_items: Optional[int]
21
- min_number_of_items: Optional[int]
20
+ max_number_of_items: int | None = None
21
+ min_number_of_items: int | None = None
22
22
 
23
23
  @staticmethod
24
- def from_et(et_element: ElementTree.Element,
25
- doc_frags: List[OdxDocFragment]) -> "EndOfPduField":
26
- kwargs = dataclass_fields_asdict(Field.from_et(et_element, doc_frags))
24
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EndOfPduField":
25
+ kwargs = dataclass_fields_asdict(Field.from_et(et_element, context))
27
26
 
28
27
  if (max_n_str := et_element.findtext("MAX-NUMBER-OF-ITEMS")) is not None:
29
28
  max_number_of_items = int(max_n_str)
@@ -40,7 +39,7 @@ class EndOfPduField(Field):
40
39
  **kwargs)
41
40
 
42
41
  @override
43
- def encode_into_pdu(self, physical_value: Optional[ParameterValue],
42
+ def encode_into_pdu(self, physical_value: ParameterValue | None,
44
43
  encode_state: EncodeState) -> None:
45
44
  odxassert(not encode_state.cursor_bit_position,
46
45
  "No bit position can be specified for end-of-pdu fields!")
@@ -72,7 +71,7 @@ class EndOfPduField(Field):
72
71
  orig_origin = decode_state.origin_byte_position
73
72
  decode_state.origin_byte_position = decode_state.cursor_byte_position
74
73
 
75
- result: List[ParameterValue] = []
74
+ result: list[ParameterValue] = []
76
75
  while decode_state.cursor_byte_position < len(decode_state.coded_message):
77
76
  # ATTENTION: the ODX specification is very misleading
78
77
  # here: it says that the item is repeated until the end of
@@ -1,18 +1,19 @@
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 NamedElement
7
7
  from .environmentdata import EnvironmentData
8
8
  from .environmentdatadescription import EnvironmentDataDescription
9
9
  from .exceptions import odxrequire
10
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
10
+ from .odxdoccontext import OdxDocContext
11
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
11
12
  from .snrefcontext import SnRefContext
12
13
  from .utils import dataclass_fields_asdict
13
14
 
14
15
 
15
- @dataclass
16
+ @dataclass(kw_only=True)
16
17
  class EnvDataConnector(NamedElement):
17
18
  env_data_desc_ref: OdxLinkRef
18
19
  env_data_snref: str
@@ -26,19 +27,18 @@ class EnvDataConnector(NamedElement):
26
27
  return self._env_data
27
28
 
28
29
  @staticmethod
29
- def from_et(et_element: ElementTree.Element,
30
- doc_frags: List[OdxDocFragment]) -> "EnvDataConnector":
31
- kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
30
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EnvDataConnector":
31
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, context))
32
32
 
33
33
  env_data_desc_ref = odxrequire(
34
- OdxLinkRef.from_et(et_element.find("ENV-DATA-DESC-REF"), doc_frags))
34
+ OdxLinkRef.from_et(et_element.find("ENV-DATA-DESC-REF"), context))
35
35
  env_data_snref_el = odxrequire(et_element.find("ENV-DATA-SNREF"))
36
36
  env_data_snref = odxrequire(env_data_snref_el.get("SHORT-NAME"))
37
37
 
38
38
  return EnvDataConnector(
39
39
  env_data_desc_ref=env_data_desc_ref, env_data_snref=env_data_snref, **kwargs)
40
40
 
41
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
41
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
42
42
  return {}
43
43
 
44
44
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
@@ -1,15 +1,14 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
3
- from typing import List, Optional
2
+ from dataclasses import dataclass, field
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from .basicstructure import BasicStructure
7
6
  from .exceptions import odxrequire
8
- from .odxlink import OdxDocFragment
7
+ from .odxdoccontext import OdxDocContext
9
8
  from .utils import dataclass_fields_asdict
10
9
 
11
10
 
12
- @dataclass
11
+ @dataclass(kw_only=True)
13
12
  class EnvironmentData(BasicStructure):
14
13
  """This class represents Environment Data that describes the
15
14
  circumstances in which the error occurred.
@@ -20,14 +19,13 @@ class EnvironmentData(BasicStructure):
20
19
  sense, it is quite similar to NRC-CONST parameters.)
21
20
  """
22
21
 
23
- all_value: Optional[bool]
24
- dtc_values: List[int]
22
+ all_value: bool | None = None
23
+ dtc_values: list[int] = field(default_factory=list)
25
24
 
26
25
  @staticmethod
27
- def from_et(et_element: ElementTree.Element,
28
- doc_frags: List[OdxDocFragment]) -> "EnvironmentData":
26
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EnvironmentData":
29
27
  """Reads Environment Data from Diag Layer."""
30
- kwargs = dataclass_fields_asdict(BasicStructure.from_et(et_element, doc_frags))
28
+ kwargs = dataclass_fields_asdict(BasicStructure.from_et(et_element, context))
31
29
 
32
30
  all_value_elem = et_element.find("ALL-VALUE")
33
31
  all_value = None if all_value_elem is None else True