odxtools 9.7.0__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 (189) hide show
  1. odxtools/additionalaudience.py +3 -3
  2. odxtools/admindata.py +8 -8
  3. odxtools/audience.py +10 -10
  4. odxtools/basecomparam.py +5 -5
  5. odxtools/basevariantpattern.py +4 -5
  6. odxtools/basicstructure.py +8 -8
  7. odxtools/cli/_print_utils.py +35 -23
  8. odxtools/cli/browse.py +9 -9
  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 +7 -7
  13. odxtools/cli/main.py +2 -2
  14. odxtools/cli/snoop.py +3 -3
  15. odxtools/codec.py +3 -3
  16. odxtools/commrelation.py +11 -11
  17. odxtools/companydata.py +5 -5
  18. odxtools/companydocinfo.py +8 -8
  19. odxtools/companyrevisioninfo.py +5 -5
  20. odxtools/companyspecificinfo.py +5 -5
  21. odxtools/comparam.py +3 -3
  22. odxtools/comparaminstance.py +10 -10
  23. odxtools/comparamspec.py +3 -3
  24. odxtools/comparamsubset.py +5 -5
  25. odxtools/complexcomparam.py +7 -7
  26. odxtools/compositecodec.py +11 -11
  27. odxtools/compumethods/compucodecompumethod.py +4 -4
  28. odxtools/compumethods/compuconst.py +4 -5
  29. odxtools/compumethods/compudefaultvalue.py +1 -2
  30. odxtools/compumethods/compuinternaltophys.py +6 -6
  31. odxtools/compumethods/compumethod.py +5 -5
  32. odxtools/compumethods/compuphystointernal.py +6 -6
  33. odxtools/compumethods/compurationalcoeffs.py +4 -4
  34. odxtools/compumethods/compuscale.py +9 -10
  35. odxtools/compumethods/createanycompumethod.py +1 -2
  36. odxtools/compumethods/identicalcompumethod.py +1 -2
  37. odxtools/compumethods/limit.py +12 -12
  38. odxtools/compumethods/linearcompumethod.py +2 -2
  39. odxtools/compumethods/linearsegment.py +14 -15
  40. odxtools/compumethods/ratfunccompumethod.py +3 -3
  41. odxtools/compumethods/ratfuncsegment.py +7 -8
  42. odxtools/compumethods/scalelinearcompumethod.py +7 -7
  43. odxtools/compumethods/scaleratfunccompumethod.py +4 -4
  44. odxtools/compumethods/tabintpcompumethod.py +15 -18
  45. odxtools/compumethods/texttablecompumethod.py +3 -3
  46. odxtools/createanycomparam.py +2 -4
  47. odxtools/createanydiagcodedtype.py +1 -2
  48. odxtools/database.py +9 -8
  49. odxtools/dataobjectproperty.py +10 -10
  50. odxtools/decodestate.py +5 -5
  51. odxtools/description.py +5 -5
  52. odxtools/determinenumberofitems.py +4 -4
  53. odxtools/diagcodedtype.py +7 -7
  54. odxtools/diagcomm.py +17 -17
  55. odxtools/diagdatadictionaryspec.py +6 -6
  56. odxtools/diaglayercontainer.py +4 -4
  57. odxtools/diaglayers/basevariant.py +10 -9
  58. odxtools/diaglayers/basevariantraw.py +9 -9
  59. odxtools/diaglayers/diaglayer.py +20 -19
  60. odxtools/diaglayers/diaglayerraw.py +10 -10
  61. odxtools/diaglayers/diaglayertype.py +1 -2
  62. odxtools/diaglayers/ecushareddata.py +4 -4
  63. odxtools/diaglayers/ecushareddataraw.py +6 -6
  64. odxtools/diaglayers/ecuvariant.py +11 -10
  65. odxtools/diaglayers/ecuvariantraw.py +9 -9
  66. odxtools/diaglayers/functionalgroup.py +8 -7
  67. odxtools/diaglayers/functionalgroupraw.py +7 -7
  68. odxtools/diaglayers/hierarchyelement.py +43 -49
  69. odxtools/diaglayers/hierarchyelementraw.py +4 -4
  70. odxtools/diaglayers/protocol.py +4 -4
  71. odxtools/diaglayers/protocolraw.py +6 -6
  72. odxtools/diagnostictroublecode.py +8 -8
  73. odxtools/diagservice.py +18 -18
  74. odxtools/diagvariable.py +14 -14
  75. odxtools/docrevision.py +11 -11
  76. odxtools/dopbase.py +6 -6
  77. odxtools/dtcconnector.py +3 -3
  78. odxtools/dtcdop.py +13 -9
  79. odxtools/dynamicendmarkerfield.py +5 -4
  80. odxtools/dynamiclengthfield.py +5 -4
  81. odxtools/dyndefinedspec.py +5 -5
  82. odxtools/dynenddopref.py +5 -5
  83. odxtools/dyniddefmodeinfo.py +13 -13
  84. odxtools/ecuvariantpattern.py +4 -5
  85. odxtools/element.py +5 -6
  86. odxtools/encodestate.py +11 -11
  87. odxtools/encoding.py +2 -3
  88. odxtools/endofpdufield.py +6 -6
  89. odxtools/envdataconnector.py +3 -3
  90. odxtools/environmentdata.py +3 -4
  91. odxtools/environmentdatadescription.py +11 -11
  92. odxtools/exceptions.py +5 -5
  93. odxtools/externalaccessmethod.py +1 -2
  94. odxtools/externaldoc.py +4 -4
  95. odxtools/field.py +9 -10
  96. odxtools/functionalclass.py +4 -4
  97. odxtools/inputparam.py +6 -6
  98. odxtools/internalconstr.py +4 -5
  99. odxtools/isotp_state_machine.py +12 -11
  100. odxtools/leadinglengthinfotype.py +2 -3
  101. odxtools/library.py +5 -5
  102. odxtools/linkeddtcdop.py +4 -4
  103. odxtools/loadfile.py +5 -6
  104. odxtools/matchingbasevariantparameter.py +2 -3
  105. odxtools/matchingparameter.py +7 -7
  106. odxtools/minmaxlengthtype.py +4 -4
  107. odxtools/modification.py +4 -4
  108. odxtools/multiplexer.py +11 -11
  109. odxtools/multiplexercase.py +6 -6
  110. odxtools/multiplexerdefaultcase.py +6 -6
  111. odxtools/multiplexerswitchkey.py +4 -4
  112. odxtools/nameditemlist.py +14 -14
  113. odxtools/negoutputparam.py +3 -3
  114. odxtools/obd.py +1 -2
  115. odxtools/odxcategory.py +6 -6
  116. odxtools/odxlink.py +19 -20
  117. odxtools/odxtypes.py +21 -18
  118. odxtools/outputparam.py +4 -4
  119. odxtools/parameterinfo.py +1 -1
  120. odxtools/parameters/codedconstparameter.py +5 -5
  121. odxtools/parameters/createanyparameter.py +1 -2
  122. odxtools/parameters/dynamicparameter.py +2 -3
  123. odxtools/parameters/lengthkeyparameter.py +5 -5
  124. odxtools/parameters/matchingrequestparameter.py +3 -4
  125. odxtools/parameters/nrcconstparameter.py +7 -7
  126. odxtools/parameters/parameter.py +11 -11
  127. odxtools/parameters/parameterwithdop.py +9 -9
  128. odxtools/parameters/physicalconstantparameter.py +4 -4
  129. odxtools/parameters/reservedparameter.py +3 -4
  130. odxtools/parameters/systemparameter.py +2 -3
  131. odxtools/parameters/tableentryparameter.py +3 -3
  132. odxtools/parameters/tablekeyparameter.py +10 -10
  133. odxtools/parameters/tablestructparameter.py +7 -7
  134. odxtools/parameters/valueparameter.py +7 -7
  135. odxtools/paramlengthinfotype.py +5 -3
  136. odxtools/parentref.py +9 -9
  137. odxtools/physicaldimension.py +11 -11
  138. odxtools/physicaltype.py +3 -4
  139. odxtools/posresponsesuppressible.py +9 -10
  140. odxtools/preconditionstateref.py +7 -7
  141. odxtools/progcode.py +6 -6
  142. odxtools/protstack.py +4 -4
  143. odxtools/relateddiagcommref.py +1 -2
  144. odxtools/relateddoc.py +6 -6
  145. odxtools/request.py +9 -9
  146. odxtools/response.py +10 -10
  147. odxtools/scaleconstr.py +3 -4
  148. odxtools/servicebinner.py +5 -5
  149. odxtools/singleecujob.py +4 -4
  150. odxtools/snrefcontext.py +2 -2
  151. odxtools/specialdata.py +5 -5
  152. odxtools/specialdatagroup.py +9 -9
  153. odxtools/specialdatagroupcaption.py +3 -3
  154. odxtools/standardlengthtype.py +10 -10
  155. odxtools/state.py +3 -3
  156. odxtools/statechart.py +4 -4
  157. odxtools/statemachine.py +4 -3
  158. odxtools/statetransition.py +4 -4
  159. odxtools/statetransitionref.py +18 -18
  160. odxtools/staticfield.py +5 -4
  161. odxtools/structure.py +2 -3
  162. odxtools/subcomponent.py +5 -5
  163. odxtools/subcomponentparamconnector.py +5 -5
  164. odxtools/subcomponentpattern.py +4 -4
  165. odxtools/swvariable.py +3 -4
  166. odxtools/table.py +14 -14
  167. odxtools/tablediagcommconnector.py +5 -5
  168. odxtools/tablerow.py +30 -30
  169. odxtools/tablerowconnector.py +3 -3
  170. odxtools/teammember.py +11 -11
  171. odxtools/text.py +2 -3
  172. odxtools/uds.py +2 -3
  173. odxtools/unit.py +9 -9
  174. odxtools/unitgroup.py +5 -5
  175. odxtools/unitspec.py +6 -6
  176. odxtools/utils.py +3 -3
  177. odxtools/variablegroup.py +2 -2
  178. odxtools/variantmatcher.py +10 -10
  179. odxtools/variantpattern.py +3 -3
  180. odxtools/version.py +2 -2
  181. odxtools/writepdxfile.py +5 -5
  182. odxtools/xdoc.py +9 -9
  183. {odxtools-9.7.0.dist-info → odxtools-10.0.0.dist-info}/METADATA +4 -5
  184. odxtools-10.0.0.dist-info/RECORD +264 -0
  185. odxtools-9.7.0.dist-info/RECORD +0 -264
  186. {odxtools-9.7.0.dist-info → odxtools-10.0.0.dist-info}/WHEEL +0 -0
  187. {odxtools-9.7.0.dist-info → odxtools-10.0.0.dist-info}/entry_points.txt +0 -0
  188. {odxtools-9.7.0.dist-info → odxtools-10.0.0.dist-info}/licenses/LICENSE +0 -0
  189. {odxtools-9.7.0.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, Optional
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -35,18 +35,18 @@ class EnvironmentDataDescription(ComplexDop):
35
35
 
36
36
  """
37
37
 
38
- param_snref: Optional[str]
39
- param_snpathref: Optional[str]
38
+ param_snref: str | None
39
+ param_snpathref: str | None
40
40
 
41
41
  # in ODX 2.0.0, ENV-DATAS seems to be a mandatory
42
42
  # sub-element of ENV-DATA-DESC, in ODX 2.2 it is not
43
43
  # present
44
44
  env_datas: NamedItemList[EnvironmentData]
45
- env_data_refs: List[OdxLinkRef]
45
+ env_data_refs: list[OdxLinkRef]
46
46
 
47
47
  @staticmethod
48
48
  def from_et(et_element: ElementTree.Element,
49
- doc_frags: List[OdxDocFragment]) -> "EnvironmentDataDescription":
49
+ doc_frags: list[OdxDocFragment]) -> "EnvironmentDataDescription":
50
50
  """Reads Environment Data Description from Diag Layer."""
51
51
  kwargs = dataclass_fields_asdict(ComplexDop.from_et(et_element, doc_frags))
52
52
 
@@ -78,7 +78,7 @@ class EnvironmentDataDescription(ComplexDop):
78
78
  env_data_refs=env_data_refs,
79
79
  **kwargs)
80
80
 
81
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
81
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
82
82
  odxlinks = {self.odx_id: self}
83
83
 
84
84
  if not self.env_data_refs:
@@ -105,7 +105,7 @@ class EnvironmentDataDescription(ComplexDop):
105
105
  ed._resolve_snrefs(context)
106
106
 
107
107
  @override
108
- def encode_into_pdu(self, physical_value: Optional[ParameterValue],
108
+ def encode_into_pdu(self, physical_value: ParameterValue | None,
109
109
  encode_state: EncodeState) -> None:
110
110
  """Convert a physical value into bytes and emplace them into a PDU.
111
111
  """
@@ -118,7 +118,7 @@ class EnvironmentDataDescription(ComplexDop):
118
118
  "descriptions via SNPATHREF is not supported yet")
119
119
  return None
120
120
 
121
- numerical_dtc_value: Optional[ParameterValue] = None
121
+ numerical_dtc_value: ParameterValue | None = None
122
122
  for prev_param, prev_param_value in reversed(encode_state.journal):
123
123
  if prev_param.short_name == self.param_snref:
124
124
  numerical_dtc_value = self._get_numerical_dtc_from_parameter(
@@ -165,7 +165,7 @@ class EnvironmentDataDescription(ComplexDop):
165
165
  "descriptions via SNPATHREF is not supported yet")
166
166
  return None
167
167
 
168
- numerical_dtc_value: Optional[ParameterValue] = None
168
+ numerical_dtc_value: ParameterValue | None = None
169
169
  for prev_param, prev_param_value in reversed(decode_state.journal):
170
170
  if prev_param.short_name == self.param_snref:
171
171
  numerical_dtc_value = self._get_numerical_dtc_from_parameter(
@@ -204,10 +204,10 @@ class EnvironmentDataDescription(ComplexDop):
204
204
  return result
205
205
 
206
206
  def _get_numerical_dtc_from_parameter(self, param: Parameter,
207
- param_value: Optional[ParameterValue]) -> int:
207
+ param_value: ParameterValue | None) -> int:
208
208
  if isinstance(param, ParameterWithDOP):
209
209
  dop = param.dop
210
- if not isinstance(dop, (DataObjectProperty, DtcDop)):
210
+ if not isinstance(dop, DataObjectProperty | DtcDop):
211
211
  odxraise(f"The DOP of the parameter referenced by environment data descriptions "
212
212
  f"must use either be DataObjectProperty or a DtcDop (encountered "
213
213
  f"{type(param).__name__} for parameter '{param.short_name}' "
odxtools/exceptions.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from typing import TYPE_CHECKING, NoReturn, Optional, Type, TypeVar
2
+ from typing import TYPE_CHECKING, NoReturn, TypeVar
3
3
 
4
4
  from .globals import logger
5
5
 
@@ -37,7 +37,7 @@ class OdxWarning(Warning):
37
37
  strict_mode = True
38
38
 
39
39
 
40
- def odxraise(message: Optional[str] = None, error_type: Type[Exception] = OdxError) -> NoReturn:
40
+ def odxraise(message: str | None = None, error_type: type[Exception] = OdxError) -> NoReturn:
41
41
  """
42
42
  Raise an exception but only if in strict mode.
43
43
 
@@ -53,8 +53,8 @@ def odxraise(message: Optional[str] = None, error_type: Type[Exception] = OdxErr
53
53
 
54
54
 
55
55
  def odxassert(condition: bool,
56
- message: Optional[str] = None,
57
- error_type: Type[Exception] = OdxError) -> None:
56
+ message: str | None = None,
57
+ error_type: type[Exception] = OdxError) -> None:
58
58
  """
59
59
  This method works similar as the build-in `assert` statement
60
60
 
@@ -72,7 +72,7 @@ def odxassert(condition: bool,
72
72
  T = TypeVar("T")
73
73
 
74
74
 
75
- def odxrequire(obj: Optional[T], message: Optional[str] = None) -> T:
75
+ def odxrequire(obj: T | None, message: str | None = None) -> T:
76
76
  """This function ensures that an object required by the ODX
77
77
  specification is actually present.
78
78
 
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from .element import IdentifiableElement
@@ -15,7 +14,7 @@ class ExternalAccessMethod(IdentifiableElement):
15
14
 
16
15
  @staticmethod
17
16
  def from_et(et_element: ElementTree.Element,
18
- doc_frags: List[OdxDocFragment]) -> "ExternalAccessMethod":
17
+ doc_frags: list[OdxDocFragment]) -> "ExternalAccessMethod":
19
18
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
20
19
 
