odxtools 9.6.1__py3-none-any.whl → 10.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. odxtools/additionalaudience.py +3 -3
  2. odxtools/addressing.py +8 -0
  3. odxtools/admindata.py +8 -8
  4. odxtools/audience.py +10 -10
  5. odxtools/basecomparam.py +7 -20
  6. odxtools/basevariantpattern.py +4 -5
  7. odxtools/basicstructure.py +12 -11
  8. odxtools/cli/_print_utils.py +35 -23
  9. odxtools/cli/browse.py +9 -9
  10. odxtools/cli/compare.py +24 -24
  11. odxtools/cli/decode.py +3 -4
  12. odxtools/cli/find.py +4 -5
  13. odxtools/cli/list.py +7 -7
  14. odxtools/cli/main.py +2 -2
  15. odxtools/cli/snoop.py +3 -3
  16. odxtools/codec.py +3 -186
  17. odxtools/commrelation.py +12 -19
  18. odxtools/commrelationvaluetype.py +9 -0
  19. odxtools/companydata.py +5 -5
  20. odxtools/companydocinfo.py +8 -8
  21. odxtools/companyrevisioninfo.py +5 -5
  22. odxtools/companyspecificinfo.py +5 -5
  23. odxtools/comparam.py +3 -3
  24. odxtools/comparaminstance.py +10 -10
  25. odxtools/comparamspec.py +3 -3
  26. odxtools/comparamsubset.py +5 -5
  27. odxtools/complexcomparam.py +7 -7
  28. odxtools/compositecodec.py +191 -0
  29. odxtools/compumethods/compucategory.py +13 -0
  30. odxtools/compumethods/compucodecompumethod.py +6 -5
  31. odxtools/compumethods/compuconst.py +4 -5
  32. odxtools/compumethods/compudefaultvalue.py +1 -2
  33. odxtools/compumethods/compuinternaltophys.py +6 -6
  34. odxtools/compumethods/compumethod.py +6 -17
  35. odxtools/compumethods/compuphystointernal.py +6 -6
  36. odxtools/compumethods/compurationalcoeffs.py +4 -4
  37. odxtools/compumethods/compuscale.py +9 -10
  38. odxtools/compumethods/createanycompumethod.py +1 -2
  39. odxtools/compumethods/identicalcompumethod.py +1 -2
  40. odxtools/compumethods/intervaltype.py +8 -0
  41. odxtools/compumethods/limit.py +13 -19
  42. odxtools/compumethods/linearcompumethod.py +4 -3
  43. odxtools/compumethods/linearsegment.py +14 -15
  44. odxtools/compumethods/ratfunccompumethod.py +5 -4
  45. odxtools/compumethods/ratfuncsegment.py +7 -8
  46. odxtools/compumethods/scalelinearcompumethod.py +10 -9
  47. odxtools/compumethods/scaleratfunccompumethod.py +6 -5
  48. odxtools/compumethods/tabintpcompumethod.py +19 -20
  49. odxtools/compumethods/texttablecompumethod.py +5 -4
  50. odxtools/createanycomparam.py +2 -4
  51. odxtools/createanydiagcodedtype.py +1 -2
  52. odxtools/database.py +9 -8
  53. odxtools/dataobjectproperty.py +10 -10
  54. odxtools/decodestate.py +5 -5
  55. odxtools/description.py +6 -22
  56. odxtools/determinenumberofitems.py +4 -4
  57. odxtools/diagclasstype.py +11 -0
  58. odxtools/diagcodedtype.py +7 -7
  59. odxtools/diagcomm.py +19 -42
  60. odxtools/diagdatadictionaryspec.py +6 -6
  61. odxtools/diaglayercontainer.py +4 -4
  62. odxtools/diaglayers/basevariant.py +10 -9
  63. odxtools/diaglayers/basevariantraw.py +9 -9
  64. odxtools/diaglayers/diaglayer.py +20 -19
  65. odxtools/diaglayers/diaglayerraw.py +10 -10
  66. odxtools/diaglayers/diaglayertype.py +1 -2
  67. odxtools/diaglayers/ecushareddata.py +4 -4
  68. odxtools/diaglayers/ecushareddataraw.py +6 -6
  69. odxtools/diaglayers/ecuvariant.py +11 -10
  70. odxtools/diaglayers/ecuvariantraw.py +9 -9
  71. odxtools/diaglayers/functionalgroup.py +8 -7
  72. odxtools/diaglayers/functionalgroupraw.py +7 -7
  73. odxtools/diaglayers/hierarchyelement.py +43 -49
  74. odxtools/diaglayers/hierarchyelementraw.py +4 -4
  75. odxtools/diaglayers/protocol.py +4 -4
  76. odxtools/diaglayers/protocolraw.py +6 -6
  77. odxtools/diagnostictroublecode.py +8 -8
  78. odxtools/diagservice.py +21 -97
  79. odxtools/diagvariable.py +14 -14
  80. odxtools/docrevision.py +11 -11
  81. odxtools/dopbase.py +6 -6
  82. odxtools/dtcconnector.py +45 -0
  83. odxtools/dtcdop.py +15 -56
  84. odxtools/dynamicendmarkerfield.py +5 -4
  85. odxtools/dynamiclengthfield.py +5 -4
  86. odxtools/dyndefinedspec.py +7 -159
  87. odxtools/dynenddopref.py +5 -5
  88. odxtools/dyniddefmodeinfo.py +161 -0
  89. odxtools/ecuvariantpattern.py +4 -5
  90. odxtools/element.py +5 -6
  91. odxtools/encodestate.py +11 -11
  92. odxtools/encoding.py +2 -3
  93. odxtools/endofpdufield.py +6 -6
  94. odxtools/envdataconnector.py +49 -0
  95. odxtools/environmentdata.py +3 -4
  96. odxtools/environmentdatadescription.py +11 -11
  97. odxtools/exceptions.py +5 -5
  98. odxtools/externalaccessmethod.py +22 -0
  99. odxtools/externaldoc.py +23 -0
  100. odxtools/field.py +9 -10
  101. odxtools/functionalclass.py +4 -4
  102. odxtools/inputparam.py +6 -6
  103. odxtools/internalconstr.py +4 -5
  104. odxtools/isotp_state_machine.py +12 -11
  105. odxtools/leadinglengthinfotype.py +2 -3
  106. odxtools/library.py +5 -5
  107. odxtools/linkeddtcdop.py +62 -0
  108. odxtools/loadfile.py +5 -6
  109. odxtools/matchingbasevariantparameter.py +2 -3
  110. odxtools/matchingparameter.py +7 -7
  111. odxtools/minmaxlengthtype.py +5 -11
  112. odxtools/modification.py +4 -4
  113. odxtools/multiplexer.py +11 -11
  114. odxtools/multiplexercase.py +6 -6
  115. odxtools/multiplexerdefaultcase.py +6 -6
  116. odxtools/multiplexerswitchkey.py +4 -4
  117. odxtools/nameditemlist.py +14 -14
  118. odxtools/negoutputparam.py +3 -3
  119. odxtools/obd.py +1 -2
  120. odxtools/odxcategory.py +6 -6
  121. odxtools/odxlink.py +19 -20
  122. odxtools/odxtypes.py +21 -18
  123. odxtools/outputparam.py +4 -4
  124. odxtools/parameterinfo.py +2 -2
  125. odxtools/parameters/codedconstparameter.py +5 -5
  126. odxtools/parameters/createanyparameter.py +1 -2
  127. odxtools/parameters/dynamicparameter.py +2 -3
  128. odxtools/parameters/lengthkeyparameter.py +5 -5
  129. odxtools/parameters/matchingrequestparameter.py +3 -4
  130. odxtools/parameters/nrcconstparameter.py +7 -7
  131. odxtools/parameters/parameter.py +11 -11
  132. odxtools/parameters/parameterwithdop.py +9 -9
  133. odxtools/parameters/physicalconstantparameter.py +4 -4
  134. odxtools/parameters/reservedparameter.py +3 -4
  135. odxtools/parameters/rowfragment.py +7 -0
  136. odxtools/parameters/systemparameter.py +2 -3
  137. odxtools/parameters/tableentryparameter.py +4 -9
  138. odxtools/parameters/tablekeyparameter.py +10 -10
  139. odxtools/parameters/tablestructparameter.py +7 -7
  140. odxtools/parameters/valueparameter.py +7 -7
  141. odxtools/paramlengthinfotype.py +5 -3
  142. odxtools/parentref.py +9 -9
  143. odxtools/physicaldimension.py +11 -11
  144. odxtools/physicaltype.py +4 -12
  145. odxtools/posresponsesuppressible.py +72 -0
  146. odxtools/preconditionstateref.py +7 -7
  147. odxtools/progcode.py +6 -6
  148. odxtools/protstack.py +4 -4
  149. odxtools/radix.py +9 -0
  150. odxtools/relateddiagcommref.py +22 -0
  151. odxtools/relateddoc.py +6 -6
  152. odxtools/request.py +14 -12
  153. odxtools/response.py +15 -13
  154. odxtools/scaleconstr.py +4 -12
  155. odxtools/servicebinner.py +5 -5
  156. odxtools/singleecujob.py +4 -4
  157. odxtools/snrefcontext.py +2 -2
  158. odxtools/specialdata.py +5 -5
  159. odxtools/specialdatagroup.py +9 -9
  160. odxtools/specialdatagroupcaption.py +3 -3
  161. odxtools/standardizationlevel.py +9 -0
  162. odxtools/standardlengthtype.py +12 -21
  163. odxtools/state.py +3 -3
  164. odxtools/statechart.py +4 -4
  165. odxtools/statemachine.py +4 -3
  166. odxtools/statetransition.py +5 -18
  167. odxtools/statetransitionref.py +18 -18
  168. odxtools/staticfield.py +5 -4
  169. odxtools/structure.py +2 -3
  170. odxtools/subcomponent.py +12 -245
  171. odxtools/subcomponentparamconnector.py +103 -0
  172. odxtools/subcomponentpattern.py +42 -0
  173. odxtools/swvariable.py +3 -4
  174. odxtools/table.py +17 -55
  175. odxtools/tablediagcommconnector.py +47 -0
  176. odxtools/tablerow.py +30 -30
  177. odxtools/tablerowconnector.py +46 -0
  178. odxtools/teammember.py +11 -11
  179. odxtools/templates/macros/printService.xml.jinja2 +2 -1
  180. odxtools/termination.py +8 -0
  181. odxtools/text.py +2 -3
  182. odxtools/transmode.py +9 -0
  183. odxtools/uds.py +2 -3
  184. odxtools/unit.py +9 -9
  185. odxtools/unitgroup.py +6 -11
  186. odxtools/unitgroupcategory.py +7 -0
  187. odxtools/unitspec.py +6 -6
  188. odxtools/usage.py +9 -0
  189. odxtools/utils.py +31 -2
  190. odxtools/validtype.py +9 -0
  191. odxtools/variablegroup.py +2 -2
  192. odxtools/variantmatcher.py +10 -10
  193. odxtools/variantpattern.py +3 -3
  194. odxtools/version.py +2 -2
  195. odxtools/writepdxfile.py +5 -5
  196. odxtools/xdoc.py +9 -9
  197. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/METADATA +4 -5
  198. odxtools-10.0.0.dist-info/RECORD +264 -0
  199. odxtools-9.6.1.dist-info/RECORD +0 -238
  200. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/WHEEL +0 -0
  201. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/entry_points.txt +0 -0
  202. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/licenses/LICENSE +0 -0
  203. {odxtools-9.6.1.dist-info → odxtools-10.0.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .dataobjectproperty import DataObjectProperty
@@ -15,7 +15,7 @@ class MultiplexerSwitchKey:
15
15
  The object that determines the case to be used by a multiplexer
16
16
  """
17
17
  byte_position: int
18
- bit_position: Optional[int]
18
+ bit_position: int | None
19
19
  dop_ref: OdxLinkRef
20
20
 
21
21
  @property
@@ -24,7 +24,7 @@ class MultiplexerSwitchKey:
24
24
 
25
25
  @staticmethod
26
26
  def from_et(et_element: ElementTree.Element,
27
- doc_frags: List[OdxDocFragment]) -> "MultiplexerSwitchKey":
27
+ doc_frags: list[OdxDocFragment]) -> "MultiplexerSwitchKey":
28
28
  byte_position = int(odxrequire(et_element.findtext("BYTE-POSITION")))
29
29
  bit_position_str = et_element.findtext("BIT-POSITION")
30
30
  bit_position = int(bit_position_str) if bit_position_str is not None else None
@@ -36,7 +36,7 @@ class MultiplexerSwitchKey:
36
36
  dop_ref=dop_ref,
37
37
  )
38
38
 
39
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
39
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
40
40
  return {}
41
41
 
42
42
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/nameditemlist.py CHANGED
@@ -1,10 +1,10 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import abc
3
3
  import typing
4
+ from collections.abc import Collection, Iterable
4
5
  from copy import deepcopy
5
6
  from keyword import iskeyword
6
- from typing import (Any, Collection, Dict, Iterable, List, Optional, SupportsIndex, Tuple, TypeVar,
7
- Union, cast, overload, runtime_checkable)
7
+ from typing import Any, SupportsIndex, TypeVar, cast, overload, runtime_checkable
8
8
 
9
9
  from .exceptions import odxraise
10
10
 
@@ -21,7 +21,7 @@ T = TypeVar("T")
21
21
  TNamed = TypeVar("TNamed", bound=OdxNamed)
22
22
 
23
23
 
24
- class ItemAttributeList(List[T]):
24
+ class ItemAttributeList(list[T]):
25
25
  """A list that provides direct access to its items as named attributes.
26
26
 
27
27
  This is a hybrid between a list and a user-defined object: One can
@@ -35,8 +35,8 @@ class ItemAttributeList(List[T]):
35
35
  returned by the item-to-name function are valid identifiers in python.
36
36
  """
37
37
 
38
- def __init__(self, input_list: Optional[Iterable[T]] = None) -> None:
39
- self._item_dict: Dict[str, T] = {}
38
+ def __init__(self, input_list: Iterable[T] | None = None) -> None:
39
+ self._item_dict: dict[str, T] = {}
40
40
 
41
41
  if input_list is not None:
42
42
  for item in input_list:
@@ -121,10 +121,10 @@ class ItemAttributeList(List[T]):
121
121
  def values(self) -> Collection[T]:
122
122
  return self._item_dict.values()
123
123
 
124
- def items(self) -> Collection[Tuple[str, T]]:
124
+ def items(self) -> Collection[tuple[str, T]]:
125
125
  return self._item_dict.items()
126
126
 
127
- def __dir__(self) -> Dict[str, Any]:
127
+ def __dir__(self) -> dict[str, Any]:
128
128
  result = dict(self.__dict__)
129
129
  result.update(self._item_dict)
130
130
  return result
@@ -138,11 +138,11 @@ class ItemAttributeList(List[T]):
138
138
  ...
139
139
 
140
140
  @overload
141
- def __getitem__(self, key: slice) -> List[T]:
141
+ def __getitem__(self, key: slice) -> list[T]:
142
142
  ...
143
143
 
144
- def __getitem__(self, key: Union[SupportsIndex, str, slice]) -> Union[T, List[T]]:
145
- if isinstance(key, (SupportsIndex, slice)):
144
+ def __getitem__(self, key: SupportsIndex | str | slice) -> T | list[T]:
145
+ if isinstance(key, SupportsIndex | slice):
146
146
  return super().__getitem__(key)
147
147
  else:
148
148
  return self._item_dict[key]
@@ -153,13 +153,13 @@ class ItemAttributeList(List[T]):
153
153
 
154
154
  return self._item_dict[key]
155
155
 
156
- def get(self, key: Union[int, str], default: Optional[T] = None) -> Optional[T]:
156
+ def get(self, key: int | str, default: T | None = None) -> T | None:
157
157
  if isinstance(key, int):
158
158
  if 0 <= key and key < len(self):
159
159
  return super().__getitem__(key)
160
160
  return default
161
161
  else:
162
- return cast(Optional[T], self._item_dict.get(key, default))
162
+ return cast(T | None, self._item_dict.get(key, default))
163
163
 
164
164
  def __eq__(self, other: object) -> bool:
165
165
  """
@@ -179,7 +179,7 @@ class ItemAttributeList(List[T]):
179
179
  def __copy__(self) -> Any:
180
180
  return self.__class__(list(self))
181
181
 
182
- def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
182
+ def __deepcopy__(self, memo: dict[int, Any]) -> Any:
183
183
  cls = self.__class__
184
184
  result = cls.__new__(cls)
185
185
  memo[id(self)] = result
@@ -189,7 +189,7 @@ class ItemAttributeList(List[T]):
189
189
 
190
190
  return result
191
191
 
192
- def __reduce__(self) -> Tuple[Any, ...]:
192
+ def __reduce__(self) -> tuple[Any, ...]:
193
193
  """Support for Python's pickle protocol.
194
194
  This method ensures that the object can be reconstructed with its current state,
195
195
  using its class and the list of items it contains.
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List
3
+ from typing import Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .dopbase import DopBase
@@ -22,14 +22,14 @@ class NegOutputParam(NamedElement):
22
22
 
23
23
  @staticmethod
24
24
  def from_et(et_element: ElementTree.Element,
25
- doc_frags: List[OdxDocFragment]) -> "NegOutputParam":
25
+ doc_frags: list[OdxDocFragment]) -> "NegOutputParam":
26
26
 
27
27
  kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
28
28
  dop_base_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DOP-BASE-REF"), doc_frags))
29
29
 
30
30
  return NegOutputParam(dop_base_ref=dop_base_ref, **kwargs)
31
31
 
32
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
32
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
33
33
  return {}
34
34
 
35
35
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/obd.py CHANGED
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from enum import IntEnum
3
- from typing import Optional
4
3
 
5
4
 
6
5
  class SID(IntEnum):
@@ -47,7 +46,7 @@ _sid_to_name = {
47
46
  }
48
47
 
49
48
 
50
- def sid_to_name(sid: int) -> Optional[str]:
49
+ def sid_to_name(sid: int) -> str | None:
51
50
  if sid in _sid_to_name:
52
51
  return _sid_to_name[sid]
53
52
 
odxtools/odxcategory.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, Optional
3
+ from typing import TYPE_CHECKING, Any
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .admindata import AdminData
@@ -21,17 +21,17 @@ if TYPE_CHECKING:
21
21
  class OdxCategory(IdentifiableElement):
22
22
  """This is the base class for all top-level container classes in ODX"""
23
23
 
24
- admin_data: Optional[AdminData]
24
+ admin_data: AdminData | None
25
25
  company_datas: NamedItemList[CompanyData]
26
- sdgs: List[SpecialDataGroup]
26
+ sdgs: list[SpecialDataGroup]
27
27
 
28
28
  @staticmethod
29
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "OdxCategory":
29
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "OdxCategory":
30
30
  raise Exception("Calling `._from_et()` is not allowed for OdxCategory. "
31
31
  "Use `OdxCategory.category_from_et()`!")
32
32
 
33
33
  @staticmethod
34
- def category_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
34
+ def category_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
35
35
  doc_type: DocType) -> "OdxCategory":
36
36
 
37
37
  short_name = odxrequire(et_element.findtext("SHORT-NAME"))
@@ -51,7 +51,7 @@ class OdxCategory(IdentifiableElement):
51
51
 
52
52
  return OdxCategory(admin_data=admin_data, company_datas=company_datas, sdgs=sdgs, **kwargs)
53
53
 
54
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
54
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
55
55
  result = {self.odx_id: self}
56
56
 
57
57
  if self.admin_data is not None:
odxtools/odxlink.py CHANGED
@@ -1,8 +1,9 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import warnings
3
+ from collections.abc import Iterable
3
4
  from dataclasses import dataclass
4
5
  from enum import Enum
5
- from typing import Any, Dict, Iterable, List, Optional, Type, TypeVar, overload
6
+ from typing import Any, Optional, TypeVar, overload
6
7
  from xml.etree import ElementTree
7
8
 
8
9
  from .exceptions import OdxWarning, odxassert, odxraise, odxrequire
@@ -44,7 +45,7 @@ class OdxLinkId:
44
45
 
45
46
  #: The name and type of the document fragment to which the
46
47
  #: `local_id` is relative to
47
- doc_fragments: List[OdxDocFragment]
48
+ doc_fragments: list[OdxDocFragment]
48
49
 
49
50
  def __hash__(self) -> int:
50
51
  # we do not hash about the document fragment here, because
@@ -68,7 +69,7 @@ class OdxLinkId:
68
69
 
69
70
  @staticmethod
70
71
  def from_et(et: ElementTree.Element,
71
- doc_fragments: List[OdxDocFragment]) -> Optional["OdxLinkId"]:
72
+ doc_fragments: list[OdxDocFragment]) -> Optional["OdxLinkId"]:
72
73
  """Construct an OdxLinkId for a given XML node (ElementTree object).
73
74
 
74
75
  Returns None if the given XML node does not exhibit an ID.
@@ -94,7 +95,7 @@ class OdxLinkRef:
94
95
  ref_id: str
95
96
 
96
97
  #: The document fragments to which the `ref_id` refers to (in reverse order)
97
- ref_docs: List[OdxDocFragment]
98
+ ref_docs: list[OdxDocFragment]
98
99
 
99
100
  # TODO: this is difficult because OdxLinkRef is derived from and
100
101
  # we do not want having to specify it mandatorily
@@ -102,17 +103,17 @@ class OdxLinkRef:
102
103
 
103
104
  @overload
104
105
  @staticmethod
105
- def from_et(et: None, source_doc_frags: List[OdxDocFragment]) -> None:
106
+ def from_et(et: None, source_doc_frags: list[OdxDocFragment]) -> None:
106
107
  ...
107
108
 
108
109
  @overload
109
110
  @staticmethod
110
- def from_et(et: ElementTree.Element, source_doc_frags: List[OdxDocFragment]) -> "OdxLinkRef":
111
+ def from_et(et: ElementTree.Element, source_doc_frags: list[OdxDocFragment]) -> "OdxLinkRef":
111
112
  ...
112
113
 
113
114
  @staticmethod
114
- def from_et(et: Optional[ElementTree.Element],
115
- source_doc_frags: List[OdxDocFragment]) -> Optional["OdxLinkRef"]:
115
+ def from_et(et: ElementTree.Element | None,
116
+ source_doc_frags: list[OdxDocFragment]) -> Optional["OdxLinkRef"]:
116
117
  """Construct an OdxLinkRef for a given XML node (ElementTree object).
117
118
 
118
119
  Returns None if the given XML node does not represent a reference.
@@ -170,17 +171,17 @@ class OdxLinkDatabase:
170
171
  """
171
172
 
172
173
  def __init__(self) -> None:
173
- self._db: Dict[OdxDocFragment, Dict[str, Any]] = {}
174
+ self._db: dict[OdxDocFragment, dict[str, Any]] = {}
174
175
 
175
176
  @overload
176
177
  def resolve(self, ref: OdxLinkRef, expected_type: None = None) -> Any:
177
178
  ...
178
179
 
179
180
  @overload
180
- def resolve(self, ref: OdxLinkRef, expected_type: Type[T]) -> T:
181
+ def resolve(self, ref: OdxLinkRef, expected_type: type[T]) -> T:
181
182
  ...
182
183
 
183
- def resolve(self, ref: OdxLinkRef, expected_type: Optional[Any] = None) -> Any:
184
+ def resolve(self, ref: OdxLinkRef, expected_type: Any | None = None) -> Any:
184
185
  """
185
186
  Resolve a reference to an object
186
187
 
@@ -219,12 +220,10 @@ class OdxLinkDatabase:
219
220
  ...
220
221
 
221
222
  @overload
222
- def resolve_lenient(self, ref: OdxLinkRef, expected_type: Type[T]) -> Optional[T]:
223
+ def resolve_lenient(self, ref: OdxLinkRef, expected_type: type[T]) -> T | None:
223
224
  ...
224
225
 
225
- def resolve_lenient(self,
226
- ref: OdxLinkRef,
227
- expected_type: Optional[Any] = None) -> Optional[Any]:
226
+ def resolve_lenient(self, ref: OdxLinkRef, expected_type: Any | None = None) -> Any | None:
228
227
  """
229
228
  Resolve a reference to an object
230
229
 
@@ -254,7 +253,7 @@ class OdxLinkDatabase:
254
253
 
255
254
  return None
256
255
 
257
- def update(self, new_entries: Dict[OdxLinkId, Any], *, overwrite: bool = True) -> None:
256
+ def update(self, new_entries: dict[OdxLinkId, Any], *, overwrite: bool = True) -> None:
258
257
  """
259
258
  Add a bunch of new objects to the ODXLINK database.
260
259
 
@@ -287,7 +286,7 @@ def resolve_snref(target_short_name: str,
287
286
  @overload
288
287
  def resolve_snref(target_short_name: str,
289
288
  items: Iterable[OdxNamed],
290
- expected_type: Type[TNamed],
289
+ expected_type: type[TNamed],
291
290
  *,
292
291
  lenient: None = None) -> TNamed:
293
292
  ...
@@ -296,16 +295,16 @@ def resolve_snref(target_short_name: str,
296
295
  @overload
297
296
  def resolve_snref(target_short_name: str,
298
297
  items: Iterable[OdxNamed],
299
- expected_type: Type[TNamed],
298
+ expected_type: type[TNamed],
300
299
  *,
301
- lenient: bool = True) -> Optional[TNamed]:
300
+ lenient: bool = True) -> TNamed | None:
302
301
  ...
303
302
 
304
303
 
305
304
  def resolve_snref(target_short_name: str,
306
305
  items: Iterable[OdxNamed],
307
306
  expected_type: Any = None,
308
- lenient: Optional[bool] = None) -> Any:
307
+ lenient: bool | None = None) -> Any:
309
308
  candidates = [x for x in items if x.short_name == target_short_name]
310
309
 
311
310
  if not candidates:
odxtools/odxtypes.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ from collections.abc import Callable, Iterable
2
3
  from enum import Enum
3
- from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Optional, SupportsBytes, Tuple,
4
- Type, Union, overload)
4
+ from typing import TYPE_CHECKING, Any, SupportsBytes, Union, overload
5
5
  from xml.etree import ElementTree
6
6
 
7
7
  from .exceptions import odxassert, odxraise, odxrequire
@@ -16,22 +16,22 @@ def bytefield_to_bytearray(bytefield: str) -> bytearray:
16
16
  return bytearray([int(x, 16) for x in bytes_string])
17
17
 
18
18
 
19
- BytesTypes = (bytearray, bytes, SupportsBytes)
20
- AtomicOdxType = Union[str, int, float, bytearray, bytes]
19
+ BytesTypes = bytearray | bytes | SupportsBytes
20
+ AtomicOdxType = str | int | float | BytesTypes
21
21
 
22
22
  # dictionary mapping short names to a Parameter that needs to be
23
23
  # specified. Complex parameters (structures) may contain
24
24
  # sub-parameters, so this is a recursive type...
25
- ParameterDict = Dict[str, Union["Parameter", "ParameterDict"]]
25
+ ParameterDict = dict[str, Union["Parameter", "ParameterDict"]]
26
26
 
27
27
  # Dictionary mapping short names of parameters to the value it
28
28
  # exhibits. Complex parameters (structures) may contain
29
29
  # sub-parameters, so this is a recursive type, and fields encompass
30
30
  # multiple items, so this can be a list of objects.
31
- TableStructParameterValue = Tuple[str, "ParameterValue"]
31
+ TableStructParameterValue = tuple[str, "ParameterValue"]
32
32
  ParameterValue = Union[AtomicOdxType, "ParameterValueDict", TableStructParameterValue,
33
33
  Iterable["ParameterValue"], "DiagnosticTroubleCode"]
34
- ParameterValueDict = Dict[str, ParameterValue]
34
+ ParameterValueDict = dict[str, ParameterValue]
35
35
 
36
36
 
37
37
  @overload
@@ -44,7 +44,7 @@ def odxstr_to_bool(str_val: str) -> bool:
44
44
  ...
45
45
 
46
46
 
47
- def odxstr_to_bool(str_val: Optional[str]) -> Optional[bool]:
47
+ def odxstr_to_bool(str_val: str | None) -> bool | None:
48
48
  if str_val is None:
49
49
  return None
50
50
 
@@ -79,7 +79,7 @@ def parse_int(value: str) -> int:
79
79
 
80
80
  #: conversion functions for strings from the XML to the types stored
81
81
  #: by the internalized database
82
- _PARSE_ODX_TYPE: Dict[str, Callable[[str], AtomicOdxType]] = {
82
+ _PARSE_ODX_TYPE: dict[str, Callable[[str], AtomicOdxType]] = {
83
83
  "A_INT32": parse_int,
84
84
  "A_UINT32": parse_int,
85
85
  "A_FLOAT32": float,
@@ -92,7 +92,7 @@ _PARSE_ODX_TYPE: Dict[str, Callable[[str], AtomicOdxType]] = {
92
92
 
93
93
  #: mapping from type name strings specified by the XML to the types
94
94
  #: used by the internalized database
95
- _ODX_TYPE_TO_PYTHON_TYPE: Dict[str, Type[AtomicOdxType]] = {
95
+ _ODX_TYPE_TO_PYTHON_TYPE: dict[str, type[int | float | str | bytearray]] = {
96
96
  "A_INT32": int,
97
97
  "A_UINT32": int,
98
98
  "A_FLOAT32": float,
@@ -109,8 +109,8 @@ def compare_odx_values(a: AtomicOdxType, b: AtomicOdxType) -> int:
109
109
  # specification. (cf section 7.3.6.5)
110
110
 
111
111
  # numeric values are compared numerically (duh!)
112
- if isinstance(a, (int, float)):
113
- if not isinstance(b, (int, float)):
112
+ if isinstance(a, int | float):
113
+ if not isinstance(b, int | float):
114
114
  odxraise()
115
115
 
116
116
  tmp = a - b
@@ -140,10 +140,13 @@ def compare_odx_values(a: AtomicOdxType, b: AtomicOdxType) -> int:
140
140
  if not isinstance(b, BytesTypes):
141
141
  odxraise()
142
142
 
143
- obj_len = max(len(a), len(b))
143
+ a_bytes = bytes(a)
144
+ b_bytes = bytes(b)
144
145
 
145
- tmp_a = a.ljust(obj_len, b'\x00')
146
- tmp_b = b.ljust(obj_len, b'\x00')
146
+ obj_len = max(len(a_bytes), len(b_bytes))
147
+
148
+ tmp_a = a_bytes.ljust(obj_len, b'\x00')
149
+ tmp_b = b_bytes.ljust(obj_len, b'\x00')
147
150
 
148
151
  if tmp_a > tmp_b:
149
152
  return 1
@@ -193,7 +196,7 @@ class DataType(Enum):
193
196
  A_UTF8STRING = "A_UTF8STRING"
194
197
 
195
198
  @property
196
- def python_type(self) -> Type[AtomicOdxType]:
199
+ def python_type(self) -> type[int | float | str | bytearray]:
197
200
  return _ODX_TYPE_TO_PYTHON_TYPE[self.value]
198
201
 
199
202
  @property
@@ -211,7 +214,7 @@ class DataType(Enum):
211
214
  def create_from_et(self, et_element: ElementTree.Element) -> AtomicOdxType:
212
215
  ...
213
216
 
214
- def create_from_et(self, et_element: Optional[ElementTree.Element]) -> Optional[AtomicOdxType]:
217
+ def create_from_et(self, et_element: ElementTree.Element | None) -> AtomicOdxType | None:
215
218
  """
216
219
  Parse a V/VT value union and return an AtomicOdxType from them that match current datatype
217
220
  this includes, but not limited to COMPU-CONST, COMPU-DEFAULT-VALUE, COMPU-INVERSE-VALUE
@@ -236,7 +239,7 @@ class DataType(Enum):
236
239
  expected_type = self.python_type
237
240
  if isinstance(value, expected_type):
238
241
  return True
239
- elif expected_type is float and isinstance(value, (int, float)):
242
+ elif expected_type is float and isinstance(value, int | float):
240
243
  return True
241
244
  elif self == DataType.A_BYTEFIELD and isinstance(value, BytesTypes):
242
245
  return True
odxtools/outputparam.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
@@ -16,7 +16,7 @@ from .utils import dataclass_fields_asdict
16
16
  @dataclass
17
17
  class OutputParam(IdentifiableElement):
18
18
  dop_base_ref: OdxLinkRef
19
- semantic: Optional[str]
19
+ semantic: str | None
20
20
 
21
21
  @property
22
22
  def dop(self) -> DopBase:
@@ -27,7 +27,7 @@ class OutputParam(IdentifiableElement):
27
27
  return self._dop
28
28
 
29
29
  @staticmethod
30
- def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "OutputParam":
30
+ def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "OutputParam":
31
31
 
32
32
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
33
33
 
@@ -36,7 +36,7 @@ class OutputParam(IdentifiableElement):
36
36
 
37
37
  return OutputParam(dop_base_ref=dop_base_ref, semantic=semantic, **kwargs)
38
38
 
39
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
39
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
40
40
  return {}
41
41
 
42
42
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
odxtools/parameterinfo.py CHANGED
@@ -1,11 +1,11 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import textwrap
3
+ from collections.abc import Iterable
3
4
  from io import StringIO
4
- from typing import Iterable
5
5
 
6
6
  from .compumethods.compucodecompumethod import CompuCodeCompuMethod
7
7
  from .compumethods.identicalcompumethod import IdenticalCompuMethod
8
- from .compumethods.limit import IntervalType
8
+ from .compumethods.intervaltype import IntervalType
9
9
  from .compumethods.linearcompumethod import LinearCompuMethod
10
10
  from .compumethods.linearsegment import LinearSegment
11
11
  from .compumethods.ratfunccompumethod import RatFuncCompuMethod
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import warnings
3
3
  from dataclasses import dataclass
4
- from typing import Any, Dict, List, Optional, cast
4
+ from typing import Any, cast
5
5
  from xml.etree import ElementTree
6
6
 
7
7
  from typing_extensions import override
@@ -45,7 +45,7 @@ class CodedConstParameter(Parameter):
45
45
  @staticmethod
46
46
  @override
47
47
  def from_et(et_element: ElementTree.Element,
48
- doc_frags: List[OdxDocFragment]) -> "CodedConstParameter":
48
+ doc_frags: list[OdxDocFragment]) -> "CodedConstParameter":
49
49
 
