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,45 +1,39 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from enum import Enum
4
- from typing import List, Optional, overload
3
+ from typing import Optional, overload
5
4
  from xml.etree import ElementTree
6
5
 
7
6
  from ..exceptions import odxraise
8
7
  from ..odxlink import OdxDocFragment
9
8
  from ..odxtypes import AtomicOdxType, DataType, compare_odx_values
10
-
11
-
12
- class IntervalType(Enum):
13
- OPEN = "OPEN"
14
- CLOSED = "CLOSED"
15
- INFINITE = "INFINITE"
9
+ from .intervaltype import IntervalType
16
10
 
17
11
 
18
12
  @dataclass
19
13
  class Limit:
20
- value_raw: Optional[str]
21
- value_type: Optional[DataType]
22
- interval_type: Optional[IntervalType]
14
+ value_raw: str | None
15
+ value_type: DataType | None
16
+ interval_type: IntervalType | None
23
17
 
24
18
  @property
25
- def value(self) -> Optional[AtomicOdxType]:
19
+ def value(self) -> AtomicOdxType | None:
26
20
  return self._value
27
21
 
28
22
  @staticmethod
29
23
  @overload
30
- def limit_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment],
31
- value_type: Optional[DataType]) -> "Limit":
24
+ def limit_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment],
25
+ value_type: DataType | None) -> "Limit":
32
26
  ...
33
27
 
34
28
  @staticmethod
35
29
  @overload
36
- def limit_from_et(et_element: None, doc_frags: List[OdxDocFragment],
37
- value_type: Optional[DataType]) -> None:
30
+ def limit_from_et(et_element: None, doc_frags: list[OdxDocFragment],
31
+ value_type: DataType | None) -> None:
38
32
  ...
39
33
 
40
34
  @staticmethod
41
- def limit_from_et(et_element: Optional[ElementTree.Element], doc_frags: List[OdxDocFragment],
42
- value_type: Optional[DataType]) -> Optional["Limit"]:
35
+ def limit_from_et(et_element: ElementTree.Element | None, doc_frags: list[OdxDocFragment],
36
+ value_type: DataType | None) -> Optional["Limit"]:
43
37
 
44
38
  if et_element is None:
45
39
  return None
@@ -56,7 +50,7 @@ class Limit:
56
50
  return Limit(value_raw=value_raw, interval_type=interval_type, value_type=value_type)
57
51
 
58
52
  def __post_init__(self) -> None:
59
- self._value: Optional[AtomicOdxType] = None
53
+ self._value: AtomicOdxType | None = None
60
54
 
61
55
  if self.value_type is not None:
62
56
  self.set_value_type(self.value_type)
@@ -1,13 +1,14 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, cast
3
+ from typing import cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
7
7
  from ..odxlink import OdxDocFragment
8
8
  from ..odxtypes import AtomicOdxType, DataType
9
9
  from ..utils import dataclass_fields_asdict
10
- from .compumethod import CompuCategory, CompuMethod
10
+ from .compucategory import CompuCategory
11
+ from .compumethod import CompuMethod
11
12
  from .linearsegment import LinearSegment
12
13
 
13
14
 
@@ -29,7 +30,7 @@ class LinearCompuMethod(CompuMethod):
29
30
  return self._segment
30
31
 
31
32
  @staticmethod
32
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
33
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
33
34
  internal_type: DataType,
34
35
  physical_type: DataType) -> "LinearCompuMethod":
