odxtools 10.0.0__py3-none-any.whl → 10.1.1__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 (175) hide show
  1. odxtools/additionalaudience.py +5 -5
  2. odxtools/admindata.py +10 -9
  3. odxtools/audience.py +15 -15
  4. odxtools/basecomparam.py +7 -6
  5. odxtools/basevariantpattern.py +7 -7
  6. odxtools/basicstructure.py +9 -9
  7. odxtools/cli/_print_utils.py +1 -1
  8. odxtools/cli/browse.py +1 -1
  9. odxtools/cli/compare.py +143 -170
  10. odxtools/cli/list.py +1 -1
  11. odxtools/commrelation.py +14 -13
  12. odxtools/companydata.py +11 -11
  13. odxtools/companydocinfo.py +11 -13
  14. odxtools/companyrevisioninfo.py +7 -7
  15. odxtools/companyspecificinfo.py +9 -11
  16. odxtools/comparam.py +6 -5
  17. odxtools/comparaminstance.py +10 -10
  18. odxtools/comparamspec.py +8 -9
  19. odxtools/comparamsubset.py +14 -22
  20. odxtools/complexcomparam.py +10 -10
  21. odxtools/complexdop.py +1 -1
  22. odxtools/compositecodec.py +3 -3
  23. odxtools/compumethods/compucodecompumethod.py +4 -4
  24. odxtools/compumethods/compuconst.py +3 -3
  25. odxtools/compumethods/compudefaultvalue.py +2 -2
  26. odxtools/compumethods/compuinternaltophys.py +11 -10
  27. odxtools/compumethods/compumethod.py +8 -7
  28. odxtools/compumethods/compuphystointernal.py +11 -10
  29. odxtools/compumethods/compurationalcoeffs.py +6 -6
  30. odxtools/compumethods/compuscale.py +14 -14
  31. odxtools/compumethods/createanycompumethod.py +12 -12
  32. odxtools/compumethods/identicalcompumethod.py +4 -4
  33. odxtools/compumethods/limit.py +8 -8
  34. odxtools/compumethods/linearcompumethod.py +4 -4
  35. odxtools/compumethods/linearsegment.py +8 -8
  36. odxtools/compumethods/ratfunccompumethod.py +4 -4
  37. odxtools/compumethods/ratfuncsegment.py +8 -8
  38. odxtools/compumethods/scalelinearcompumethod.py +5 -5
  39. odxtools/compumethods/scaleratfunccompumethod.py +4 -4
  40. odxtools/compumethods/tabintpcompumethod.py +12 -12
  41. odxtools/compumethods/texttablecompumethod.py +4 -4
  42. odxtools/createanycomparam.py +4 -4
  43. odxtools/createanydiagcodedtype.py +7 -7
  44. odxtools/database.py +28 -26
  45. odxtools/dataobjectproperty.py +15 -16
  46. odxtools/description.py +7 -7
  47. odxtools/determinenumberofitems.py +6 -5
  48. odxtools/diagcodedtype.py +6 -6
  49. odxtools/diagcomm.py +26 -27
  50. odxtools/diagdatadictionaryspec.py +34 -34
  51. odxtools/diaglayercontainer.py +32 -31
  52. odxtools/diaglayers/basevariant.py +5 -4
  53. odxtools/diaglayers/basevariantraw.py +18 -19
  54. odxtools/diaglayers/diaglayer.py +5 -4
  55. odxtools/diaglayers/diaglayerraw.py +39 -48
  56. odxtools/diaglayers/ecushareddata.py +6 -6
  57. odxtools/diaglayers/ecushareddataraw.py +11 -12
  58. odxtools/diaglayers/ecuvariant.py +5 -4
  59. odxtools/diaglayers/ecuvariantraw.py +17 -18
  60. odxtools/diaglayers/functionalgroup.py +5 -5
  61. odxtools/diaglayers/functionalgroupraw.py +13 -14
  62. odxtools/diaglayers/hierarchyelement.py +9 -9
  63. odxtools/diaglayers/hierarchyelementraw.py +8 -9
  64. odxtools/diaglayers/protocol.py +4 -4
  65. odxtools/diaglayers/protocolraw.py +10 -11
  66. odxtools/diagnostictroublecode.py +12 -14
  67. odxtools/diagservice.py +19 -18
  68. odxtools/diagvariable.py +19 -20
  69. odxtools/docrevision.py +14 -13
  70. odxtools/dopbase.py +10 -11
  71. odxtools/dtcconnector.py +6 -5
  72. odxtools/dtcdop.py +15 -15
  73. odxtools/dynamicendmarkerfield.py +6 -6
  74. odxtools/dynamiclengthfield.py +6 -6
  75. odxtools/dyndefinedspec.py +7 -7
  76. odxtools/dynenddopref.py +7 -7
  77. odxtools/dyniddefmodeinfo.py +17 -17
  78. odxtools/ecuvariantpattern.py +6 -7
  79. odxtools/element.py +12 -12
  80. odxtools/endofpdufield.py +6 -7
  81. odxtools/envdataconnector.py +6 -6
  82. odxtools/environmentdata.py +7 -8
  83. odxtools/environmentdatadescription.py +13 -12
  84. odxtools/externalaccessmethod.py +4 -5
  85. odxtools/externaldoc.py +4 -4
  86. odxtools/field.py +12 -11
  87. odxtools/functionalclass.py +7 -7
  88. odxtools/inputparam.py +9 -8
  89. odxtools/internalconstr.py +10 -10
  90. odxtools/leadinglengthinfotype.py +5 -6
  91. odxtools/library.py +7 -6
  92. odxtools/linkeddtcdop.py +7 -6
  93. odxtools/matchingbasevariantparameter.py +5 -5
  94. odxtools/matchingparameter.py +6 -6
  95. odxtools/message.py +1 -1
  96. odxtools/minmaxlengthtype.py +6 -7
  97. odxtools/modification.py +5 -4
  98. odxtools/multiplexer.py +48 -12
  99. odxtools/multiplexercase.py +10 -10
  100. odxtools/multiplexerdefaultcase.py +8 -7
  101. odxtools/multiplexerswitchkey.py +6 -6
  102. odxtools/nameditemlist.py +1 -1
  103. odxtools/negoutputparam.py +6 -6
  104. odxtools/odxcategory.py +12 -24
  105. odxtools/odxdoccontext.py +16 -0
  106. odxtools/odxlink.py +11 -12
  107. odxtools/odxtypes.py +3 -3
  108. odxtools/outputparam.py +7 -6
  109. odxtools/parameters/codedconstparameter.py +6 -6
  110. odxtools/parameters/createanyparameter.py +15 -15
  111. odxtools/parameters/dynamicparameter.py +4 -5
  112. odxtools/parameters/lengthkeyparameter.py +6 -6
  113. odxtools/parameters/matchingrequestparameter.py +4 -4
  114. odxtools/parameters/nrcconstparameter.py +8 -8
  115. odxtools/parameters/parameter.py +12 -13
  116. odxtools/parameters/parameterwithdop.py +9 -9
  117. odxtools/parameters/physicalconstantparameter.py +5 -4
  118. odxtools/parameters/reservedparameter.py +4 -5
  119. odxtools/parameters/systemparameter.py +4 -5
  120. odxtools/parameters/tableentryparameter.py +6 -6
  121. odxtools/parameters/tablekeyparameter.py +12 -12
  122. odxtools/parameters/tablestructparameter.py +9 -9
  123. odxtools/parameters/valueparameter.py +6 -6
  124. odxtools/paramlengthinfotype.py +6 -7
  125. odxtools/parentref.py +12 -10
  126. odxtools/physicaldimension.py +12 -12
  127. odxtools/physicaltype.py +5 -5
  128. odxtools/posresponsesuppressible.py +11 -11
  129. odxtools/preconditionstateref.py +8 -8
  130. odxtools/progcode.py +9 -8
  131. odxtools/protstack.py +8 -7
  132. odxtools/relateddiagcommref.py +5 -5
  133. odxtools/relateddoc.py +8 -7
  134. odxtools/request.py +12 -13
  135. odxtools/response.py +12 -13
  136. odxtools/scaleconstr.py +8 -8
  137. odxtools/singleecujob.py +14 -13
  138. odxtools/snrefcontext.py +1 -1
  139. odxtools/specialdata.py +6 -5
  140. odxtools/specialdatagroup.py +13 -13
  141. odxtools/specialdatagroupcaption.py +5 -4
  142. odxtools/standardlengthtype.py +5 -13
  143. odxtools/state.py +5 -4
  144. odxtools/statechart.py +10 -9
  145. odxtools/statemachine.py +2 -2
  146. odxtools/statetransition.py +7 -7
  147. odxtools/statetransitionref.py +11 -11
  148. odxtools/staticfield.py +5 -4
  149. odxtools/structure.py +5 -5
  150. odxtools/subcomponent.py +18 -16
  151. odxtools/subcomponentparamconnector.py +8 -7
  152. odxtools/subcomponentpattern.py +7 -7
  153. odxtools/swvariable.py +6 -6
  154. odxtools/table.py +20 -21
  155. odxtools/tablediagcommconnector.py +7 -6
  156. odxtools/tablerow.py +57 -36
  157. odxtools/tablerowconnector.py +6 -6
  158. odxtools/teammember.py +14 -13
  159. odxtools/templates/macros/printParentRef.xml.jinja2 +3 -1
  160. odxtools/text.py +4 -4
  161. odxtools/unit.py +9 -8
  162. odxtools/unitgroup.py +9 -8
  163. odxtools/unitspec.py +15 -16
  164. odxtools/variablegroup.py +4 -5
  165. odxtools/variantpattern.py +3 -4
  166. odxtools/version.py +2 -2
  167. odxtools/writepdxfile.py +0 -19
  168. odxtools/xdoc.py +11 -10
  169. {odxtools-10.0.0.dist-info → odxtools-10.1.1.dist-info}/METADATA +1 -1
  170. odxtools-10.1.1.dist-info/RECORD +265 -0
  171. {odxtools-10.0.0.dist-info → odxtools-10.1.1.dist-info}/WHEEL +1 -1
  172. odxtools-10.0.0.dist-info/RECORD +0 -264
  173. {odxtools-10.0.0.dist-info → odxtools-10.1.1.dist-info}/entry_points.txt +0 -0
  174. {odxtools-10.0.0.dist-info → odxtools-10.1.1.dist-info}/licenses/LICENSE +0 -0
  175. {odxtools-10.0.0.dist-info → odxtools-10.1.1.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,8 @@ from .dopbase import DopBase
12
12
  from .encodestate import EncodeState
13
13
  from .exceptions import EncodeError, odxraise, odxrequire
14
14
  from .internalconstr import InternalConstr
15
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
15
+ from .odxdoccontext import OdxDocContext
16
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
16
17
  from .odxtypes import AtomicOdxType, BytesTypes, ParameterValue
17
18
  from .physicaltype import PhysicalType
18
19
  from .snrefcontext import SnRefContext
@@ -20,7 +21,7 @@ from .unit import Unit
20
21
  from .utils import dataclass_fields_asdict
21
22
 
22
23
 
23
- @dataclass
24
+ @dataclass(kw_only=True)
24
25
  class DataObjectProperty(DopBase):
25
26
  """This class represents a DATA-OBJECT-PROP.
26
27
 
@@ -37,42 +38,40 @@ class DataObjectProperty(DopBase):
37
38
  #: The type of the value in the physical world
38
39
  physical_type: PhysicalType
39
40
 
40
- internal_constr: InternalConstr | None
41
+ internal_constr: InternalConstr | None = None
41
42
 
42
43
  #: The unit associated with physical values (e.g. 'm/s^2')
43
- unit_ref: OdxLinkRef | None
44
+ unit_ref: OdxLinkRef | None = None
44
45
 
45
- physical_constr: InternalConstr | None
46
+ physical_constr: InternalConstr | None = None
46
47
 
47
48
  @property
48
49
  def unit(self) -> Unit | None:
49
50
  return self._unit
50
51
 
51
52
  @staticmethod
52
- def from_et(et_element: ElementTree.Element,
53
- doc_frags: list[OdxDocFragment]) -> "DataObjectProperty":
53
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DataObjectProperty":
54
54
  """Reads a DATA-OBJECT-PROP."""
55
- kwargs = dataclass_fields_asdict(DopBase.from_et(et_element, doc_frags))
55
+ kwargs = dataclass_fields_asdict(DopBase.from_et(et_element, context))
56
56
 
57
57
  diag_coded_type = create_any_diag_coded_type_from_et(
58
- odxrequire(et_element.find("DIAG-CODED-TYPE")), doc_frags)
59
- physical_type = PhysicalType.from_et(
60
- odxrequire(et_element.find("PHYSICAL-TYPE")), doc_frags)
58
+ odxrequire(et_element.find("DIAG-CODED-TYPE")), context)
59
+ physical_type = PhysicalType.from_et(odxrequire(et_element.find("PHYSICAL-TYPE")), context)
61
60
  compu_method = create_any_compu_method_from_et(
62
61
  odxrequire(et_element.find("COMPU-METHOD")),
63
- doc_frags,
62
+ context,
64
63
  internal_type=diag_coded_type.base_data_type,
65
64
  physical_type=physical_type.base_data_type,
66
65
  )
67
66
  internal_constr = None
68
67
  if (internal_constr_elem := et_element.find("INTERNAL-CONSTR")) is not None:
69
68
  internal_constr = InternalConstr.constr_from_et(
70
- internal_constr_elem, doc_frags, value_type=diag_coded_type.base_data_type)
71
- unit_ref = OdxLinkRef.from_et(et_element.find("UNIT-REF"), doc_frags)
69
+ internal_constr_elem, context, value_type=diag_coded_type.base_data_type)
70
+ unit_ref = OdxLinkRef.from_et(et_element.find("UNIT-REF"), context)
72
71
  physical_constr = None
73
72
  if (physical_constr_elem := et_element.find("PHYS-CONSTR")) is not None:
74
73
  physical_constr = InternalConstr.constr_from_et(
75
- physical_constr_elem, doc_frags, value_type=physical_type.base_data_type)
74
+ physical_constr_elem, context, value_type=physical_type.base_data_type)
76
75
 
77
76
  return DataObjectProperty(
78
77
  compu_method=compu_method,
@@ -118,7 +117,7 @@ class DataObjectProperty(DopBase):
118
117
  f"The value {repr(physical_value)} of type {type(physical_value).__name__}"
119
118
  f" is not a valid.")
120
119
 
121
- if not isinstance(physical_value, int | float | str | BytesTypes):
120
+ if not isinstance(physical_value, (int, float, str, BytesTypes)):
122
121
  odxraise(f"Invalid type '{type(physical_value).__name__}' for physical value. "
123
122
  f"(Expect atomic type!)")
124
123
  internal_value = self.compu_method.convert_physical_to_internal(physical_value)
odxtools/description.py CHANGED
@@ -1,22 +1,22 @@
1
- from dataclasses import dataclass
1
+ from dataclasses import dataclass, field
2
2
  from typing import Optional
3
3
  from xml.etree import ElementTree
4
4
 
5
5
  from .exceptions import odxrequire
6
6
  from .externaldoc import ExternalDoc
7
- from .odxlink import OdxDocFragment
7
+ from .odxdoccontext import OdxDocContext
8
8
 
9
9
 
10
- @dataclass
10
+ @dataclass(kw_only=True)
11
11
  class Description:
12
12
  text: str
13
- external_docs: list[ExternalDoc]
13
+ external_docs: list[ExternalDoc] = field(default_factory=list)
14
14
 
15
- text_identifier: str | None
15
+ text_identifier: str | None = None
16
16
 
17
17
  @staticmethod
18
18
  def from_et(et_element: ElementTree.Element | None,
19
- doc_frags: list[OdxDocFragment]) -> Optional["Description"]:
19
+ context: OdxDocContext) -> Optional["Description"]:
20
20
  if et_element is None:
21
21
  return None
22
22
 
@@ -35,7 +35,7 @@ class Description:
35
35
 
36
36
  external_docs = \
37
37
  [
38
- odxrequire(ExternalDoc.from_et(ed, doc_frags)) for ed in et_element.iterfind("EXTERNAL-DOCS/EXTERNAL-DOC")
38
+ odxrequire(ExternalDoc.from_et(ed, context)) for ed in et_element.iterfind("EXTERNAL-DOCS/EXTERNAL-DOC")
39
39
  ]
40
40
 
41
41
  text_identifier = et_element.attrib.get("TI")
@@ -5,17 +5,18 @@ from xml.etree import ElementTree
5
5
 
6
6
  from .dataobjectproperty import DataObjectProperty
7
7
  from .exceptions import odxrequire
8
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
8
+ from .odxdoccontext import OdxDocContext
9
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
9
10
  from .snrefcontext import SnRefContext
10
11
 
11
12
 
12
- @dataclass
13
+ @dataclass(kw_only=True)
13
14
  class DetermineNumberOfItems:
14
15
  """
15
16
  The object that determines the number of items of dynamic fields
16
17
  """
17
18
  byte_position: int
18
- bit_position: int | None
19
+ bit_position: int | None = None
19
20
  dop_ref: OdxLinkRef
20
21
 
21
22
  @property
@@ -24,11 +25,11 @@ class DetermineNumberOfItems:
24
25
 
25
26
  @staticmethod
26
27
  def from_et(et_element: ElementTree.Element,
27
- doc_frags: list[OdxDocFragment]) -> "DetermineNumberOfItems":
28
+ context: OdxDocContext) -> "DetermineNumberOfItems":
28
29
  byte_position = int(odxrequire(et_element.findtext("BYTE-POSITION")))
29
30
  bit_position_str = et_element.findtext("BIT-POSITION")
30
31
  bit_position = int(bit_position_str) if bit_position_str is not None else None
31
- dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DATA-OBJECT-PROP-REF"), doc_frags))
32
+ dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DATA-OBJECT-PROP-REF"), context))
32
33
 
33
34
  return DetermineNumberOfItems(
34
35
  byte_position=byte_position,
odxtools/diagcodedtype.py CHANGED
@@ -7,7 +7,8 @@ from .decodestate import DecodeState
7
7
  from .encodestate import EncodeState
8
8
  from .encoding import Encoding
9
9
  from .exceptions import odxassert, odxraise, odxrequire
10
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
10
+ from .odxdoccontext import OdxDocContext
11
+ from .odxlink import OdxLinkDatabase, OdxLinkId
11
12
  from .odxtypes import AtomicOdxType, DataType, odxstr_to_bool
12
13
  from .snrefcontext import SnRefContext
13
14
 
@@ -20,12 +21,12 @@ DctType = Literal[
20
21
  ]
21
22
 
22
23
 
23
- @dataclass
24
+ @dataclass(kw_only=True)
24
25
  class DiagCodedType:
25
- base_type_encoding: Encoding | None
26
+ base_type_encoding: Encoding | None = None
26
27
  base_data_type: DataType
27
28
 
28
- is_highlow_byte_order_raw: bool | None
29
+ is_highlow_byte_order_raw: bool | None = None
29
30
 
30
31
  @property
31
32
  def dct_type(self) -> DctType:
@@ -38,8 +39,7 @@ class DiagCodedType:
38
39
  return self.is_highlow_byte_order_raw in [None, True]
39
40
 
40
41
  @staticmethod
41
- def from_et(et_element: ElementTree.Element,
42
- doc_frags: list[OdxDocFragment]) -> "DiagCodedType":
42
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DiagCodedType":
43
43
  base_type_encoding = None
44
44
  if (base_type_encoding_str := et_element.get("BASE-TYPE-ENCODING")) is not None:
45
45
  try:
odxtools/diagcomm.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
2
+ from dataclasses import dataclass, field
3
3
  from typing import TYPE_CHECKING, Any
4
4
  from xml.etree import ElementTree
5
5
 
@@ -10,7 +10,8 @@ from .element import IdentifiableElement
10
10
  from .exceptions import odxraise, odxrequire
11
11
  from .functionalclass import FunctionalClass
12
12
  from .nameditemlist import NamedItemList
13
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
13
+ from .odxdoccontext import OdxDocContext
14
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
14
15
  from .odxtypes import odxstr_to_bool
15
16
  from .preconditionstateref import PreConditionStateRef
16
17
  from .relateddiagcommref import RelatedDiagCommRef
@@ -25,7 +26,7 @@ if TYPE_CHECKING:
25
26
  from .diaglayers.protocol import Protocol
26
27
 
27
28
 
28
- @dataclass
29
+ @dataclass(kw_only=True)
29
30
  class DiagComm(IdentifiableElement):
30
31
  """Representation of a diagnostic communication object.
31
32
 
@@ -34,21 +35,21 @@ class DiagComm(IdentifiableElement):
34
35
 
35
36
  """
36
37
 
37
- admin_data: AdminData | None
38
- sdgs: list[SpecialDataGroup]
39
- functional_class_refs: list[OdxLinkRef]
40
- audience: Audience | None
41
- protocol_snrefs: list[str]
42
- related_diag_comm_refs: list[RelatedDiagCommRef]
43
- pre_condition_state_refs: list[PreConditionStateRef]
44
- state_transition_refs: list[StateTransitionRef]
38
+ admin_data: AdminData | None = None
39
+ sdgs: list[SpecialDataGroup] = field(default_factory=list)
40
+ functional_class_refs: list[OdxLinkRef] = field(default_factory=list)
41
+ audience: Audience | None = None
42
+ protocol_snrefs: list[str] = field(default_factory=list)
43
+ related_diag_comm_refs: list[RelatedDiagCommRef] = field(default_factory=list)
44
+ pre_condition_state_refs: list[PreConditionStateRef] = field(default_factory=list)
45
+ state_transition_refs: list[StateTransitionRef] = field(default_factory=list)
45
46
 
46
47
  # attributes
47
- semantic: str | None
48
- diagnostic_class: DiagClassType | None
49
- is_mandatory_raw: bool | None
50
- is_executable_raw: bool | None
51
- is_final_raw: bool | None
48
+ semantic: str | None = None
49
+ diagnostic_class: DiagClassType | None = None
50
+ is_mandatory_raw: bool | None = None
51
+ is_executable_raw: bool | None = None
52
+ is_final_raw: bool | None = None
52
53
 
53
54
  @property
54
55
  def functional_classes(self) -> NamedItemList[FunctionalClass]:
@@ -83,22 +84,20 @@ class DiagComm(IdentifiableElement):
83
84
  return self.is_final_raw is True
84
85
 
85
86
  @staticmethod
86
- def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "DiagComm":
87
- kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
87
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DiagComm":
88
+ kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
88
89
 
89
- admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
90
- sdgs = [
91
- SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
92
- ]
90
+ admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), context)
91
+ sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
93
92
 
94
93
  functional_class_refs = [
95
- odxrequire(OdxLinkRef.from_et(el, doc_frags))
94
+ odxrequire(OdxLinkRef.from_et(el, context))
96
95
  for el in et_element.iterfind("FUNCT-CLASS-REFS/FUNCT-CLASS-REF")
97
96
  ]
98
97
 
99
98
  audience = None
100
99
  if (audience_elem := et_element.find("AUDIENCE")) is not None:
101
- audience = Audience.from_et(audience_elem, doc_frags)
100
+ audience = Audience.from_et(audience_elem, context)
102
101
 
103
102
  protocol_snrefs = [
104
103
  odxrequire(el.get("SHORT-NAME"))
@@ -106,17 +105,17 @@ class DiagComm(IdentifiableElement):
106
105
  ]
107
106
 
108
107
  related_diag_comm_refs = [
109
- RelatedDiagCommRef.from_et(el, doc_frags)
108
+ RelatedDiagCommRef.from_et(el, context)
110
109
  for el in et_element.iterfind("RELATED-DIAG-COMM-REFS/RELATED-DIAG-COMM-REF")
111
110
  ]
112
111
 
113
112
  pre_condition_state_refs = [
114
- PreConditionStateRef.from_et(el, doc_frags)
113
+ PreConditionStateRef.from_et(el, context)
115
114
  for el in et_element.iterfind("PRE-CONDITION-STATE-REFS/PRE-CONDITION-STATE-REF")
116
115
  ]
117
116
 
118
117
  state_transition_refs = [
119
- StateTransitionRef.from_et(el, doc_frags)
118
+ StateTransitionRef.from_et(el, context)
120
119
  for el in et_element.iterfind("STATE-TRANSITION-REFS/STATE-TRANSITION-REF")
121
120
  ]
122
121
 
@@ -1,5 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
2
+ from dataclasses import dataclass, field
3
3
  from itertools import chain
4
4
  from typing import Any
5
5
  from xml.etree import ElementTree
@@ -15,7 +15,8 @@ from .environmentdata import EnvironmentData
15
15
  from .environmentdatadescription import EnvironmentDataDescription
16
16
  from .multiplexer import Multiplexer
17
17
  from .nameditemlist import NamedItemList
18
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
18
+ from .odxdoccontext import OdxDocContext
19
+ from .odxlink import OdxLinkDatabase, OdxLinkId
19
20
  from .snrefcontext import SnRefContext
20
21
  from .specialdatagroup import SpecialDataGroup
21
22
  from .staticfield import StaticField
@@ -24,72 +25,73 @@ from .table import Table
24
25
  from .unitspec import UnitSpec
25
26
 
26
27
 
27
- @dataclass
28
+ @dataclass(kw_only=True)
28
29
  class DiagDataDictionarySpec:
29
- admin_data: AdminData | None
30
- dtc_dops: NamedItemList[DtcDop]
31
- env_data_descs: NamedItemList[EnvironmentDataDescription]
32
- data_object_props: NamedItemList[DataObjectProperty]
33
- structures: NamedItemList[Structure]
34
- static_fields: NamedItemList[StaticField]
35
- dynamic_length_fields: NamedItemList[DynamicLengthField]
36
- dynamic_endmarker_fields: NamedItemList[DynamicEndmarkerField]
37
- end_of_pdu_fields: NamedItemList[EndOfPduField]
38
- muxs: NamedItemList[Multiplexer]
39
- env_datas: NamedItemList[EnvironmentData]
40
- unit_spec: UnitSpec | None
41
- tables: NamedItemList[Table]
42
- sdgs: list[SpecialDataGroup]
30
+ admin_data: AdminData | None = None
31
+ dtc_dops: NamedItemList[DtcDop] = field(default_factory=NamedItemList)
32
+ env_data_descs: NamedItemList[EnvironmentDataDescription] = field(default_factory=NamedItemList)
33
+ data_object_props: NamedItemList[DataObjectProperty] = field(default_factory=NamedItemList)
34
+ structures: NamedItemList[Structure] = field(default_factory=NamedItemList)
35
+ static_fields: NamedItemList[StaticField] = field(default_factory=NamedItemList)
36
+ dynamic_length_fields: NamedItemList[DynamicLengthField] = field(default_factory=NamedItemList)
37
+ dynamic_endmarker_fields: NamedItemList[DynamicEndmarkerField] = field(
38
+ default_factory=NamedItemList)
39
+ end_of_pdu_fields: NamedItemList[EndOfPduField] = field(default_factory=NamedItemList)
40
+ muxs: NamedItemList[Multiplexer] = field(default_factory=NamedItemList)
41
+ env_datas: NamedItemList[EnvironmentData] = field(default_factory=NamedItemList)
42
+ unit_spec: UnitSpec | None = None
43
+ tables: NamedItemList[Table] = field(default_factory=NamedItemList)
44
+ sdgs: list[SpecialDataGroup] = field(default_factory=list)
43
45
 
44
46
  @staticmethod
45
47
  def from_et(et_element: ElementTree.Element,
46
- doc_frags: list[OdxDocFragment]) -> "DiagDataDictionarySpec":
48
+ context: OdxDocContext) -> "DiagDataDictionarySpec":
47
49
  admin_data = None
48
50
  if (admin_data_elem := et_element.find("ADMIN-DATA")) is not None:
49
- admin_data = AdminData.from_et(admin_data_elem, doc_frags)
51
+ admin_data = AdminData.from_et(admin_data_elem, context)
50
52
 
51
53
  dtc_dops = NamedItemList([
52
- DtcDop.from_et(dtc_dop_elem, doc_frags)
54
+ DtcDop.from_et(dtc_dop_elem, context)
53
55
  for dtc_dop_elem in et_element.iterfind("DTC-DOPS/DTC-DOP")
54
56
  ])
55
57
 
56
58
  env_data_descs = NamedItemList([
57
- EnvironmentDataDescription.from_et(env_data_desc_element, doc_frags)
59
+ EnvironmentDataDescription.from_et(env_data_desc_element, context)
58
60
  for env_data_desc_element in et_element.iterfind("ENV-DATA-DESCS/ENV-DATA-DESC")
59
61
  ])
60
62
 
61
63
  data_object_props = NamedItemList([
62
- DataObjectProperty.from_et(dop_element, doc_frags)
64
+ DataObjectProperty.from_et(dop_element, context)
63
65
  for dop_element in et_element.iterfind("DATA-OBJECT-PROPS/DATA-OBJECT-PROP")
64
66
  ])
65
67
 
66
68
  structures = NamedItemList([
67
- Structure.from_et(structure_element, doc_frags)
69
+ Structure.from_et(structure_element, context)
68
70
  for structure_element in et_element.iterfind("STRUCTURES/STRUCTURE")
69
71
  ])
70
72
 
71
73
  static_fields = NamedItemList([
72
- StaticField.from_et(dl_element, doc_frags)
74
+ StaticField.from_et(dl_element, context)
73
75
  for dl_element in et_element.iterfind("STATIC-FIELDS/STATIC-FIELD")
74
76
  ])
75
77
 
76
78
  dynamic_length_fields = NamedItemList([
77
- DynamicLengthField.from_et(dl_element, doc_frags)
79
+ DynamicLengthField.from_et(dl_element, context)
78
80
  for dl_element in et_element.iterfind("DYNAMIC-LENGTH-FIELDS/DYNAMIC-LENGTH-FIELD")
79
81
  ])
80
82
 
81
83
  dynamic_endmarker_fields = NamedItemList([
82
- DynamicEndmarkerField.from_et(dl_element, doc_frags) for dl_element in
84
+ DynamicEndmarkerField.from_et(dl_element, context) for dl_element in
83
85
  et_element.iterfind("DYNAMIC-ENDMARKER-FIELDS/DYNAMIC-ENDMARKER-FIELD")
84
86
  ])
85
87
 
86
88
  end_of_pdu_fields = NamedItemList([
87
- EndOfPduField.from_et(eofp_element, doc_frags)
89
+ EndOfPduField.from_et(eofp_element, context)
88
90
  for eofp_element in et_element.iterfind("END-OF-PDU-FIELDS/END-OF-PDU-FIELD")
89
91
  ])
90
92
 
91
93
  muxs = NamedItemList([
92
- Multiplexer.from_et(mux_element, doc_frags)
94
+ Multiplexer.from_et(mux_element, context)
93
95
  for mux_element in et_element.iterfind("MUXS/MUX")
94
96
  ])
95
97
 
@@ -99,23 +101,21 @@ class DiagDataDictionarySpec:
99
101
  et_element.iterfind("ENV-DATA-DESCS/ENV-DATA-DESC/ENV-DATAS/ENV-DATA"),
100
102
  )
101
103
  env_datas = NamedItemList([
102
- EnvironmentData.from_et(env_data_element, doc_frags)
104
+ EnvironmentData.from_et(env_data_element, context)
103
105
  for env_data_element in env_data_elements
104
106
  ])
105
107
 
106
108
  if (spec_elem := et_element.find("UNIT-SPEC")) is not None:
107
- unit_spec = UnitSpec.from_et(spec_elem, doc_frags)
109
+ unit_spec = UnitSpec.from_et(spec_elem, context)
108
110
  else:
109
111
  unit_spec = None
110
112
 
111
113
  tables = NamedItemList([
112
- Table.from_et(table_element, doc_frags)
114
+ Table.from_et(table_element, context)
113
115
  for table_element in et_element.iterfind("TABLES/TABLE")
114
116
  ])
115
117
 
116
- sdgs = [
117
- SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
118
- ]
118
+ sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
119
119
 
120
120
  return DiagDataDictionarySpec(
121
121
  admin_data=admin_data,
@@ -1,5 +1,5 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
2
+ from dataclasses import dataclass, field
3
3
  from itertools import chain
4
4
  from typing import TYPE_CHECKING, Any
5
5
  from xml.etree import ElementTree
@@ -10,8 +10,10 @@ from .diaglayers.ecushareddata import EcuSharedData
10
10
  from .diaglayers.ecuvariant import EcuVariant
11
11
  from .diaglayers.functionalgroup import FunctionalGroup
12
12
  from .diaglayers.protocol import Protocol
13
+ from .exceptions import odxrequire
13
14
  from .nameditemlist import NamedItemList
14
15
  from .odxcategory import OdxCategory
16
+ from .odxdoccontext import OdxDocContext
15
17
  from .odxlink import DocType, OdxDocFragment, OdxLinkDatabase, OdxLinkId
16
18
  from .snrefcontext import SnRefContext
17
19
  from .utils import dataclass_fields_asdict
@@ -20,13 +22,13 @@ if TYPE_CHECKING:
20
22
  from .database import Database
21
23
 
22
24
 
23
- @dataclass
25
+ @dataclass(kw_only=True)
24
26
  class DiagLayerContainer(OdxCategory):
25
- protocols: NamedItemList[Protocol]
26
- functional_groups: NamedItemList[FunctionalGroup]
27
- ecu_shared_datas: NamedItemList[EcuSharedData]
28
- base_variants: NamedItemList[BaseVariant]
29
- ecu_variants: NamedItemList[EcuVariant]
27
+ protocols: NamedItemList[Protocol] = field(default_factory=NamedItemList)
28
+ functional_groups: NamedItemList[FunctionalGroup] = field(default_factory=NamedItemList)
29
+ ecu_shared_datas: NamedItemList[EcuSharedData] = field(default_factory=NamedItemList)
30
+ base_variants: NamedItemList[BaseVariant] = field(default_factory=NamedItemList)
31
+ ecu_variants: NamedItemList[EcuVariant] = field(default_factory=NamedItemList)
30
32
 
31
33
  @property
32
34
  def diag_layers(self) -> NamedItemList[DiagLayer]:
@@ -40,33 +42,32 @@ class DiagLayerContainer(OdxCategory):
40
42
  return self.ecu_variants
41
43
 
42
44
  @staticmethod
43
- def from_et(et_element: ElementTree.Element,
44
- doc_frags: list[OdxDocFragment]) -> "DiagLayerContainer":
45
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DiagLayerContainer":
45
46
 
46
- cat = OdxCategory.category_from_et(et_element, doc_frags, doc_type=DocType.CONTAINER)
47
- doc_frags = cat.odx_id.doc_fragments
47
+ cat = OdxCategory.from_et(et_element, context)
48
48
  kwargs = dataclass_fields_asdict(cat)
49
49
 
50
- protocols = NamedItemList([
51
- Protocol.from_et(dl_element, doc_frags)
52
- for dl_element in et_element.iterfind("PROTOCOLS/PROTOCOL")
53
- ])
54
- functional_groups = NamedItemList([
55
- FunctionalGroup.from_et(dl_element, doc_frags)
56
- for dl_element in et_element.iterfind("FUNCTIONAL-GROUPS/FUNCTIONAL-GROUP")
57
- ])
58
- ecu_shared_datas = NamedItemList([
59
- EcuSharedData.from_et(dl_element, doc_frags)
60
- for dl_element in et_element.iterfind("ECU-SHARED-DATAS/ECU-SHARED-DATA")
61
- ])
62
- base_variants = NamedItemList([
63
- BaseVariant.from_et(dl_element, doc_frags)
64
- for dl_element in et_element.iterfind("BASE-VARIANTS/BASE-VARIANT")
65
- ])
66
- ecu_variants = NamedItemList([
67
- EcuVariant.from_et(dl_element, doc_frags)
68
- for dl_element in et_element.iterfind("ECU-VARIANTS/ECU-VARIANT")
69
- ])
50
+ def get_layer_context(diag_layer_et: ElementTree.Element) -> OdxDocContext:
51
+ layer_sn = odxrequire(diag_layer_et.findtext("SHORT-NAME"))
52
+ layer_docfrag = OdxDocFragment(layer_sn, DocType.LAYER)
53
+ # add layer doc fragment to container doc fragment
54
+ return OdxDocContext(context.version, (context.doc_fragments[0], layer_docfrag))
55
+
56
+ protocols = NamedItemList(
57
+ Protocol.from_et(layer_et, get_layer_context(layer_et))
58
+ for layer_et in et_element.iterfind("PROTOCOLS/PROTOCOL"))
59
+ functional_groups = NamedItemList(
60
+ FunctionalGroup.from_et(layer_et, get_layer_context(layer_et))
61
+ for layer_et in et_element.iterfind("FUNCTIONAL-GROUPS/FUNCTIONAL-GROUP"))
62
+ ecu_shared_datas = NamedItemList(
63
+ EcuSharedData.from_et(layer_et, get_layer_context(layer_et))
64
+ for layer_et in et_element.iterfind("ECU-SHARED-DATAS/ECU-SHARED-DATA"))
65
+ base_variants = NamedItemList(
66
+ BaseVariant.from_et(layer_et, get_layer_context(layer_et))
67
+ for layer_et in et_element.iterfind("BASE-VARIANTS/BASE-VARIANT"))
68
+ ecu_variants = NamedItemList(
69
+ EcuVariant.from_et(layer_et, get_layer_context(layer_et))
70
+ for layer_et in et_element.iterfind("ECU-VARIANTS/ECU-VARIANT"))
70
71
 
71
72
  return DiagLayerContainer(
72
73
  protocols=protocols,
@@ -12,7 +12,8 @@ from ..diagvariable import DiagVariable
12
12
  from ..dyndefinedspec import DynDefinedSpec
13
13
  from ..exceptions import odxassert
14
14
  from ..nameditemlist import NamedItemList
15
- from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkRef
15
+ from ..odxdoccontext import OdxDocContext
16
+ from ..odxlink import OdxLinkDatabase, OdxLinkRef
16
17
  from ..parentref import ParentRef
17
18
  from ..variablegroup import VariableGroup
18
19
  from .basevariantraw import BaseVariantRaw
@@ -20,7 +21,7 @@ from .diaglayer import DiagLayer
20
21
  from .hierarchyelement import HierarchyElement
21
22
 
22
23
 
23
- @dataclass
24
+ @dataclass(kw_only=True)
24
25
  class BaseVariant(HierarchyElement):
25
26
  """This is a diagnostic layer for common functionality of an ECU
26
27
  """
@@ -68,8 +69,8 @@ class BaseVariant(HierarchyElement):
68
69
  #######
69
70
 
70
71
  @staticmethod
71
- def from_et(et_element: ElementTree.Element, doc_frags: list[OdxDocFragment]) -> "BaseVariant":
72
- base_variant_raw = BaseVariantRaw.from_et(et_element, doc_frags)
72
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "BaseVariant":
73
+ base_variant_raw = BaseVariantRaw.from_et(et_element, context)
73
74
 
74
75
  return BaseVariant(diag_layer_raw=base_variant_raw)
75
76