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