35
36
  cm = CompuMethod.compu_method_from_et(
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Optional, Union
4
3
 
5
4
  from ..exceptions import odxraise, odxrequire
6
5
  from ..odxtypes import AtomicOdxType, DataType
@@ -24,20 +23,20 @@ class LinearSegment:
24
23
  offset: float
25
24
  factor: float
26
25
  denominator: float
27
- internal_lower_limit: Optional[Limit]
28
- internal_upper_limit: Optional[Limit]
26
+ internal_lower_limit: Limit | None
27
+ internal_upper_limit: Limit | None
29
28
 
30
- inverse_value: Union[int, float] # value used as inverse if factor is 0
29
+ inverse_value: int | float # value used as inverse if factor is 0
31
30
 
32
31
  internal_type: DataType
33
32
  physical_type: DataType
34
33
 
35
34
  @property
36
- def physical_lower_limit(self) -> Optional[Limit]:
35
+ def physical_lower_limit(self) -> Limit | None:
37
36
  return self._physical_lower_limit
38
37
 
39
38
  @property
40
- def physical_upper_limit(self) -> Optional[Limit]:
39
+ def physical_upper_limit(self) -> Limit | None:
41
40
  return self._physical_upper_limit
42
41
 
43
42
  @staticmethod
@@ -52,10 +51,10 @@ class LinearSegment:
52
51
  if len(coeffs.denominators) > 0:
53
52
  denominator = coeffs.denominators[0]
54
53
 
55
- inverse_value: Union[int, float] = 0
54
+ inverse_value: int | float = 0
56
55
  if scale.compu_inverse_value is not None:
57
56
  x = odxrequire(scale.compu_inverse_value).value
58
- if not isinstance(x, (int, float)):
57
+ if not isinstance(x, int | float):
59
58
  odxraise(f"Non-numeric COMPU-INVERSE-VALUE specified ({x!r})")
60
59
  inverse_value = x
61
60
 
@@ -75,8 +74,8 @@ class LinearSegment:
75
74
  def __post_init__(self) -> None:
76
75
  self.__compute_physical_limits()
77
76
 
78
- def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> Union[float, int]:
79
- if not isinstance(internal_value, (int, float)):
77
+ def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> float | int:
78
+ if not isinstance(internal_value, int | float):
80
79
  odxraise(f"Internal values of linear compumethods must "
81
80
  f"either be int or float (is: {type(internal_value).__name__})")
82
81
 
@@ -90,8 +89,8 @@ class LinearSegment:
90
89
 
91
90
  return result
92
91
 
93
- def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> Union[float, int]:
94
- if not isinstance(physical_value, (int, float)):
92
+ def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> float | int:
93
+ if not isinstance(physical_value, int | float):
95
94
  odxraise(f"Physical values of linear compumethods must "
96
95
  f"either be int or float (is: {type(physical_value).__name__})")
97
96
 
@@ -115,7 +114,7 @@ class LinearSegment:
115
114
  This method is called by `__post_init__()`.
116
115
  """
117
116
 
118
- def convert_internal_to_physical_limit(internal_limit: Optional[Limit]) -> Optional[Limit]:
117
+ def convert_internal_to_physical_limit(internal_limit: Limit | None) -> Limit | None:
119
118
  """Helper method to convert a single internal limit
120
119
  """
121
120
  if internal_limit is None or internal_limit.value_raw is None:
@@ -152,7 +151,7 @@ class LinearSegment:
152
151
  # Do type checks
153
152
  expected_type = self.physical_type.python_type
154
153
  if issubclass(expected_type, float):
155
- if not isinstance(physical_value, (int, float)):
154
+ if not isinstance(physical_value, int | float):
156
155
  return False
157
156
  else:
158
157
  if not isinstance(physical_value, expected_type):
@@ -173,7 +172,7 @@ class LinearSegment:
173
172
  # Do type checks
174
173
  expected_type = self.internal_type.python_type
175
174
  if issubclass(expected_type, float):
176
- if not isinstance(internal_value, (int, float)):
175
+ if not isinstance(internal_value, int | float):
177
176
  return False
178
177
  else:
179
178
  if not isinstance(internal_value, expected_type):
@@ -1,13 +1,14 @@
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 ..exceptions import DecodeError, EncodeError, odxassert, odxraise
7
7
  from ..odxlink import OdxDocFragment
8
8
  from ..odxtypes import AtomicOdxType, DataType
9
9
  from ..utils import dataclass_fields_asdict
10
- from .compumethod import CompuCategory, CompuMethod
10
+ from .compucategory import CompuCategory
11
+ from .compumethod import CompuMethod
11
12
  from .ratfuncsegment import RatFuncSegment
12
13
 
13
14
 
@@ -29,11 +30,11 @@ class RatFuncCompuMethod(CompuMethod):
29
30
  return self._int_to_phys_segment
30
31
 
31
32
  @property
32
- def phys_to_int_segment(self) -> Optional[RatFuncSegment]:
33
+ def phys_to_int_segment(self) -> RatFuncSegment | None:
33
34
  return self._phys_to_int_segment
34
35
 
35
36
  @staticmethod
36
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
37
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
37
38
  internal_type: DataType,
38
39
  physical_type: DataType) -> "RatFuncCompuMethod":
39
40
  cm = CompuMethod.compu_method_from_et(
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional, Union
4
3
 
5
4
  from ..exceptions import odxraise, odxrequire
6
5
  from ..odxtypes import AtomicOdxType, DataType
@@ -14,11 +13,11 @@ class RatFuncSegment:
14
13
  """
15
14
  value_type: DataType
16
15
 
17
- numerator_coeffs: List[Union[int, float]]
18
- denominator_coeffs: List[Union[int, float]]
16
+ numerator_coeffs: list[int | float]
17
+ denominator_coeffs: list[int | float]
19
18
 
20
- lower_limit: Optional[Limit]
21
- upper_limit: Optional[Limit]
19
+ lower_limit: Limit | None
20
+ upper_limit: Limit | None
22
21
 
23
22
  @staticmethod
24
23
  def from_compu_scale(scale: CompuScale, value_type: DataType) -> "RatFuncSegment":
@@ -39,8 +38,8 @@ class RatFuncSegment:
39
38
  upper_limit=upper_limit,
40
39
  value_type=scale.range_type)