50
50
  kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
51
51
 
@@ -61,7 +61,7 @@ class CodedConstParameter(Parameter):
61
61
  AtomicOdxType, self.diag_coded_type.base_data_type.from_string(self.coded_value_raw))
62
62
 
63
63
  @override
64
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
64
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
65
65
  result = super()._build_odxlinks()
66
66
 
67
67
  result.update(self.diag_coded_type._build_odxlinks())
@@ -69,7 +69,7 @@ class CodedConstParameter(Parameter):
69
69
  return result
70
70
 
71
71
  @override
72
- def get_static_bit_length(self) -> Optional[int]:
72
+ def get_static_bit_length(self) -> int | None:
73
73
  return self.diag_coded_type.get_static_bit_length()
74
74
 
75
75
  @property
@@ -77,7 +77,7 @@ class CodedConstParameter(Parameter):
77
77
  return self.diag_coded_type.base_data_type
78
78
 
79
79
  @override
80
- def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
80
+ def _encode_positioned_into_pdu(self, physical_value: ParameterValue | None,
81
81
  encode_state: EncodeState) -> None:
82
82
  if physical_value is not None and physical_value != self.coded_value:
83
83
  odxraise(
@@ -1,5 +1,4 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from typing import List
3
2
  from xml.etree import ElementTree
4
3
 
5
4
  from ..exceptions import odxraise
@@ -21,7 +20,7 @@ from .valueparameter import ValueParameter
21
20
 
22
21
 
23
22
  def create_any_parameter_from_et(et_element: ElementTree.Element,
24
- doc_frags: List[OdxDocFragment]) \
23
+ doc_frags: list[OdxDocFragment]) \
25
24
  -> Parameter:
26
25
  parameter_type = et_element.get(f"{xsi}type")
27
26
 
@@ -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 typing_extensions import override
@@ -34,14 +33,14 @@ class DynamicParameter(Parameter):
34
33
  @staticmethod
35
34
  @override
36
35
  def from_et(et_element: ElementTree.Element,
37
- doc_frags: List[OdxDocFragment]) -> "DynamicParameter":
36
+ doc_frags: list[OdxDocFragment]) -> "DynamicParameter":
38
37
 
39
38
  kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
40
39
 
41
40
  return DynamicParameter(**kwargs)
42
41
 
43
42
  @override
44
- def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
43
+ def _encode_positioned_into_pdu(self, physical_value: ParameterValue | None,
45
44
  encode_state: EncodeState) -> None:
46
45
  raise NotImplementedError("Encoding DynamicParameter is not implemented yet.")
47
46
 
@@ -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 final, override
@@ -49,7 +49,7 @@ class LengthKeyParameter(ParameterWithDOP):
49
49
  @staticmethod
50
50
  @override
51
51
  def from_et(et_element: ElementTree.Element,
52
- doc_frags: List[OdxDocFragment]) -> "LengthKeyParameter":
52
+ doc_frags: list[OdxDocFragment]) -> "LengthKeyParameter":
53
53
 