21
20
  method = odxrequire(et_element.findtext("METHOD"))
odxtools/externaldoc.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import List, Optional
2
+ from typing import Optional
3
3
  from xml.etree import ElementTree
4
4
 
5
5
  from .exceptions import odxrequire
@@ -8,12 +8,12 @@ from .odxlink import OdxDocFragment
8
8
 
9
9
  @dataclass
10
10
  class ExternalDoc:
11
- description: Optional[str]
11
+ description: str | None
12
12
  href: str
13
13
 
14
14
  @staticmethod
15
- def from_et(et_element: Optional[ElementTree.Element],
16
- doc_frags: List[OdxDocFragment]) -> Optional["ExternalDoc"]:
15
+ def from_et(et_element: ElementTree.Element | None,
16
+ doc_frags: list[OdxDocFragment]) -> Optional["ExternalDoc"]:
17
17
  if et_element is None:
18
18
  return None
19
19
 
odxtools/field.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
@@ -15,11 +14,11 @@ from .utils import dataclass_fields_asdict
15
14
 
16
15
  @dataclass
17
16
  class Field(ComplexDop):
18
- structure_ref: Optional[OdxLinkRef]
19
- structure_snref: Optional[str]
20
- env_data_desc_ref: Optional[OdxLinkRef]
21
- env_data_desc_snref: Optional[str]
22
- is_visible_raw: Optional[bool]
17
+ structure_ref: OdxLinkRef | None
18
+ structure_snref: str | None
19
+ env_data_desc_ref: OdxLinkRef | None
20
+ env_data_desc_snref: str | None
21
+ is_visible_raw: bool | None
23
22
 
