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 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 .comparam import Comparam
@@ -22,12 +22,12 @@ class ComparamSubset(OdxCategory):
22
22
  comparams: NamedItemList[Comparam]
23
23
  complex_comparams: NamedItemList[ComplexComparam]
24
24
  data_object_props: NamedItemList[DataObjectProperty]
25
- unit_spec: Optional[UnitSpec]
26
- category: Optional[str] # mandatory in ODX 2.2, but non-existent in ODX 2.0
25
+ unit_spec: UnitSpec | None
26
+ category: str | None # mandatory in ODX 2.2, but non-existent in ODX 2.0
27
27
 
28
28
  @staticmethod
29
29
  def from_et(et_element: ElementTree.Element,
30
- doc_frags: List[OdxDocFragment]) -> "ComparamSubset":
30
+ doc_frags: list[OdxDocFragment]) -> "ComparamSubset":
31
31
 
32
32
  category_attrib = et_element.attrib.get("CATEGORY")
33
33
 
@@ -64,7 +64,7 @@ class ComparamSubset(OdxCategory):
64
64
  unit_spec=unit_spec,
65
65
  **kwargs)
66
66
 
67
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
67
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
68
68
  odxlinks = super()._build_odxlinks()
69
69
 
70
70
  for comparam in self.comparams:
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional, Union
3
+ from typing import Any, Union
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .basecomparam import BaseComparam
@@ -10,7 +10,7 @@ from .odxtypes import odxstr_to_bool
10
10
  from .snrefcontext import SnRefContext
11
11
  from .utils import dataclass_fields_asdict
12
12
 
13
- ComplexValue = List[Union[str, "ComplexValue"]]
13
+ ComplexValue = list[Union[str, "ComplexValue"]]
14
14
 
15
15
 
16
16
  def create_complex_value_from_et(et_element: ElementTree.Element) -> ComplexValue:
@@ -26,8 +26,8 @@ def create_complex_value_from_et(et_element: ElementTree.Element) -> ComplexValu
26
26
  @dataclass
27
27
  class ComplexComparam(BaseComparam):
28
28
  subparams: NamedItemList[BaseComparam]
29
- physical_default_value: Optional[ComplexValue]
30
- allow_multiple_values_raw: Optional[bool]
29
+ physical_default_value: ComplexValue | None
30
+ allow_multiple_values_raw: bool | None
31
31
 
32
32
  @property
33
33
  def allow_multiple_values(self) -> bool:
@@ -35,7 +35,7 @@ class ComplexComparam(BaseComparam):
35
35
 
36
36
  @staticmethod
37
37
  def from_et(et_element: ElementTree.Element,
38
- doc_frags: List[OdxDocFragment]) -> "ComplexComparam":
38
+ doc_frags: list[OdxDocFragment]) -> "ComplexComparam":
39
39
  kwargs = dataclass_fields_asdict(BaseComparam.from_et(et_element, doc_frags))
40
40
 
41
41
  # to avoid a cyclic import, create_any_comparam_from_et cannot
@@ -68,7 +68,7 @@ class ComplexComparam(BaseComparam):
68
68
  # extract the complex physical default value. (what's the
69
69
  # purpose of this? the sub-parameters can define their own
70
70
  # default values if a default is desired...)
71
- complex_physical_default_value: Optional[ComplexValue] = None
71
+ complex_physical_default_value: ComplexValue | None = None
72
72
  if (cpdv_elem := et_element.find("COMPLEX-PHYSICAL-DEFAULT-VALUE")) is not None:
73
73
  complex_physical_default_value = create_complex_value_from_et(cpdv_elem)
74
74
 
@@ -80,7 +80,7 @@ class ComplexComparam(BaseComparam):
80
80
  allow_multiple_values_raw=allow_multiple_values_raw,
81
81
  **kwargs)
82
82
 
83
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
83
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
84
84
  odxlinks = super()._build_odxlinks()
85
85
  for subparam in self.subparams:
86
86
  odxlinks.update(subparam._build_odxlinks())