41
40
 
42
- def convert(self, value: AtomicOdxType) -> Union[float, int]:
43
- if not isinstance(value, (int, float)):
41
+ def convert(self, value: AtomicOdxType) -> float | int:
42
+ if not isinstance(value, int | float):
44
43
  odxraise(f"Internal values of linear compumethods must "
45
44
  f"either be int or float (is: {type(value).__name__})")
46
45
 
@@ -70,7 +69,7 @@ class RatFuncSegment:
70
69
  # Do type checks
71
70
  expected_type = self.value_type.python_type
72
71
  if issubclass(expected_type, float):
73
- if not isinstance(value, (int, float)):
72
+ if not isinstance(value, int | float):
74
73
  return False
75
74
  else:
76
75
  if not isinstance(value, expected_type):
@@ -1,14 +1,15 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Union, cast
3
+ from typing import cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
7
7
  from ..odxlink import OdxDocFragment
8
8
  from ..odxtypes import AtomicOdxType, DataType
9
9
  from ..utils import dataclass_fields_asdict
10
- from .compumethod import CompuCategory, CompuMethod
11
- from .limit import IntervalType
10
+ from .compucategory import CompuCategory
11
+ from .compumethod import CompuMethod
12
+ from .intervaltype import IntervalType
12
13
  from .linearsegment import LinearSegment
13
14
 
14
15
 
@@ -20,11 +21,11 @@ class ScaleLinearCompuMethod(CompuMethod):
20
21
  """
21
22
 
22
23
  @property
23
- def segments(self) -> List[LinearSegment]:
24
+ def segments(self) -> list[LinearSegment]:
24
25
  return self._segments
25
26
 
26
27
  @staticmethod
27
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
28
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
28
29
  internal_type: DataType,
29
30
  physical_type: DataType) -> "ScaleLinearCompuMethod":
30
31
  cm = CompuMethod.compu_method_from_et(
@@ -34,7 +35,7 @@ class ScaleLinearCompuMethod(CompuMethod):
34
35
  return ScaleLinearCompuMethod(**kwargs)
35
36
 
36
37
  def __post_init__(self) -> None:
37
- self._segments: List[LinearSegment] = []
38
+ self._segments: list[LinearSegment] = []
38
39
 
39
40
  odxassert(self.category == CompuCategory.SCALE_LINEAR,
40
41
  "ScaleLinearCompuMethod must exibit SCALE-LINEAR category")
@@ -99,7 +100,7 @@ class ScaleLinearCompuMethod(CompuMethod):
99
100
  self._is_invertible = False
100
101
  break
101
102
 
102
- if not isinstance(x, (int, float)):
103
+ if not isinstance(x, int | float):
103
104
  odxraise("Linear segments must use int or float for all quantities")
104
105
 
105
106
  # the respective function value at the interval's
@@ -110,7 +111,7 @@ class ScaleLinearCompuMethod(CompuMethod):
110
111
  self._is_invertible = False
111
112
  break
112
113
 
113
- def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> Union[float, int]:
114
+ def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> float | int:
114
115
  if not self._is_invertible:
115
116
  odxraise(
116
117
  f"Trying to encode value {physical_value!r} using a non-invertible "
@@ -127,7 +128,7 @@ class ScaleLinearCompuMethod(CompuMethod):
127
128
 
128
129
  return seg.convert_physical_to_internal(physical_value)
129
130
 
130
- def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> Union[float, int]:
131
+ def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> float | int:
131
132
  applicable_segments = [
132
133
  seg for seg in self._segments if seg.internal_applies(internal_value)
133
134
  ]
@@ -1,13 +1,14 @@
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 ..exceptions import DecodeError, EncodeError, odxassert, odxraise
7
7
  from ..odxlink import OdxDocFragment
8
8
  from ..odxtypes import AtomicOdxType, DataType
9
9
  from ..utils import dataclass_fields_asdict
10
- from .compumethod import CompuCategory, CompuMethod
10
+ from .compucategory import CompuCategory
11
+ from .compumethod import CompuMethod
11
12
  from .ratfuncsegment import RatFuncSegment
12
13
 
13
14
 
@@ -19,15 +20,15 @@ class ScaleRatFuncCompuMethod(CompuMethod):
19
20
  """