24
23
  @property
25
24
  def structure(self) -> BasicStructure:
@@ -31,7 +30,7 @@ class Field(ComplexDop):
31
30
  return self.is_visible_raw in (None, True)
32
31
 
33
32
  @staticmethod
34
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Field":
33
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "Field":
35
34
  kwargs = dataclass_fields_asdict(ComplexDop.from_et(et_element, doc_frags))
36
35
 
37
36
  structure_ref = OdxLinkRef.from_et(et_element.find("BASIC-STRUCTURE-REF"), doc_frags)
@@ -54,8 +53,8 @@ class Field(ComplexDop):
54
53
  **kwargs)
55
54
 
56
55
  def __post_init__(self) -> None:
57
- self._structure: Optional[BasicStructure] = None
58
- self._env_data_desc: Optional[EnvironmentDataDescription] = None
56
+ self._structure: BasicStructure | None = None
57
+ self._env_data_desc: EnvironmentDataDescription | None = None
59
58
  num_struct_refs = 0 if self.structure_ref is None else 1
60
59
  num_struct_refs += 0 if self.structure_snref is None else 1
61
60
 
@@ -87,5 +86,5 @@ class Field(ComplexDop):
87
86
  self._env_data_desc = resolve_snref(self.env_data_desc_snref, ddds.env_data_descs,
88
87
  EnvironmentDataDescription)