54
54
  kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
55
55
 
@@ -58,7 +58,7 @@ class LengthKeyParameter(ParameterWithDOP):
58
58
  return LengthKeyParameter(odx_id=odx_id, **kwargs)
59
59
 
60
60
  @override
61
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
61
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
62
62
  result = super()._build_odxlinks()
63
63
 
64
64
  result[self.odx_id] = self
@@ -67,7 +67,7 @@ class LengthKeyParameter(ParameterWithDOP):
67
67
 
68
68
  @override
69
69
  @final
70
- def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
70
+ def _encode_positioned_into_pdu(self, physical_value: ParameterValue | None,
71
71
  encode_state: EncodeState) -> None:
72
72
  # if you get this exception, you ought to use
73
73
  # `.encode_placeholder_into_pdu()` followed by (after the
@@ -75,7 +75,7 @@ class LengthKeyParameter(ParameterWithDOP):
75
75
  # `.encode_value_into_pdu()`.
76
76
  raise RuntimeError("_encode_positioned_into_pdu() cannot be called for length keys.")
77
77
 
78
- def encode_placeholder_into_pdu(self, physical_value: Optional[ParameterValue],
78
+ def encode_placeholder_into_pdu(self, physical_value: ParameterValue | None,
79
79
  encode_state: EncodeState) -> None:
80
80
 
81
81
  if physical_value is not 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 typing_extensions import override
@@ -37,7 +36,7 @@ class MatchingRequestParameter(Parameter):
37
36
  @staticmethod
38
37
  @override
39
38
  def from_et(et_element: ElementTree.Element,
40
- doc_frags: List[OdxDocFragment]) -> "MatchingRequestParameter":
39
+ doc_frags: list[OdxDocFragment]) -> "MatchingRequestParameter":
41
40
 
42
41
  kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
43
42
 
@@ -48,11 +47,11 @@ class MatchingRequestParameter(Parameter):
48
47
  request_byte_position=request_byte_position, byte_length=byte_length, **kwargs)
49
48
 
50
49
  @override
51
- def get_static_bit_length(self) -> Optional[int]:
50
+ def get_static_bit_length(self) -> int | None:
52
51
  return 8 * self.byte_length
53
52
 
54
53
  @override
55
- def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
54
+ def _encode_positioned_into_pdu(self, physical_value: ParameterValue | None,
56
55
  encode_state: EncodeState) -> None:
57
56
  if encode_state.triggering_request is None:
58
57
  odxraise(