20
21
 
21
22
  @property
22
- def int_to_phys_segments(self) -> List[RatFuncSegment]:
23
+ def int_to_phys_segments(self) -> list[RatFuncSegment]:
23
24
  return self._int_to_phys_segments
24
25
 
25
26
  @property
26
- def phys_to_int_segments(self) -> Optional[List[RatFuncSegment]]:
27
+ def phys_to_int_segments(self) -> list[RatFuncSegment] | None:
27
28
  return self._phys_to_int_segments
28
29
 
29
30
  @staticmethod
30
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
31
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
31
32
  internal_type: DataType,
32
33
  physical_type: DataType) -> "ScaleRatFuncCompuMethod":
33
34
  cm = CompuMethod.compu_method_from_et(
@@ -1,14 +1,15 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Union
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from ..exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
7
6
  from ..odxlink import OdxDocFragment
8
7
  from ..odxtypes import AtomicOdxType, DataType
9
8
  from ..utils import dataclass_fields_asdict
10
- from .compumethod import CompuCategory, CompuMethod
11
- from .limit import IntervalType, Limit
9
+ from .compucategory import CompuCategory
10
+ from .compumethod import CompuMethod
11
+ from .intervaltype import IntervalType
12
+ from .limit import Limit
12
13
 
13
14
 
14
15
  @dataclass
@@ -35,11 +36,11 @@ class TabIntpCompuMethod(CompuMethod):
35
36
  """
36
37
 
37
38
  @property
38
- def internal_points(self) -> List[Union[float, int]]:
39
+ def internal_points(self) -> list[float | int]:
39
40
  return self._internal_points
40
41
 
41
42
  @property
42
- def physical_points(self) -> List[Union[float, int]]:
43
+ def physical_points(self) -> list[float | int]:
43
44
  return self._physical_points
44
45
 
45
46
  @property
@@ -59,7 +60,7 @@ class TabIntpCompuMethod(CompuMethod):
59
60
  return self._physical_upper_limit
60
61
 
61
62
  @staticmethod
62
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
63
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
63
64
  internal_type: DataType,
64
65
  physical_type: DataType) -> "TabIntpCompuMethod":
65
66
  cm = CompuMethod.compu_method_from_et(
@@ -72,16 +73,16 @@ class TabIntpCompuMethod(CompuMethod):
72
73
  odxassert(self.category == CompuCategory.TAB_INTP,
73
74
  "TabIntpCompuMethod must exibit TAB-INTP category")
74
75
 
75
- self._internal_points: List[Union[int, float]] = []
76
- self._physical_points: List[Union[int, float]] = []
76
+ self._internal_points: list[int | float] = []
77
+ self._physical_points: list[int | float] = []
77
78
  for scale in odxrequire(self.compu_internal_to_phys).compu_scales:
78
79
  internal_point = odxrequire(scale.lower_limit).value
79
80
  physical_point = odxrequire(scale.compu_const).value
80
81
 
81
- if not isinstance(internal_point, (float, int)):
82
+ if not isinstance(internal_point, float | int):
82
83
  odxraise("The type of values of tab-intp compumethods must "
83
84
  "either int or float")
84
- if not isinstance(physical_point, (float, int)):
85
+ if not isinstance(physical_point, float | int):
85
86
  odxraise("The type of values of tab-intp compumethods must "
86
87
  "either int or float")
87
88
 
@@ -128,10 +129,8 @@ class TabIntpCompuMethod(CompuMethod):
128
129
  ], "Physical data type of TAB-INTP compumethod must be one of"
129
130
  " [A_INT32, A_UINT32, A_FLOAT32, A_FLOAT64]")
130
131
 
131
- def __piecewise_linear_interpolate(self, x: Union[int, float],
132
- range_samples: List[Union[int, float]],
133
- domain_samples: List[Union[int,
134
- float]]) -> Union[float, None]:
132
+ def __piecewise_linear_interpolate(self, x: int | float, range_samples: list[int | float],
133
+ domain_samples: list[int | float]) -> float | None:
135
134
  for i in range(0, len(range_samples) - 1):
136
135
  if (x0 := range_samples[i]) <= x and x <= (x1 := range_samples[i + 1]):
137
136
  y0 = domain_samples[i]
@@ -141,13 +140,13 @@ class TabIntpCompuMethod(CompuMethod):
141
140
  return None
142
141
 
143
142
  def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> AtomicOdxType:
144
- if not isinstance(physical_value, (int, float)):
143
+ if not isinstance(physical_value, int | float):
145
144
  odxraise("The type of values of tab-intp compumethods must "
146
145
  "either int or float", EncodeError)
147
146
  return None
148
147
 
149
148
  odxassert(
150
- isinstance(physical_value, (int, float)),
149
+ isinstance(physical_value, int | float),
151
150
  "Only integers and floats can be piecewise linearly interpolated", EncodeError)
152
151
  result = self.__piecewise_linear_interpolate(physical_value, self._physical_points,
153
152
  self._internal_points)
@@ -162,14 +161,14 @@ class TabIntpCompuMethod(CompuMethod):
162
161
  return res
163
162
 
164
163
  def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> AtomicOdxType:
165
- if not isinstance(internal_value, (int, float)):
164
+ if not isinstance(internal_value, int | float):
166
165
  odxraise(
167
166
  "The internal type of values of tab-intp compumethods must "
168
167
  "either int or float", EncodeError)
169
168
  return None
170
169
 
171
170
  odxassert(
172
- isinstance(internal_value, (int, float)),
171
+ isinstance(internal_value, int | float),
173
172
  "Only integers and floats can be piecewise linearly interpolated", DecodeError)
174
173
 
175
174
  result = self.__piecewise_linear_interpolate(internal_value, self._internal_points,
@@ -186,14 +185,14 @@ class TabIntpCompuMethod(CompuMethod):
186
185
  return res
187
186
 
188
187
  def is_valid_physical_value(self, physical_value: AtomicOdxType) -> bool:
189
- if not isinstance(physical_value, (int, float)):
188
+ if not isinstance(physical_value, int | float):
190
189
  return False
191
190
 
192
191
  return min(self.physical_points) <= physical_value and physical_value <= max(
193
192
  self.physical_points)
194
193
 
195
194
  def is_valid_internal_value(self, internal_value: AtomicOdxType) -> bool:
196
- if not isinstance(internal_value, (int, float)):
195
+ if not isinstance(internal_value, int | float):
197
196
  return False
198
197
 
199
198
  return min(self.internal_points) <= internal_value and internal_value <= max(
@@ -1,13 +1,14 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, cast
3
+ from typing import cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from ..exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
7
7
  from ..odxlink import OdxDocFragment
8
8
  from ..odxtypes import AtomicOdxType, DataType
9
9
  from ..utils import dataclass_fields_asdict
10
- from .compumethod import CompuCategory, CompuMethod
10
+ from .compucategory import CompuCategory
11
+ from .compumethod import CompuMethod
11
12
  from .compuscale import CompuScale
12
13
 
13
14
 
@@ -21,7 +22,7 @@ class TexttableCompuMethod(CompuMethod):
21
22
  """
22
23
 
23
24
  @staticmethod
24
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
25
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
25
26
  internal_type: DataType,
26
27
  physical_type: DataType) -> "TexttableCompuMethod":