89
88
 
90
- def get_static_bit_length(self) -> Optional[int]:
89
+ def get_static_bit_length(self) -> int | None:
91
90
  return None
@@ -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
@@ -16,11 +16,11 @@ class FunctionalClass(IdentifiableElement):
16
16
  Corresponds to FUNCT-CLASS.
17
17
  """
18
18
 
19
- admin_data: Optional[AdminData]
19
+ admin_data: AdminData | None
20
20
 
21
21
  @staticmethod
22
22
  def from_et(et_element: ElementTree.Element,
23
- doc_frags: List[OdxDocFragment]) -> "FunctionalClass":
23
+ doc_frags: list[OdxDocFragment]) -> "FunctionalClass":
24
24
 
25
25
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
26
26
 
@@ -28,7 +28,7 @@ class FunctionalClass(IdentifiableElement):
28
28
 
29
29
  return FunctionalClass(admin_data=admin_data, **kwargs)
30
30
 
31
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
31
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
32
32
  return {self.odx_id: self}
33
33
 
34
34
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/inputparam.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 deprecation import deprecated
@@ -15,10 +15,10 @@ from .utils import dataclass_fields_asdict
15
15
 
16
16
  @dataclass
17
17
  class InputParam(NamedElement):
18
- physical_default_value: Optional[str]
18
+ physical_default_value: str | None
19
19
  dop_base_ref: OdxLinkRef
20
- oid: Optional[str]
21
- semantic: Optional[str]
20
+ oid: str | None
21
+ semantic: str | None
22
22
 
23
23
  @property
24
24
  def dop(self) -> DopBase:
@@ -30,7 +30,7 @@ class InputParam(NamedElement):
30
30
  return self._dop
31
31
 
32
32
  @staticmethod
33
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "InputParam":
33
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "InputParam":
34
34
  kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
35
35
 
36
36
  physical_default_value = et_element.findtext("PHYSICAL-DEFAULT-VALUE")
@@ -46,7 +46,7 @@ class InputParam(NamedElement):
46
46
  semantic=semantic,
47
47
  **kwargs)
48
48
 
49
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
49
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
50
50
  return {}
51
51
 
52
52
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
@@ -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 .compumethods.limit import Limit
@@ -16,14 +15,14 @@ class InternalConstr:
16
15
 
17
16
  # TODO: Enforce the internal and physical constraints.
18
17
 
19
- lower_limit: Optional[Limit]
20
- upper_limit: Optional[Limit]
21
- scale_constrs: List[ScaleConstr]
18
+ lower_limit: Limit | None
19
+ upper_limit: Limit | None
20
+ scale_constrs: list[ScaleConstr]
22
21
 
23
22
  value_type: DataType
24
23
 
25
24
  @staticmethod
26
- def constr_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
25
+ def constr_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
27
26
  value_type: DataType) -> "InternalConstr":
28
27
 
29
28
  lower_limit = Limit.limit_from_et(
@@ -4,9 +4,10 @@
4
4
  import asyncio
5
5
  import re
6
6
  import sys
7
+ from collections.abc import AsyncGenerator, Iterable
7
8
  from enum import IntEnum
8
9
  from io import TextIOBase
9
- from typing import AsyncGenerator, Iterable, List, Optional, TextIO, Tuple, Union
10
+ from typing import TextIO
10
11
 
11
12
  import bitstruct
12
13
  import can
@@ -32,7 +33,7 @@ class IsoTpStateMachine:
32
33
  can_fd_log_frame_re = re.compile(
33
34
  "\\([0-9.]*\\) *([a-zA-Z0-9_-]*) ([0-9A-Fa-f]+)##[0-9A-Fa-f]([0-9A-Fa-f]+)")
34
35
 
35
- def __init__(self, can_rx_ids: Union[int, List[int]]):
36
+ def __init__(self, can_rx_ids: int | list[int]):
36
37
  if isinstance(can_rx_ids, int):
37
38
  can_rx_ids = [can_rx_ids]
38
39
 
@@ -40,10 +41,10 @@ class IsoTpStateMachine:
40
41
  assert isinstance(self._can_rx_ids, list)
41
42
 
42
43
  self._telegram_specified_len = [0] * len(can_rx_ids)
43
- self._telegram_data: List[Optional[bytearray]] = [None] * len(can_rx_ids)
44
+ self._telegram_data: list[bytearray | None] = [None] * len(can_rx_ids)
44
45
  self._telegram_last_rx_fragment_idx = [0] * len(can_rx_ids)
45
46
 
46
- def decode_rx_frame(self, rx_id: int, data: bytes) -> Iterable[Tuple[int, bytes]]:
47
+ def decode_rx_frame(self, rx_id: int, data: bytes) -> Iterable[tuple[int, bytes]]:
47
48
  """Handle the ISO-TP state transitions caused by a CAN frame.