@@ -0,0 +1,191 @@
1
+ # SPDX-License-Identifier: MIT
2
+ import typing
3
+ from typing import runtime_checkable
4
+
5
+ from .codec import Codec
6
+ from .decodestate import DecodeState
7
+ from .encodestate import EncodeState
8
+ from .exceptions import EncodeError, odxraise
9
+ from .odxtypes import ParameterValue
10
+ from .parameters.codedconstparameter import CodedConstParameter
11
+ from .parameters.matchingrequestparameter import MatchingRequestParameter
12
+ from .parameters.parameter import Parameter
13
+ from .parameters.physicalconstantparameter import PhysicalConstantParameter
14
+
15
+
16
+ @runtime_checkable
17
+ class CompositeCodec(Codec, typing.Protocol):
18
+ """Any object which can be en- or decoded to be transferred over
19
+ the wire which is composed of multiple parameter implements this
20
+ API.
21
+
22
+ """
23
+
24
+ @property
25
+ def parameters(self) -> list[Parameter]:
26
+ return []
27
+
28
+ @property
29
+ def required_parameters(self) -> list[Parameter]:
30
+ return []
31
+
32
+ @property
33
+ def free_parameters(self) -> list[Parameter]:
34
+ return []
35
+
36
+
37
+ # some helper functions useful for composite codec objects
38
+ def composite_codec_get_static_bit_length(codec: CompositeCodec) -> int | None:
39
+ """Compute the length of a composite codec object in bits
40
+
41
+ This is basically the sum of the lengths of all parameters. If the
42
+ length of any parameter can only determined at runtime, `None` is
43
+ returned.
44
+ """
45
+
46
+ cursor = 0
47
+ byte_length = 0
48
+ for param in codec.parameters:
49
+ param_bit_length = param.get_static_bit_length()
50
+ if param_bit_length is None:
51
+ # We were not able to calculate a static bit length
52
+ return None
53
+ elif param.byte_position is not None:
54
+ cursor = param.byte_position
55
+
56
+ cursor += ((param.bit_position or 0) + param_bit_length + 7) // 8
57
+ byte_length = max(byte_length, cursor)
58
+
59
+ return byte_length * 8
60
+
61
+
62
+ def composite_codec_get_required_parameters(codec: CompositeCodec) -> list[Parameter]:
63
+ """Return the list of parameters which are required to be
64
+ specified for encoding the composite codec object
65
+
66
+ I.e., all free parameters that do not exhibit a default value.
67
+ """
68
+ return [p for p in codec.parameters if p.is_required]
69
+
70
+
71
+ def composite_codec_get_free_parameters(codec: CompositeCodec) -> list[Parameter]:
72
+ """Return the list of parameters which can be freely specified by
73
+ the user when encoding the composite codec object
74
+
75
+ This means all required parameters plus parameters that can be
76
+ omitted because they specify a default.
77
+ """
78
+ return [p for p in codec.parameters if p.is_settable]
79
+
80
+
81
+ def composite_codec_get_coded_const_prefix(codec: CompositeCodec,
82
+ request_prefix: bytes = b'') -> bytes:
83
+ encode_state = EncodeState(coded_message=bytearray(), triggering_request=request_prefix)
84
+
85
+ for param in codec.parameters:
86
+ if (isinstance(param, MatchingRequestParameter) and param.request_byte_position < len(request_prefix)) or \
87
+ isinstance(param, CodedConstParameter|PhysicalConstantParameter) :
88
+ param.encode_into_pdu(physical_value=None, encode_state=encode_state)
89
+ else:
90
+ break
91
+
92
+ return encode_state.coded_message
93
+
94
+
95
+ def composite_codec_encode_into_pdu(codec: CompositeCodec, physical_value: ParameterValue | None,
96
+ encode_state: EncodeState) -> None:
97
+ from .parameters.lengthkeyparameter import LengthKeyParameter
98
+ from .parameters.tablekeyparameter import TableKeyParameter
99
+
100
+ if not isinstance(physical_value, dict):
101
+ odxraise(
102
+ f"Expected a dictionary for the values of {codec.short_name}, "
103
+ f"got {type(physical_value).__name__}", EncodeError)
104
+ elif encode_state.cursor_bit_position != 0:
105
+ odxraise(
106
+ f"Compositional codec objecs must be byte aligned, but "
107
+ f"{codec.short_name} requested to be at bit position "
108
+ f"{encode_state.cursor_bit_position}", EncodeError)
109
+ encode_state.bit_position = 0
110
+
111
+ orig_origin = encode_state.origin_byte_position
112
+ encode_state.origin_byte_position = encode_state.cursor_byte_position
113
+
114
+ orig_is_end_of_pdu = encode_state.is_end_of_pdu
115
+ encode_state.is_end_of_pdu = False
116
+
117
+ # ensure that no values for unknown parameters are specified.
118
+ if not encode_state.allow_unknown_parameters:
119
+ param_names = {param.short_name for param in codec.parameters}
120
+ for param_value_name in physical_value:
121
+ if param_value_name not in param_names:
122
+ odxraise(f"Value for unknown parameter '{param_value_name}' specified "
123
+ f"for composite codec object {codec.short_name}")
124
+
125
+ for param in codec.parameters:
126
+ if id(param) == id(codec.parameters[-1]):
127
+ # The last parameter of the composite codec object is at
128
+ # the end of the PDU if the codec object itself is at the
129
+ # end of the PDU.
130
+ #
131
+ # TODO: This assumes that the last parameter specified in
132
+ # the ODX is located last in the PDU...
133
+ encode_state.is_end_of_pdu = orig_is_end_of_pdu
134
+
135
+ if isinstance(param, LengthKeyParameter | TableKeyParameter):
136
+ # At this point, we encode a placeholder value for length-
137
+ # and table keys, since these can be specified
138
+ # implicitly (i.e., by means of parameters that use
139
+ # these keys). To avoid getting an "overlapping
140
+ # parameter" warning, we must encode a value of zero
141
+ # into the PDU here and add the real value of the
142
+ # parameter in a post-processing step.
143
+ param.encode_placeholder_into_pdu(
144
+ physical_value=physical_value.get(param.short_name), encode_state=encode_state)
145
+
146
+ continue
147
+
148
+ if param.is_required and param.short_name not in physical_value:
149
+ odxraise(f"No value for required parameter {param.short_name} specified", EncodeError)
150
+
151
+ param_phys_value = physical_value.get(param.short_name)
152
+ param.encode_into_pdu(physical_value=param_phys_value, encode_state=encode_state)
153
+
154
+ encode_state.journal.append((param, param_phys_value))
155
+
156
+ encode_state.is_end_of_pdu = False
157
+
158
+ # encode the length- and table keys. This cannot be done above
159
+ # because we allow these to be defined implicitly (i.e. they
160
+ # are defined by their respective users)
161
+ for param in codec.parameters:
162
+ if not isinstance(param, LengthKeyParameter | TableKeyParameter):
163
+ # the current parameter is neither a length- nor a table key
164
+ continue
165
+
166
+ # Encode the value of the key parameter into the message
167
+ param.encode_value_into_pdu(encode_state=encode_state)
168
+
169
+ encode_state.origin_byte_position = orig_origin
170
+
171
+
172
+ def composite_codec_decode_from_pdu(codec: CompositeCodec,
173
+ decode_state: DecodeState) -> ParameterValue:
174
+ # move the origin since positions specified by sub-parameters of
175
+ # composite codec objects are relative to the beginning of the
176
+ # object.
177
+ orig_origin = decode_state.origin_byte_position
178
+ decode_state.origin_byte_position = decode_state.cursor_byte_position
179
+
180
+ result = {}
181
+ for param in codec.parameters:
182
+ value = param.decode_from_pdu(decode_state)
183
+
184
+ decode_state.journal.append((param, value))
185
+ result[param.short_name] = value
186
+
187
+ # decoding of the composite codec object finished. go back the
188
+ # original origin.
189
+ decode_state.origin_byte_position = orig_origin
190
+
191
+ return result
@@ -0,0 +1,13 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from enum import Enum
3
+
4
+
5
+ class CompuCategory(Enum):
6
+ IDENTICAL = "IDENTICAL"
7
+ LINEAR = "LINEAR"
8
+ SCALE_LINEAR = "SCALE-LINEAR"
9
+ TEXTTABLE = "TEXTTABLE"
10
+ COMPUCODE = "COMPUCODE"
11
+ TAB_INTP = "TAB-INTP"
12
+ RAT_FUNC = "RAT-FUNC"
13
+ SCALE_RAT_FUNC = "SCALE-RAT-FUNC"
@@ -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 ..exceptions import DecodeError, EncodeError, odxassert, odxraise
@@ -8,7 +8,8 @@ from ..odxlink import OdxDocFragment
8
8
  from ..odxtypes import AtomicOdxType, DataType