27
28
  cm = CompuMethod.compu_method_from_et(
@@ -94,7 +95,7 @@ class TexttableCompuMethod(CompuMethod):
94
95
  scales = []
95
96
  if (citp := self.compu_internal_to_phys) is not None:
96
97
  scales = citp.compu_scales
97
- matching_scales: List[CompuScale] = [x for x in scales if x.applies(internal_value)]
98
+ matching_scales: list[CompuScale] = [x for x in scales if x.applies(internal_value)]
98
99
 
99
100
  if len(matching_scales) == 0:
100
101
  if self._compu_physical_default_value is None:
@@ -1,4 +1,3 @@
1
- from typing import List, Union
2
1
  from xml.etree import ElementTree
3
2
 
4
3
  from .comparam import Comparam
@@ -6,9 +5,8 @@ from .complexcomparam import ComplexComparam
6
5
  from .odxlink import OdxDocFragment
7
6
 
8
7
 
9
- def create_any_comparam_from_et(
10
- et_element: ElementTree.Element,
11
- doc_frags: List[OdxDocFragment]) -> Union[Comparam, ComplexComparam]:
8
+ def create_any_comparam_from_et(et_element: ElementTree.Element,
9
+ doc_frags: list[OdxDocFragment]) -> Comparam | ComplexComparam:
12
10
  if et_element.tag == "COMPARAM":
13
11
  return Comparam.from_et(et_element, doc_frags)
14
12
  elif et_element.tag == "COMPLEX-COMPARAM":
@@ -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 .diagcodedtype import DiagCodedType
@@ -13,7 +12,7 @@ from .standardlengthtype import StandardLengthType
13
12
 
14
13
 
15
14
  def create_any_diag_coded_type_from_et(et_element: ElementTree.Element,
16
- doc_frags: List[OdxDocFragment]) -> DiagCodedType:
15
+ doc_frags: list[OdxDocFragment]) -> DiagCodedType:
17
16
  dct_type = et_element.get(f"{xsi}type")