48
49
 
49
50
  E.g., add some data to a telegram, etc. Returns a generator of
@@ -114,8 +115,8 @@ class IsoTpStateMachine:
114
115
  else:
115
116
  self.on_frame_type_error(telegram_idx, frame_type)
116
117
 
117
- async def read_telegrams(self, bus: Union[can.BusABC,
118
- TextIO]) -> AsyncGenerator[Tuple[int, bytes], None]:
118
+ async def read_telegrams(self,
119
+ bus: can.BusABC | TextIO) -> AsyncGenerator[tuple[int, bytes], None]:
119
120
  """This is equivalent to the :py:meth:`file.readlines()` method, but
120
121
  it yields ISO-TP telegrams instead of lines.
121
122
 
@@ -184,7 +185,7 @@ class IsoTpStateMachine:
184
185
  """
185
186
  return self._can_rx_ids[telegram_idx]
186
187
 
187
- def telegram_data(self, telegram_idx: int) -> Optional[bytes]:
188
+ def telegram_data(self, telegram_idx: int) -> bytes | None:
188
189
  """Given a Telegram index, returns the data received for this telegram
189
190
  so far.
190
191
 
@@ -233,8 +234,8 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
233
234
 
234
235
  def __init__(self,
235
236
  can_bus: can.BusABC,
236
- can_rx_ids: List[int],
237
- can_tx_ids: List[int],
237
+ can_rx_ids: list[int],
238
+ can_tx_ids: list[int],
238
239
  padding_size: int = 0,
239
240
  padding_value: int = 0xAA):
240
241
  self._can_bus = can_bus
@@ -251,8 +252,8 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
251
252
  assert len(self._can_rx_ids) == len(self._can_tx_ids)
252
253
  assert set(self._can_rx_ids).isdisjoint(set(self._can_tx_ids)) # correct?
253
254
 
254
- self._block_size: List[Optional[int]] = [None] * len(self._can_rx_ids)
255
- self._frames_received: List[Optional[int]] = [None] * len(self._can_rx_ids)
255
+ self._block_size: list[int | None] = [None] * len(self._can_rx_ids)
256
+ self._frames_received: list[int | None] = [None] * len(self._can_rx_ids)
256
257
 
257
258
  def can_tx_id(self, telegram_idx: int) -> int:
258
259
  """Given a Telegram index, returns the CAN ID for sending data.
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from typing_extensions import override
@@ -30,7 +29,7 @@ class LeadingLengthInfoType(DiagCodedType):
30
29
  @staticmethod