9
9
  from ..progcode import ProgCode
10
10
  from ..utils import dataclass_fields_asdict
11
- from .compumethod import CompuCategory, CompuMethod
11
+ from .compucategory import CompuCategory
12
+ from .compumethod import CompuMethod
12
13
 
13
14
 
14
15
  @dataclass
@@ -19,21 +20,21 @@ class CompuCodeCompuMethod(CompuMethod):
19
20
  """
20
21
 
21
22
  @property
22
- def internal_to_phys_code(self) -> Optional[ProgCode]:
23
+ def internal_to_phys_code(self) -> ProgCode | None:
23
24
  if self.compu_internal_to_phys is None:
24
25
  return None
25
26
 
26
27
  return self.compu_internal_to_phys.prog_code
27
28
 
28
29
  @property
29
- def phys_to_internal_code(self) -> Optional[ProgCode]:
30
+ def phys_to_internal_code(self) -> ProgCode | None:
30
31
  if self.compu_phys_to_internal is None:
31
32
  return None
32
33
 
33
34
  return self.compu_phys_to_internal.prog_code
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) -> "CompuCodeCompuMethod":
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 Optional
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from ..odxtypes import AtomicOdxType, DataType
@@ -8,13 +7,13 @@ from ..odxtypes import AtomicOdxType, DataType
8
7
 
9
8
  @dataclass
10
9
  class CompuConst:
11
- v: Optional[str]
12
- vt: Optional[str]
10
+ v: str | None
11
+ vt: str | None
13
12
 
14
13
  data_type: DataType
15
14
 
16
15
  @property
17
- def value(self) -> Optional[AtomicOdxType]:
16
+ def value(self) -> AtomicOdxType | None:
18
17
  return self._value
19
18
 
20
19
  @staticmethod
@@ -26,6 +25,6 @@ class CompuConst:
26
25
  return CompuConst(v=v, vt=vt, data_type=data_type)
27
26
 
28
27
  def __post_init__(self) -> None:
29
- self._value: Optional[AtomicOdxType] = self.vt
28
+ self._value: AtomicOdxType | None = self.vt
30
29
  if self.v is not None:
31
30
  self._value = self.data_type.from_string(self.v)
@@ -1,6 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Optional
4
3
  from xml.etree import ElementTree
5
4
 
6
5
  from ..odxtypes import DataType
@@ -11,7 +10,7 @@ from .compuinversevalue import CompuInverseValue
11
10
 
12
11
  @dataclass
13
12
  class CompuDefaultValue(CompuConst):
14
- compu_inverse_value: Optional[CompuInverseValue]
13
+ compu_inverse_value: CompuInverseValue | None
15
14
 
16
15
  @staticmethod
17
16
  def compuvalue_from_et(et_element: ElementTree.Element, *,
@@ -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 ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
@@ -13,13 +13,13 @@ from .compuscale import CompuScale
13
13
 
14
14
  @dataclass
15
15
  class CompuInternalToPhys:
16
- compu_scales: List[CompuScale]
17
- prog_code: Optional[ProgCode]
18
- compu_default_value: Optional[CompuDefaultValue]
16
+ compu_scales: list[CompuScale]
17
+ prog_code: ProgCode | None
18
+ compu_default_value: CompuDefaultValue | None
19
19
 
20
20
  @staticmethod
21
21
  def compu_internal_to_phys_from_et(et_element: ElementTree.Element,
22
- doc_frags: List[OdxDocFragment], *, internal_type: DataType,
22
+ doc_frags: list[OdxDocFragment], *, internal_type: DataType,
23
23
  physical_type: DataType) -> "CompuInternalToPhys":
24
24
  compu_scales = [
25
25
  CompuScale.compuscale_from_et(
@@ -39,7 +39,7 @@ class CompuInternalToPhys:
39
39
  return CompuInternalToPhys(
40
40
  compu_scales=compu_scales, prog_code=prog_code, compu_default_value=compu_default_value)
41
41
 
42
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
42
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
43
43
  result = {}
44
44
 
45
45
  if self.prog_code is not None:
@@ -1,28 +1,17 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from enum import Enum
4
- from typing import Any, Dict, List, Optional
3
+ from typing import Any
5
4
  from xml.etree import ElementTree
6
5
 
7
6
  from ..exceptions import odxraise
8
7
  from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
9
8
  from ..odxtypes import AtomicOdxType, DataType
10
9
  from ..snrefcontext import SnRefContext
10
+ from .compucategory import CompuCategory
11
11
  from .compuinternaltophys import CompuInternalToPhys
12
12
  from .compuphystointernal import CompuPhysToInternal
13
13
 
14
14
 
15
- class CompuCategory(Enum):
16
- IDENTICAL = "IDENTICAL"
17
- LINEAR = "LINEAR"
18
- SCALE_LINEAR = "SCALE-LINEAR"
19
- TEXTTABLE = "TEXTTABLE"
20
- COMPUCODE = "COMPUCODE"
21
- TAB_INTP = "TAB-INTP"
22
- RAT_FUNC = "RAT-FUNC"
23
- SCALE_RAT_FUNC = "SCALE-RAT-FUNC"
24
-
25
-
26
15
  @dataclass
27
16
  class CompuMethod:
28
17
  """A compu method translates between the internal representation
