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
odxtools/diagvariable.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import typing
3
3
  from dataclasses import dataclass
4
- from typing import Any, Dict, List, Optional, runtime_checkable
4
+ from typing import Any, runtime_checkable
5
5
  from xml.etree import ElementTree
6
6
 
7
7
  from .admindata import AdminData
@@ -33,32 +33,32 @@ class DiagVariable(IdentifiableElement):
33
33
  """Representation of a diagnostic variable
34
34
  """
35
35
 
36
- admin_data: Optional[AdminData]
37
- variable_group_ref: Optional[OdxLinkRef]
38
- sw_variables: List[SwVariable]
36
+ admin_data: AdminData | None
37
+ variable_group_ref: OdxLinkRef | None
38
+ sw_variables: list[SwVariable]
39
39
 
40
40
  # a diag variable must specify either COMM-RELATIONS or a
41
41
  # reference to a table row
42
- comm_relations: List[CommRelation]
42
+ comm_relations: list[CommRelation]
43
43
 
44
44
  # these are nested inside the SNREF-TO-TABLEROW tag
45
- table_snref: Optional[str]
46
- table_row_snref: Optional[str]
45
+ table_snref: str | None
46
+ table_row_snref: str | None
47
47
 
48
- sdgs: List[SpecialDataGroup]
48
+ sdgs: list[SpecialDataGroup]
49
49
 
50
- is_read_before_write_raw: Optional[bool]
50
+ is_read_before_write_raw: bool | None
51
51
 
52
52
  @property
53
- def table(self) -> Optional[Table]:
53
+ def table(self) -> Table | None:
54
54
  return self._table
55
55
 
56
56
  @property
57
- def table_row(self) -> Optional[TableRow]:
57
+ def table_row(self) -> TableRow | None:
58
58
  return self._table_row
59
59
 
60
60
  @property
61
- def variable_group(self) -> Optional[VariableGroup]:
61
+ def variable_group(self) -> VariableGroup | None:
62
62
  return self._variable_group
63
63
 
64
64
  @property
@@ -66,7 +66,7 @@ class DiagVariable(IdentifiableElement):
66
66
  return self.is_read_before_write_raw is True
67
67
 
68
68
  @staticmethod
69
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "DiagVariable":
69
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "DiagVariable":
70
70
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
71
71
 
72
72
  admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
@@ -106,7 +106,7 @@ class DiagVariable(IdentifiableElement):
106
106
  is_read_before_write_raw=is_read_before_write_raw,
107
107
  **kwargs)
108
108
 
109
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
109
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
110
110
  result = {self.odx_id: self}
111
111
 
112
112
  if self.admin_data is not None:
odxtools/docrevision.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, Optional
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .companyrevisioninfo import CompanyRevisionInfo
@@ -17,20 +17,20 @@ class DocRevision:
17
17
  Representation of a single revision of the relevant object.
18
18
  """
19
19
 
20
- team_member_ref: Optional[OdxLinkRef]
21
- revision_label: Optional[str]
22
- state: Optional[str]
20
+ team_member_ref: OdxLinkRef | None
21
+ revision_label: str | None
22
+ state: str | None
23
23
  date: str
24
- tool: Optional[str]
25
- company_revision_infos: List[CompanyRevisionInfo]
26
- modifications: List[Modification]
24
+ tool: str | None
25
+ company_revision_infos: list[CompanyRevisionInfo]
26
+ modifications: list[Modification]
27
27
 
28
28
  @property
29
- def team_member(self) -> Optional[TeamMember]:
29
+ def team_member(self) -> TeamMember | None:
30
30
  return self._team_member
31
31
 
32
32
  @staticmethod
33
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "DocRevision":
33
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "DocRevision":
34
34
 
35
35
  team_member_ref = OdxLinkRef.from_et(et_element.find("TEAM-MEMBER-REF"), doc_frags)
36
36
  revision_label = et_element.findtext("REVISION-LABEL")
@@ -59,11 +59,11 @@ class DocRevision:
59
59
  modifications=modifications,
60
60
  )
61
61
 
62
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
62
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
63
63
  return {}
64
64
 
65
65
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
66
- self._team_member: Optional[TeamMember] = None
66
+ self._team_member: TeamMember | None = None
67
67
  if self.team_member_ref is not None:
68
68
  self._team_member = odxlinks.resolve(self.team_member_ref, TeamMember)
69
69
 
odxtools/dopbase.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, Optional
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .admindata import AdminData
@@ -24,11 +24,11 @@ class DopBase(IdentifiableElement):
24
24
 
25
25
  """