31
30
  @override
32
31
  def from_et(et_element: ElementTree.Element,
33
- doc_frags: List[OdxDocFragment]) -> "LeadingLengthInfoType":
32
+ doc_frags: list[OdxDocFragment]) -> "LeadingLengthInfoType":
34
33
  kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, doc_frags))
35
34
 
36
35
  bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
@@ -53,7 +52,7 @@ class LeadingLengthInfoType(DiagCodedType):
53
52
  @override
54
53
  def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
55
54
 
56
- if not isinstance(internal_value, (str, bytes)):
55
+ if not isinstance(internal_value, str | bytes):
57
56
  odxraise(
58
57
  f"LEADING-LENGTH-INFO types can only be used for strings and byte fields, "
59
58
  f"not {type(internal_value).__name__}", EncodeError)
odxtools/library.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, cast
3
+ from typing import Any, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
@@ -19,17 +19,17 @@ class Library(IdentifiableElement):
19
19
  """
20
20
 
21
21
  code_file: str
22
- encryption: Optional[str]
22
+ encryption: str | None
23
23
  syntax: str
24
24
  revision: str
25
- entrypoint: Optional[str]
25
+ entrypoint: str | None
26
26
 
27
27
  @property
28
28
  def code(self) -> bytes:
29
29
  return self._code
30
30
 
31
31
  @staticmethod
32
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Library":
32
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "Library":
33
33
 
34
34
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
35
35
 
@@ -47,7 +47,7 @@ class Library(IdentifiableElement):
47
47
  entrypoint=entrypoint,
48
48
  **kwargs)
49
49
 
50
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
50
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
51
51
  return {self.odx_id: self}
52
52
 
53
53
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/linkeddtcdop.py CHANGED
@@ -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
3
+ from typing import TYPE_CHECKING, Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .diagnostictroublecode import DiagnosticTroubleCode
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
15
15
 
16
16
  @dataclass
17
17
  class LinkedDtcDop:
18
- not_inherited_dtc_snrefs: List[str]
18
+ not_inherited_dtc_snrefs: list[str]
19
19
  dtc_dop_ref: OdxLinkRef
20
20
 
21
21
  @property
@@ -31,7 +31,7 @@ class LinkedDtcDop:
31
31
  return self._dtc_dop.short_name
32
32
 
33
33
  @staticmethod
34
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "LinkedDtcDop":
34
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "LinkedDtcDop":
35
35
  not_inherited_dtc_snrefs = [
36
36
  odxrequire(el.get("SHORT-NAME"))
37
37
  for el in et_element.iterfind("NOT-INHERITED-DTC-SNREFS/"
@@ -43,7 +43,7 @@ class LinkedDtcDop:
43
43
  return LinkedDtcDop(
44
44
  not_inherited_dtc_snrefs=not_inherited_dtc_snrefs, dtc_dop_ref=dtc_dop_ref)
45
45
 
46
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
46
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
47
47
  return {}
48
48
 
49
49
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/loadfile.py CHANGED
@@ -1,19 +1,18 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import os
3
3
  from pathlib import Path
4
- from typing import Union
5
4
 
6
5
  from .database import Database
7
6
 
8
7
 
9
- def load_pdx_file(pdx_file: Union[str, Path]) -> Database:
8
+ def load_pdx_file(pdx_file: str | Path) -> Database:
10
9
  db = Database()
11
10
  db.add_pdx_file(str(pdx_file))
12
11
  db.refresh()
13
12
  return db
14
13
 
15
14
 
16
- def load_odx_d_file(odx_d_file_name: Union[str, Path]) -> Database:
15
+ def load_odx_d_file(odx_d_file_name: str | Path) -> Database:
17
16
  db = Database()
18
17
  db.add_odx_file(str(odx_d_file_name))
19
18
  db.refresh()
@@ -21,7 +20,7 @@ def load_odx_d_file(odx_d_file_name: Union[str, Path]) -> Database:
21
20
  return db
22
21
 
23
22
 
24
- def load_file(file_name: Union[str, Path]) -> Database:
23
+ def load_file(file_name: str | Path) -> Database:
25
24
  if str(file_name).lower().endswith(".pdx"):
26
25
  return load_pdx_file(str(file_name))
27
26
  elif str(file_name).lower().endswith(".odx-d"):
@@ -30,7 +29,7 @@ def load_file(file_name: Union[str, Path]) -> Database:
30
29
  raise RuntimeError(f"Could not guess the file format of file '{file_name}'!")
31
30
 
32
31
 
33
- def load_files(*file_names: Union[str, Path]) -> Database:
32
+ def load_files(*file_names: str | Path) -> Database:
34
33
  db = Database()
35
34
  for file_name in file_names:
36
35
  p = Path(file_name)
@@ -45,7 +44,7 @@ def load_files(*file_names: Union[str, Path]) -> Database:
45
44
  return db
46
45
 
47
46
 
48
- def load_directory(dir_name: Union[str, Path]) -> Database:
47
+ def load_directory(dir_name: str | Path) -> Database:
49
48
  db = Database()
50
49
  for file_name in os.listdir(str(dir_name)):
51
50
  p = Path(dir_name) / file_name
@@ -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 .matchingparameter import MatchingParameter
@@ -18,7 +17,7 @@ class MatchingBaseVariantParameter(MatchingParameter):
18
17
  additional subtag `USE-PHYSICAL-ADDRESSING`.
19
18
  """