18
17
  if dct_type == "LEADING-LENGTH-INFO-TYPE":
19
18
  return LeadingLengthInfoType.from_et(et_element, doc_frags)
odxtools/database.py CHANGED
@@ -1,8 +1,9 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ from collections import OrderedDict
2
3
  from itertools import chain
3
4
  from os import PathLike
4
5
  from pathlib import Path
5
- from typing import IO, Any, Dict, List, Optional, OrderedDict, Union
6
+ from typing import IO, Any, Union
6
7
  from xml.etree import ElementTree
7
8
  from zipfile import ZipFile
8
9
 
@@ -30,7 +31,7 @@ class Database:
30
31
  """
31
32
 
32
33
  def __init__(self) -> None:
33
- self.model_version: Optional[Version] = None
34
+ self.model_version: Version | None = None
34
35
  self.auxiliary_files: OrderedDict[str, IO[bytes]] = OrderedDict()
35
36
 
36
37
  # create an empty database object
@@ -68,16 +69,16 @@ class Database:
68
69
 
69
70
  def add_auxiliary_file(self,
70
71
  aux_file_name: Union[str, "PathLike[Any]"],
71
- aux_file_obj: Optional[IO[bytes]] = None) -> None:
72
+ aux_file_obj: IO[bytes] | None = None) -> None:
72
73
  if aux_file_obj is None:
73
74
  aux_file_obj = open(aux_file_name, "rb")
74
75
 
75
76
  self.auxiliary_files[str(aux_file_name)] = aux_file_obj
76
77
 
77
78
  def _process_xml_tree(self, root: ElementTree.Element) -> None:
78
- dlcs: List[DiagLayerContainer] = []
79
- comparam_subsets: List[ComparamSubset] = []
80
- comparam_specs: List[ComparamSpec] = []
79
+ dlcs: list[DiagLayerContainer] = []
80
+ comparam_subsets: list[ComparamSubset] = []
81
+ comparam_specs: list[ComparamSpec] = []
81
82
 
82
83
  # ODX spec version
83
84
  model_version = Version(root.attrib.get("MODEL-VERSION", "2.0"))
@@ -160,8 +161,8 @@ class Database:
160
161
  for dlc in self.diag_layer_containers:
161
162
  dlc._resolve_snrefs(context)
162
163
 
163
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
164
- result: Dict[OdxLinkId, Any] = {}
164
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
165
+ result: dict[OdxLinkId, Any] = {}
165
166
 
166
167
  for subset in self.comparam_subsets:
167
168
  result.update(subset._build_odxlinks())