26
26
 
27
- admin_data: Optional[AdminData]
28
- sdgs: List[SpecialDataGroup]
27
+ admin_data: AdminData | None
28
+ sdgs: list[SpecialDataGroup]
29
29
 
30
30
  @staticmethod
31
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "DopBase":
31
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "DopBase":
32
32
 
33
33
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
34
34
 
@@ -42,7 +42,7 @@ class DopBase(IdentifiableElement):
42
42
 
43
43
  return DopBase(admin_data=admin_data, sdgs=sdgs, **kwargs)
44
44
 
45
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
45
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
46
46
  result = {self.odx_id: self}
47
47
 
48
48
  for sdg in self.sdgs:
@@ -58,7 +58,7 @@ class DopBase(IdentifiableElement):
58
58
  for sdg in self.sdgs:
59
59
  sdg._resolve_snrefs(context)
60
60
 
61
- def get_static_bit_length(self) -> Optional[int]:
61
+ def get_static_bit_length(self) -> int | None:
62
62
  return None
63
63
 
64
64
  def is_valid_physical_value(self, physical_value: ParameterValue) -> bool:
@@ -0,0 +1,45 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any
4
+ from xml.etree import ElementTree
5
+
6
+ from .diagnostictroublecode import DiagnosticTroubleCode
7
+ from .dtcdop import DtcDop
8
+ from .element import NamedElement
9
+ from .exceptions import odxrequire
10
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
11
+ from .snrefcontext import SnRefContext
12
+ from .utils import dataclass_fields_asdict
13
+
14
+
15
+ @dataclass
16
+ class DtcConnector(NamedElement):
17
+ dtc_dop_ref: OdxLinkRef
18
+ dtc_snref: str
19
+
20
+ @property
21
+ def dtc_dop(self) -> DtcDop:
22
+ return self._dtc_dop
23
+
24
+ @property
25
+ def dtc(self) -> DiagnosticTroubleCode:
26
+ return self._dtc
27
+
28
+ @staticmethod
29
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "DtcConnector":
30
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
31
+
32
+ dtc_dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DTC-DOP-REF"), doc_frags))
33
+ dtc_snref_el = odxrequire(et_element.find("DTC-SNREF"))
34
+ dtc_snref = odxrequire(dtc_snref_el.get("SHORT-NAME"))
35
+
36
+ return DtcConnector(dtc_dop_ref=dtc_dop_ref, dtc_snref=dtc_snref, **kwargs)
37
+
38
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
39
+ return {}
40
+
41
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
42
+ self._dtc_dop = odxlinks.resolve(self.dtc_dop_ref, DtcDop)
43
+
44
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
45
+ self._dtc = resolve_snref(self.dtc_snref, self._dtc_dop.dtcs, DiagnosticTroubleCode)
odxtools/dtcdop.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, Optional, Union, cast
3
+ from typing import Any, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -14,60 +14,15 @@ from .diagnostictroublecode import DiagnosticTroubleCode
14
14
  from .dopbase import DopBase
15
15
  from .encodestate import EncodeState
16
16
  from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
17
+ from .linkeddtcdop import LinkedDtcDop
17
18
  from .nameditemlist import NamedItemList
18
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
19
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
19
20
  from .odxtypes import ParameterValue, odxstr_to_bool
20
21
  from .physicaltype import PhysicalType
21
22
  from .snrefcontext import SnRefContext
22
23
  from .utils import dataclass_fields_asdict
23
24
 
24
25
 
25
- @dataclass
26
- class LinkedDtcDop:
27
- not_inherited_dtc_snrefs: List[str]
28
- dtc_dop_ref: OdxLinkRef
29
-
30
- @property
31
- def not_inherited_dtcs(self) -> NamedItemList[DiagnosticTroubleCode]:
32
- return self._not_inherited_dtcs
33
-
34
- @property
35
- def dtc_dop(self) -> "DtcDop":
36
- return self._dtc_dop
37
-
38
- @property
39
- def short_name(self) -> str:
40
- return self._dtc_dop.short_name
41
-
42
- @staticmethod
43
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "LinkedDtcDop":
44
- not_inherited_dtc_snrefs = [
45
- odxrequire(el.get("SHORT-NAME"))
46
- for el in et_element.iterfind("NOT-INHERITED-DTC-SNREFS/"
47
- "NOT-INHERITED-DTC-SNREF")
48
- ]
49
-
50
- dtc_dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DTC-DOP-REF"), doc_frags))
51
-
52
- return LinkedDtcDop(
53
- not_inherited_dtc_snrefs=not_inherited_dtc_snrefs, dtc_dop_ref=dtc_dop_ref)
54
-
55
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
56
- return {}
57
-
58
- def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
59
- self._dtc_dop = odxlinks.resolve(self.dtc_dop_ref, DtcDop)
60
-
61
- def _resolve_snrefs(self, context: SnRefContext) -> None:
62
- dtc_dop = self._dtc_dop
63
- not_inherited_dtcs = [
64
- resolve_snref(ni_snref, dtc_dop.dtcs, DiagnosticTroubleCode)
65
- for ni_snref in self.not_inherited_dtc_snrefs
66
- ]
67
-
68
- self._not_inherited_dtcs = NamedItemList(not_inherited_dtcs)
69
-
70
-
71
26
  @dataclass
72
27
  class DtcDop(DopBase):
73
28
  """A DOP describing a diagnostic trouble code"""
@@ -75,9 +30,9 @@ class DtcDop(DopBase):
75
30
  diag_coded_type: DiagCodedType
76
31
  physical_type: PhysicalType
77
32
  compu_method: CompuMethod
78
- dtcs_raw: List[Union[DiagnosticTroubleCode, OdxLinkRef]]
79
- linked_dtc_dops_raw: List[LinkedDtcDop]
80
- is_visible_raw: Optional[bool]
33
+ dtcs_raw: list[DiagnosticTroubleCode | OdxLinkRef]
34
+ linked_dtc_dops_raw: list[LinkedDtcDop]
35
+ is_visible_raw: bool | None
81
36
 
82
37
  @property
83
38
  def dtcs(self) -> NamedItemList[DiagnosticTroubleCode]:
@@ -92,7 +47,7 @@ class DtcDop(DopBase):
92
47
  return self.is_visible_raw is True
93
48
 
94
49
  @staticmethod
95
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "DtcDop":
50
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "DtcDop":
96
51
  """Reads a DTC-DOP."""
97
52
  kwargs = dataclass_fields_asdict(DopBase.from_et(et_element, doc_frags))
98
53
 
@@ -106,7 +61,7 @@ class DtcDop(DopBase):
106
61
  internal_type=diag_coded_type.base_data_type,
107
62
  physical_type=physical_type.base_data_type,
108
63
  )
109
- dtcs_raw: List[Union[DiagnosticTroubleCode, OdxLinkRef]] = []
64
+ dtcs_raw: list[DiagnosticTroubleCode | OdxLinkRef] = []
110
65
  if (dtcs_elem := et_element.find("DTCS")) is not None:
111
66
  for dtc_proxy_elem in dtcs_elem:
112
67
  if dtc_proxy_elem.tag == "DTC":
@@ -200,7 +155,7 @@ class DtcDop(DopBase):
200
155
  return cast(int, None)
201
156
 
202
157
  @override
203
- def encode_into_pdu(self, physical_value: Optional[ParameterValue],
158
+ def encode_into_pdu(self, physical_value: ParameterValue | None,
204
159
  encode_state: EncodeState) -> None:
205
160
  if physical_value is None:
206
161
  odxraise(f"No DTC specified", EncodeError)
@@ -208,7 +163,11 @@ class DtcDop(DopBase):
208
163
 
209
164
  trouble_code = self.convert_to_numerical_trouble_code(physical_value)
210
165
 
211
- internal_trouble_code = int(self.compu_method.convert_physical_to_internal(trouble_code))
166
+ if not isinstance(trouble_code, int):
167
+ odxraise()
168
+ internal_trouble_code = self.compu_method.convert_physical_to_internal(trouble_code)
169
+ if not isinstance(internal_trouble_code, int):
170
+ odxraise()
212
171
 
213
172
  found = False
214
173
  for dtc in self.dtcs:
@@ -223,7 +182,7 @@ class DtcDop(DopBase):
223
182
 
224
183
  self.diag_coded_type.encode_into_pdu(internal_trouble_code, encode_state)
225
184
 
226
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
185
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
227
186
  odxlinks = super()._build_odxlinks()
228
187
 
229
188
  odxlinks.update(self.compu_method._build_odxlinks())
@@ -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
@@ -33,7 +34,7 @@ class DynamicEndmarkerField(Field):
33
34
 
34
35
  @staticmethod
35
36
  def from_et(et_element: ElementTree.Element,
36
- doc_frags: List[OdxDocFragment]) -> "DynamicEndmarkerField":
37
+ doc_frags: list[OdxDocFragment]) -> "DynamicEndmarkerField":
37
38
  kwargs = dataclass_fields_asdict(Field.from_et(et_element, doc_frags))
38
39
 
39
40
  # ODX 2.0 uses DATA-OBJECT-PROP-REF
@@ -43,7 +44,7 @@ class DynamicEndmarkerField(Field):
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
@@ -24,7 +25,7 @@ class DynamicLengthField(Field):
24
25
 
25
26
  @staticmethod
26
27
  def from_et(et_element: ElementTree.Element,
27
- doc_frags: List[OdxDocFragment]) -> "DynamicLengthField":
28
+ doc_frags: list[OdxDocFragment]) -> "DynamicLengthField":
28
29
  kwargs = dataclass_fields_asdict(Field.from_et(et_element, doc_frags))
29
30
 
30
31
  offset = int(odxrequire(et_element.findtext('OFFSET')))
@@ -36,7 +37,7 @@ class DynamicLengthField(Field):
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,180 +1,28 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional, Union
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
- from .diagcomm import DiagClassType, DiagComm
7
- from .exceptions import odxassert, odxraise, odxrequire
8
- from .nameditemlist import NamedItemList
9
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
6
+ from .dyniddefmodeinfo import DynIdDefModeInfo
7
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
10
8
  from .snrefcontext import SnRefContext
11
- from .table import Table
12
-
13
-
14
- @dataclass
15
- class DynIdDefModeInfo:
16
- def_mode: str
17
-
18
- clear_dyn_def_message_ref: Optional[OdxLinkRef]
19
- clear_dyn_def_message_snref: Optional[str]
20
-
21
- read_dyn_def_message_ref: Optional[OdxLinkRef]
22
- read_dyn_def_message_snref: Optional[str]
23
-
24
- dyn_def_message_ref: Optional[OdxLinkRef]
25
- dyn_def_message_snref: Optional[str]
26
-
27
- supported_dyn_ids: List[bytes]
28
- selection_table_refs: List[Union[OdxLinkRef, str]]
29
-
30
- @property
31
- def clear_dyn_def_message(self) -> DiagComm:
32
- return self._clear_dyn_def_message
33
-
34
- @property
35
- def read_dyn_def_message(self) -> DiagComm:
36
- return self._read_dyn_def_message
37
-
38
- @property
39
- def dyn_def_message(self) -> DiagComm:
40
- return self._dyn_def_message
41
-
42
- @property
43
- def selection_tables(self) -> NamedItemList[Table]:
44
- return self._selection_tables
45
-
46
- @staticmethod
47
- def from_et(et_element: ElementTree.Element,
48
- doc_frags: List[OdxDocFragment]) -> "DynIdDefModeInfo":
49
- def_mode = odxrequire(et_element.findtext("DEF-MODE"))
50
-
51
- clear_dyn_def_message_ref = OdxLinkRef.from_et(
52
- et_element.find("CLEAR-DYN-DEF-MESSAGE-REF"), doc_frags)
53
- clear_dyn_def_message_snref = None
54
- if (snref_elem := et_element.find("CLEAR-DYN-DEF-MESSAGE-SNREF")) is not None:
55
- clear_dyn_def_message_snref = odxrequire(snref_elem.attrib.get("SHORT-NAME"))
56
-
57
- read_dyn_def_message_ref = OdxLinkRef.from_et(
58
- et_element.find("READ-DYN-DEF-MESSAGE-REF"), doc_frags)
59
- read_dyn_def_message_snref = None
60
- if (snref_elem := et_element.find("READ-DYN-DEF-MESSAGE-SNREF")) is not None:
61
- read_dyn_def_message_snref = odxrequire(snref_elem.attrib.get("SHORT-NAME"))
62
-
63
- dyn_def_message_ref = OdxLinkRef.from_et(et_element.find("DYN-DEF-MESSAGE-REF"), doc_frags)
64
- dyn_def_message_snref = None
65
- if (snref_elem := et_element.find("DYN-DEF-MESSAGE-SNREF")) is not None:
66
- dyn_def_message_snref = odxrequire(snref_elem.attrib.get("SHORT-NAME"))
67
-
68
- supported_dyn_ids = [
69
- bytes.fromhex(odxrequire(x.text))
70
- for x in et_element.iterfind("SUPPORTED-DYN-IDS/SUPPORTED-DYN-ID")
71
- ]
72
-
73
- selection_table_refs: List[Union[OdxLinkRef, str]] = []
74
- if (st_elems := et_element.find("SELECTION-TABLE-REFS")) is not None:
75
- for st_elem in st_elems:
76
- if st_elem.tag == "SELECTION-TABLE-REF":
77
- selection_table_refs.append(OdxLinkRef.from_et(st_elem, doc_frags))
78
- elif st_elem.tag == "SELECTION-TABLE-SNREF":
79
- selection_table_refs.append(odxrequire(st_elem.get("SHORT-NAME")))
80
- else:
81
- odxraise()
82
-
83
- return DynIdDefModeInfo(
84
- def_mode=def_mode,
85
- clear_dyn_def_message_ref=clear_dyn_def_message_ref,
86
- clear_dyn_def_message_snref=clear_dyn_def_message_snref,
87
- read_dyn_def_message_ref=read_dyn_def_message_ref,
88
- read_dyn_def_message_snref=read_dyn_def_message_snref,
89
- dyn_def_message_ref=dyn_def_message_ref,
90
- dyn_def_message_snref=dyn_def_message_snref,
91
- supported_dyn_ids=supported_dyn_ids,
92
- selection_table_refs=selection_table_refs,
93
- )
94
-
95
- def __post_init__(self) -> None:
96
- odxassert(
97
- self.clear_dyn_def_message_ref is not None or
98
- self.clear_dyn_def_message_snref is not None,
99
- "A CLEAR-DYN-DEF-MESSAGE must be specified")
100
- odxassert(
101
- self.read_dyn_def_message_ref is not None or
102
- self.read_dyn_def_message_snref is not None, "A READ-DYN-DEF-MESSAGE must be specified")
103
- odxassert(self.dyn_def_message_ref is not None or self.dyn_def_message_snref is not None,
104
- "A DYN-DEF-MESSAGE must be specified")
105
-
106
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
107
- result: Dict[OdxLinkId, Any] = {}
108
-
109
- return result
110
-
111
- def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
112
- if self.clear_dyn_def_message_ref is not None:
113
- self._clear_dyn_def_message = odxlinks.resolve(self.clear_dyn_def_message_ref, DiagComm)
114
-
115
- if self.read_dyn_def_message_ref is not None:
116
- self._read_dyn_def_message = odxlinks.resolve(self.read_dyn_def_message_ref, DiagComm)
117
-
118
- if self.dyn_def_message_ref is not None:
119
- self._dyn_def_message = odxlinks.resolve(self.dyn_def_message_ref, DiagComm)
120
-
121
- # resolve the selection tables that are referenced via ODXLINK
122
- self._selection_tables = NamedItemList[Table]()
123
- for x in self.selection_table_refs:
124
- if isinstance(x, OdxLinkRef):
125
- self._selection_tables.append(odxlinks.resolve(x, Table))
126
-
127
- def _resolve_snrefs(self, context: SnRefContext) -> None:
128
- diag_layer = odxrequire(context.diag_layer)
129
-
130
- if self.clear_dyn_def_message_snref is not None:
131
- self._clear_dyn_def_message = resolve_snref(self.clear_dyn_def_message_snref,
132
- diag_layer.diag_comms, DiagComm)
133
-
134
- if self.read_dyn_def_message_snref is not None:
135
- self._read_dyn_def_message = resolve_snref(self.read_dyn_def_message_snref,
136
- diag_layer.diag_comms, DiagComm)
137
-
138
- if self.dyn_def_message_snref is not None:
139
- self._dyn_def_message = resolve_snref(self.dyn_def_message_snref, diag_layer.diag_comms,
140
- DiagComm)
141
-
142
- if self._clear_dyn_def_message.diagnostic_class != DiagClassType.CLEAR_DYN_DEF_MESSAGE:
143
- odxraise(
144
- f"Diagnostic communication object of wrong type referenced: "
145
- f"({odxrequire(self._clear_dyn_def_message.diagnostic_class).value} instead of "
146
- f"CLEAR-DYN-DEF-MESSAGE)")
147
- if self._read_dyn_def_message.diagnostic_class != DiagClassType.READ_DYN_DEFINED_MESSAGE:
148
- odxraise(f"Diagnostic communication object of wrong type referenced: "
149
- f"({odxrequire(self._read_dyn_def_message.diagnostic_class).value} instead of "
150
- f"READ-DYN-DEFINED-MESSAGE)")
151
- if self._dyn_def_message.diagnostic_class != DiagClassType.DYN_DEF_MESSAGE:
152
- odxraise(f"Diagnostic communication object of wrong type referenced: "
153
- f"({odxrequire(self._dyn_def_message.diagnostic_class).value} instead of "
154
- f"DYN-DEF-MESSAGE)")
155
-
156
- # resolve the remaining selection tables that are referenced via SNREF
157
- ddd_spec = odxrequire(diag_layer.diag_data_dictionary_spec)
158
- for i, x in enumerate(self.selection_table_refs):
159
- if isinstance(x, str):
160
- self._selection_tables.insert(i, resolve_snref(x, ddd_spec.tables, Table))
161
9
 
162
10
 
163
11
  @dataclass
164
12
  class DynDefinedSpec:
165
- dyn_id_def_mode_infos: List[DynIdDefModeInfo]
13
+ dyn_id_def_mode_infos: list[DynIdDefModeInfo]
166
14
 
167
15
  @staticmethod
168
16
  def from_et(et_element: ElementTree.Element,
169
- doc_frags: List[OdxDocFragment]) -> "DynDefinedSpec":
17
+ doc_frags: list[OdxDocFragment]) -> "DynDefinedSpec":
170
18
  dyn_id_def_mode_infos = [
171
19
  DynIdDefModeInfo.from_et(x, doc_frags)
172
20
  for x in et_element.iterfind("DYN-ID-DEF-MODE-INFOS/DYN-ID-DEF-MODE-INFO")
173
21
  ]
174
22
  return DynDefinedSpec(dyn_id_def_mode_infos=dyn_id_def_mode_infos)
175
23
 
176
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
177
- result: Dict[OdxLinkId, Any] = {}
24
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
25
+ result: dict[OdxLinkId, Any] = {}
178
26
 
179
27
  for didmi in self.dyn_id_def_mode_infos:
180
28
  result.update(didmi._build_odxlinks())
odxtools/dynenddopref.py CHANGED
@@ -1,6 +1,6 @@
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
@@ -14,18 +14,18 @@ class DynEndDopRef(OdxLinkRef):
14
14
 
15
15
  @staticmethod
16
16
  @overload
17
- def from_et(et_element: None, source_doc_frags: List[OdxDocFragment]) -> None:
17
+ def from_et(et_element: None, source_doc_frags: list[OdxDocFragment]) -> None:
18
18
  ...
19
19
 
20
20
  @staticmethod
21
21
  @overload
22
22
  def from_et(et_element: ElementTree.Element,
23
- source_doc_frags: List[OdxDocFragment]) -> "DynEndDopRef":
23
+ source_doc_frags: list[OdxDocFragment]) -> "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
+ source_doc_frags: list[OdxDocFragment]) -> Optional["DynEndDopRef"]:
29
29
 
30
30
  if et_element is None:
31
31
  odxraise("Mandatory DYN-END-DOP-REF tag is missing")