@@ -42,14 +31,14 @@ class CompuMethod:
42
31
  """
43
32
 
44
33
  category: CompuCategory
45
- compu_internal_to_phys: Optional[CompuInternalToPhys]
46
- compu_phys_to_internal: Optional[CompuPhysToInternal]
34
+ compu_internal_to_phys: CompuInternalToPhys | None
35
+ compu_phys_to_internal: CompuPhysToInternal | None
47
36
 
48
37
  physical_type: DataType
49
38
  internal_type: DataType
50
39
 
51
40
  @staticmethod
52
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
41
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
53
42
  internal_type: DataType, physical_type: DataType) -> "CompuMethod":
54
43
  cat_text = et_element.findtext("CATEGORY")
55
44
  if cat_text is None:
@@ -78,7 +67,7 @@ class CompuMethod:
78
67
  physical_type=physical_type,
79
68
  internal_type=internal_type)
80
69
 
81
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
70
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
82
71
  result = {}
83
72
 
84
73
  if self.compu_internal_to_phys is not 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 ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
@@ -13,13 +13,13 @@ from .compuscale import CompuScale
13
13
 
14
14
  @dataclass
15
15
  class CompuPhysToInternal:
16
- compu_scales: List[CompuScale]
17
- prog_code: Optional[ProgCode]
18
- compu_default_value: Optional[CompuDefaultValue]
16
+ compu_scales: list[CompuScale]
17
+ prog_code: ProgCode | None
18
+ compu_default_value: CompuDefaultValue | None
19
19
 
20
20
  @staticmethod
21
21
  def compu_phys_to_internal_from_et(et_element: ElementTree.Element,
22
- doc_frags: List[OdxDocFragment], *, internal_type: DataType,
22
+ doc_frags: list[OdxDocFragment], *, internal_type: DataType,
23
23
  physical_type: DataType) -> "CompuPhysToInternal":
24
24
  compu_scales = [
25
25
  CompuScale.compuscale_from_et(
@@ -39,7 +39,7 @@ class CompuPhysToInternal:
39
39
  return CompuPhysToInternal(
40
40
  compu_scales=compu_scales, prog_code=prog_code, compu_default_value=compu_default_value)
41
41
 
42
- def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
42
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
43
43
  result = {}
44
44
 
45
45
  if self.prog_code is not None:
@@ -1,6 +1,6 @@
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 odxassert, odxrequire
@@ -12,11 +12,11 @@ from ..odxtypes import DataType
12
12
  class CompuRationalCoeffs:
13
13
  value_type: DataType
14
14
 
15
- numerators: List[Union[int, float]]
16
- denominators: List[Union[int, float]]
15
+ numerators: list[int | float]
16
+ denominators: list[int | float]
17
17
 
18
18
  @staticmethod
19
- def coeffs_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
19
+ def coeffs_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
20
20
  value_type: DataType) -> "CompuRationalCoeffs":
21
21
  odxassert(
22
22
  value_type
@@ -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 ..description import Description
@@ -17,13 +16,13 @@ class CompuScale:
17
16
  """A COMPU-SCALE represents one value range of a COMPU-METHOD.
18
17
  """
19
18
 
20
- short_label: Optional[str]
21
- description: Optional[Description]
22
- lower_limit: Optional[Limit]
23
- upper_limit: Optional[Limit]
24
- compu_inverse_value: Optional[CompuInverseValue]
25
- compu_const: Optional[CompuConst]
26
- compu_rational_coeffs: Optional[CompuRationalCoeffs]
19
+ short_label: str | None
20
+ description: Description | None
21
+ lower_limit: Limit | None
22
+ upper_limit: Limit | None
23
+ compu_inverse_value: CompuInverseValue | None
24
+ compu_const: CompuConst | None
25
+ compu_rational_coeffs: CompuRationalCoeffs | None
27
26
 
28
27
  # the following two attributes are not specified for COMPU-SCALE
29
28
  # tags in the XML, but they are required to do anything useful
@@ -38,7 +37,7 @@ class CompuScale:
38
37
  range_type: DataType
39
38
 
40
39
  @staticmethod
41
- def compuscale_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
40
+ def compuscale_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
42
41
  domain_type: DataType, range_type: DataType) -> "CompuScale":
43
42
  short_label = et_element.findtext("SHORT-LABEL")
44
43
  description = Description.from_et(et_element.find("DESC"), doc_frags)
@@ -56,7 +55,7 @@ class CompuScale:
56
55
  if (cce := et_element.find("COMPU-CONST")) is not None:
57
56
  compu_const = CompuConst.compuvalue_from_et(cce, data_type=range_type)
58
57
 
59
- compu_rational_coeffs: Optional[CompuRationalCoeffs] = None
58
+ compu_rational_coeffs: CompuRationalCoeffs | None = None
60
59
  if (crc_elem := et_element.find("COMPU-RATIONAL-COEFFS")) is not None:
61
60
  compu_rational_coeffs = CompuRationalCoeffs.coeffs_from_et(
62
61
  crc_elem, doc_frags, value_type=range_type)
@@ -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, odxrequire
@@ -17,7 +16,7 @@ from .texttablecompumethod import TexttableCompuMethod
17
16
 
18
17
 
19
18
  def create_any_compu_method_from_et(et_element: ElementTree.Element,
20
- doc_frags: List[OdxDocFragment], *, internal_type: DataType,
19
+ doc_frags: list[OdxDocFragment], *, internal_type: DataType,
21
20
  physical_type: DataType) -> CompuMethod:
22
21
  compu_category = odxrequire(et_element.findtext("CATEGORY"))
23
22
 
@@ -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 ..exceptions import odxassert
@@ -18,7 +17,7 @@ class IdenticalCompuMethod(CompuMethod):
18
17
  """
19
18
 
20
19
  @staticmethod
21
- def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
20
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment], *,
22
21
  internal_type: DataType,
23
22
  physical_type: DataType) -> "IdenticalCompuMethod":
24
23
  cm = CompuMethod.compu_method_from_et(
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from enum import Enum
3
+
4
+
5
+ class IntervalType(Enum):
6
+ OPEN = "OPEN"
7
+ CLOSED = "CLOSED"
8
+ INFINITE = "INFINITE"