20
19
 
21
- use_physical_addressing_raw: Optional[bool]
20
+ use_physical_addressing_raw: bool | None
22
21
 
23
22
  @property
24
23
  def use_physical_addressing(self) -> bool:
@@ -26,7 +25,7 @@ class MatchingBaseVariantParameter(MatchingParameter):
26
25
 
27
26
  @staticmethod
28
27
  def from_et(et_element: ElementTree.Element,
29
- doc_frags: List[OdxDocFragment]) -> "MatchingBaseVariantParameter":
28
+ doc_frags: list[OdxDocFragment]) -> "MatchingBaseVariantParameter":
30
29
 
31
30
  kwargs = dataclass_fields_asdict(MatchingParameter.from_et(et_element, doc_frags))
32
31
 
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional, cast
3
+ from typing import Any, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .diaglayers.diaglayer import DiagLayer
@@ -34,12 +34,12 @@ class MatchingParameter:
34
34
  # or negative response. What it probably actually wants to say is
35
35
  # that any response that can possibly be received shall exhibit
36
36
  # the referenced parameter.
37
- out_param_if_snref: Optional[str]
38
- out_param_if_snpathref: Optional[str]
37
+ out_param_if_snref: str | None
38
+ out_param_if_snpathref: str | None
39
39
 
40
40
  @staticmethod
41
41
  def from_et(et_element: ElementTree.Element,
42
- doc_frags: List[OdxDocFragment]) -> "MatchingParameter":
42
+ doc_frags: list[OdxDocFragment]) -> "MatchingParameter":
43
43
 
44
44
  expected_value = odxrequire(et_element.findtext("EXPECTED-VALUE"))
45
45
  diag_comm_snref = odxrequire(
@@ -61,7 +61,7 @@ class MatchingParameter:
61
61
  out_param_if_snpathref=out_param_if_snpathref,
62
62
  )
63
63
 
64
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
64
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
65
65
  return {}
66
66
 
67
67
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
@@ -93,7 +93,7 @@ class MatchingParameter:
93
93
 
94
94
  return self.__matches(param_dict, snpath_chunks)
95
95
 
96
- def __matches(self, param_dict: ParameterValue, snpath_chunks: List[str]) -> bool:
96
+ def __matches(self, param_dict: ParameterValue, snpath_chunks: list[str]) -> bool:
97
97
  if len(snpath_chunks) == 0:
98
98
  parameter_value = param_dict
99
99
  if isinstance(parameter_value, dict):
@@ -105,7 +105,7 @@ class MatchingParameter:
105
105
  # floating point
106
106
  return abs(float(self.expected_value) - parameter_value) < 1e-8
107
107
  elif isinstance(parameter_value, BytesTypes):
108
- return parameter_value.hex().upper() == self.expected_value.upper()
108
+ return bytes(parameter_value).hex().upper() == self.expected_value.upper()
109
109
  elif isinstance(parameter_value, DiagnosticTroubleCode):
110
110
  # TODO: what happens if non-numerical DTCs like
111
111
  # "U123456" are specified? Is specifying DTCs even
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional, cast
3
+ from typing import cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -18,7 +18,7 @@ from .utils import dataclass_fields_asdict
18
18
 
19
19
  @dataclass
20
20
  class MinMaxLengthType(DiagCodedType):
21
- max_length: Optional[int]
21
+ max_length: int | None
22
22
  min_length: int
23
23
  termination: Termination
24
24
 
@@ -29,7 +29,7 @@ class MinMaxLengthType(DiagCodedType):
29
29
  @staticmethod
30
30
  @override
31
31
  def from_et(et_element: ElementTree.Element,
32
- doc_frags: List[OdxDocFragment]) -> "MinMaxLengthType":
32
+ doc_frags: list[OdxDocFragment]) -> "MinMaxLengthType":
33
33
  kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, doc_frags))
34
34
 
35
35
  max_length = None
@@ -77,7 +77,7 @@ class MinMaxLengthType(DiagCodedType):
77
77
  @override
78
78
  def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
79
79
 
80
- if not isinstance(internal_value, (str, BytesTypes)):
80
+ if not isinstance(internal_value, str | BytesTypes):
81
81
  odxraise("MinMaxLengthType is currently only implemented for strings and byte arrays",
82
82
  EncodeError)
83
83
 
odxtools/modification.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 .exceptions import odxrequire
@@ -11,16 +11,16 @@ from .snrefcontext import SnRefContext
11
11
  @dataclass
12
12
  class Modification:
13
13
  change: str
14
- reason: Optional[str]
14
+ reason: str | None
15
15
 
16
16
  @staticmethod
17
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Modification":
17
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "Modification":
18
18
  change = odxrequire(et_element.findtext("CHANGE"))
19
19
  reason = et_element.findtext("REASON")
20
20
 
21
21
  return Modification(change=change, reason=reason)
22
22
 
23
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
23
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
24
24
  return {}
25
25
 
26
26
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None: