odxtools 6.6.1__py3-none-any.whl → 9.3.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 (222) hide show
  1. odxtools/__init__.py +7 -5
  2. odxtools/additionalaudience.py +3 -5
  3. odxtools/admindata.py +5 -7
  4. odxtools/audience.py +10 -13
  5. odxtools/basecomparam.py +3 -5
  6. odxtools/basicstructure.py +55 -241
  7. odxtools/cli/_parser_utils.py +16 -1
  8. odxtools/cli/_print_utils.py +169 -134
  9. odxtools/cli/browse.py +127 -103
  10. odxtools/cli/compare.py +114 -87
  11. odxtools/cli/decode.py +2 -1
  12. odxtools/cli/dummy_sub_parser.py +3 -1
  13. odxtools/cli/find.py +2 -1
  14. odxtools/cli/list.py +26 -16
  15. odxtools/cli/main.py +1 -0
  16. odxtools/cli/snoop.py +32 -6
  17. odxtools/codec.py +211 -0
  18. odxtools/commrelation.py +122 -0
  19. odxtools/companydata.py +5 -7
  20. odxtools/companydocinfo.py +7 -8
  21. odxtools/companyrevisioninfo.py +3 -5
  22. odxtools/companyspecificinfo.py +8 -9
  23. odxtools/comparam.py +4 -6
  24. odxtools/comparaminstance.py +14 -14
  25. odxtools/comparamspec.py +16 -54
  26. odxtools/comparamsubset.py +22 -62
  27. odxtools/complexcomparam.py +5 -7
  28. odxtools/compumethods/compucodecompumethod.py +63 -0
  29. odxtools/compumethods/compuconst.py +31 -0
  30. odxtools/compumethods/compudefaultvalue.py +27 -0
  31. odxtools/compumethods/compuinternaltophys.py +56 -0
  32. odxtools/compumethods/compuinversevalue.py +7 -0
  33. odxtools/compumethods/compumethod.py +94 -15
  34. odxtools/compumethods/compuphystointernal.py +56 -0
  35. odxtools/compumethods/compurationalcoeffs.py +20 -9
  36. odxtools/compumethods/compuscale.py +67 -32
  37. odxtools/compumethods/createanycompumethod.py +31 -172
  38. odxtools/compumethods/identicalcompumethod.py +31 -6
  39. odxtools/compumethods/limit.py +70 -36
  40. odxtools/compumethods/linearcompumethod.py +70 -181
  41. odxtools/compumethods/linearsegment.py +190 -0
  42. odxtools/compumethods/ratfunccompumethod.py +106 -0
  43. odxtools/compumethods/ratfuncsegment.py +87 -0
  44. odxtools/compumethods/scalelinearcompumethod.py +132 -26
  45. odxtools/compumethods/scaleratfunccompumethod.py +113 -0
  46. odxtools/compumethods/tabintpcompumethod.py +123 -92
  47. odxtools/compumethods/texttablecompumethod.py +117 -57
  48. odxtools/createanydiagcodedtype.py +10 -67
  49. odxtools/database.py +167 -87
  50. odxtools/dataobjectproperty.py +25 -32
  51. odxtools/decodestate.py +14 -17
  52. odxtools/description.py +47 -0
  53. odxtools/determinenumberofitems.py +4 -5
  54. odxtools/diagcodedtype.py +37 -106
  55. odxtools/diagcomm.py +24 -12
  56. odxtools/diagdatadictionaryspec.py +120 -96
  57. odxtools/diaglayercontainer.py +46 -54
  58. odxtools/diaglayers/basevariant.py +128 -0
  59. odxtools/diaglayers/basevariantraw.py +123 -0
  60. odxtools/diaglayers/diaglayer.py +432 -0
  61. odxtools/{diaglayerraw.py → diaglayers/diaglayerraw.py} +105 -120
  62. odxtools/diaglayers/diaglayertype.py +42 -0
  63. odxtools/diaglayers/ecushareddata.py +96 -0
  64. odxtools/diaglayers/ecushareddataraw.py +87 -0
  65. odxtools/diaglayers/ecuvariant.py +124 -0
  66. odxtools/diaglayers/ecuvariantraw.py +129 -0
  67. odxtools/diaglayers/functionalgroup.py +110 -0
  68. odxtools/diaglayers/functionalgroupraw.py +106 -0
  69. odxtools/{diaglayer.py → diaglayers/hierarchyelement.py} +273 -472
  70. odxtools/diaglayers/hierarchyelementraw.py +58 -0
  71. odxtools/diaglayers/protocol.py +64 -0
  72. odxtools/diaglayers/protocolraw.py +91 -0
  73. odxtools/diagnostictroublecode.py +8 -9
  74. odxtools/diagservice.py +57 -44
  75. odxtools/diagvariable.py +113 -0
  76. odxtools/docrevision.py +5 -7
  77. odxtools/dopbase.py +15 -15
  78. odxtools/dtcdop.py +170 -50
  79. odxtools/dynamicendmarkerfield.py +134 -0
  80. odxtools/dynamiclengthfield.py +47 -42
  81. odxtools/dyndefinedspec.py +177 -0
  82. odxtools/dynenddopref.py +38 -0
  83. odxtools/ecuvariantmatcher.py +6 -7
  84. odxtools/element.py +13 -15
  85. odxtools/encodestate.py +199 -22
  86. odxtools/endofpdufield.py +31 -18
  87. odxtools/environmentdata.py +8 -1
  88. odxtools/environmentdatadescription.py +198 -36
  89. odxtools/exceptions.py +11 -2
  90. odxtools/field.py +10 -10
  91. odxtools/functionalclass.py +3 -5
  92. odxtools/inputparam.py +3 -12
  93. odxtools/internalconstr.py +14 -5
  94. odxtools/isotp_state_machine.py +14 -6
  95. odxtools/leadinglengthinfotype.py +37 -18
  96. odxtools/library.py +66 -0
  97. odxtools/loadfile.py +64 -0
  98. odxtools/matchingparameter.py +3 -3
  99. odxtools/message.py +0 -7
  100. odxtools/minmaxlengthtype.py +61 -33
  101. odxtools/modification.py +3 -5
  102. odxtools/multiplexer.py +135 -75
  103. odxtools/multiplexercase.py +39 -18
  104. odxtools/multiplexerdefaultcase.py +15 -12
  105. odxtools/multiplexerswitchkey.py +4 -5
  106. odxtools/nameditemlist.py +33 -8
  107. odxtools/negoutputparam.py +3 -5
  108. odxtools/odxcategory.py +83 -0
  109. odxtools/odxlink.py +62 -53
  110. odxtools/odxtypes.py +93 -8
  111. odxtools/outputparam.py +5 -16
  112. odxtools/parameterinfo.py +219 -61
  113. odxtools/parameters/codedconstparameter.py +45 -32
  114. odxtools/parameters/createanyparameter.py +19 -193
  115. odxtools/parameters/dynamicparameter.py +25 -4
  116. odxtools/parameters/lengthkeyparameter.py +83 -25
  117. odxtools/parameters/matchingrequestparameter.py +48 -18
  118. odxtools/parameters/nrcconstparameter.py +76 -54
  119. odxtools/parameters/parameter.py +97 -73
  120. odxtools/parameters/parameterwithdop.py +41 -38
  121. odxtools/parameters/physicalconstantparameter.py +41 -20
  122. odxtools/parameters/reservedparameter.py +36 -18
  123. odxtools/parameters/systemparameter.py +74 -7
  124. odxtools/parameters/tableentryparameter.py +47 -7
  125. odxtools/parameters/tablekeyparameter.py +142 -55
  126. odxtools/parameters/tablestructparameter.py +79 -58
  127. odxtools/parameters/valueparameter.py +39 -21
  128. odxtools/paramlengthinfotype.py +56 -33
  129. odxtools/parentref.py +20 -3
  130. odxtools/physicaldimension.py +3 -8
  131. odxtools/progcode.py +26 -11
  132. odxtools/protstack.py +3 -5
  133. odxtools/py.typed +0 -0
  134. odxtools/relateddoc.py +7 -9
  135. odxtools/request.py +120 -10
  136. odxtools/response.py +123 -23
  137. odxtools/scaleconstr.py +14 -8
  138. odxtools/servicebinner.py +1 -1
  139. odxtools/singleecujob.py +12 -10
  140. odxtools/snrefcontext.py +29 -0
  141. odxtools/specialdata.py +3 -5
  142. odxtools/specialdatagroup.py +7 -9
  143. odxtools/specialdatagroupcaption.py +3 -6
  144. odxtools/standardlengthtype.py +80 -14
  145. odxtools/state.py +3 -5
  146. odxtools/statechart.py +13 -19
  147. odxtools/statetransition.py +8 -18
  148. odxtools/staticfield.py +107 -0
  149. odxtools/subcomponent.py +288 -0
  150. odxtools/swvariable.py +21 -0
  151. odxtools/table.py +9 -9
  152. odxtools/tablerow.py +30 -15
  153. odxtools/teammember.py +3 -5
  154. odxtools/templates/comparam-spec.odx-c.xml.jinja2 +4 -24
  155. odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +5 -26
  156. odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +15 -31
  157. odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +1 -1
  158. odxtools/templates/macros/printAudience.xml.jinja2 +1 -1
  159. odxtools/templates/macros/printBaseVariant.xml.jinja2 +53 -0
  160. odxtools/templates/macros/printCompanyData.xml.jinja2 +4 -7
  161. odxtools/templates/macros/printComparam.xml.jinja2 +6 -4
  162. odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
  163. odxtools/templates/macros/printCompuMethod.xml.jinja2 +147 -0
  164. odxtools/templates/macros/printDOP.xml.jinja2 +27 -137
  165. odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
  166. odxtools/templates/macros/printDiagComm.xml.jinja2 +1 -1
  167. odxtools/templates/macros/printDiagLayer.xml.jinja2 +222 -0
  168. odxtools/templates/macros/printDiagVariable.xml.jinja2 +66 -0
  169. odxtools/templates/macros/printDynDefinedSpec.xml.jinja2 +48 -0
  170. odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +16 -0
  171. odxtools/templates/macros/printDynamicLengthField.xml.jinja2 +1 -1
  172. odxtools/templates/macros/printEcuSharedData.xml.jinja2 +30 -0
  173. odxtools/templates/macros/printEcuVariant.xml.jinja2 +53 -0
  174. odxtools/templates/macros/printEcuVariantPattern.xml.jinja2 +1 -1
  175. odxtools/templates/macros/printElementId.xml.jinja2 +8 -3
  176. odxtools/templates/macros/printEndOfPdu.xml.jinja2 +1 -1
  177. odxtools/templates/macros/printEnvDataDesc.xml.jinja2 +1 -1
  178. odxtools/templates/macros/printFunctionalClass.xml.jinja2 +1 -1
  179. odxtools/templates/macros/printFunctionalGroup.xml.jinja2 +40 -0
  180. odxtools/templates/macros/printHierarchyElement.xml.jinja2 +24 -0
  181. odxtools/templates/macros/printLibrary.xml.jinja2 +21 -0
  182. odxtools/templates/macros/printMux.xml.jinja2 +5 -3
  183. odxtools/templates/macros/printOdxCategory.xml.jinja2 +28 -0
  184. odxtools/templates/macros/printParam.xml.jinja2 +18 -19
  185. odxtools/templates/macros/printProtStack.xml.jinja2 +1 -1
  186. odxtools/templates/macros/printProtocol.xml.jinja2 +30 -0
  187. odxtools/templates/macros/printRequest.xml.jinja2 +1 -1
  188. odxtools/templates/macros/printResponse.xml.jinja2 +1 -1
  189. odxtools/templates/macros/printService.xml.jinja2 +3 -2
  190. odxtools/templates/macros/printSingleEcuJob.xml.jinja2 +5 -26
  191. odxtools/templates/macros/printSpecialData.xml.jinja2 +1 -1
  192. odxtools/templates/macros/printState.xml.jinja2 +1 -1
  193. odxtools/templates/macros/printStateChart.xml.jinja2 +1 -1
  194. odxtools/templates/macros/printStateTransition.xml.jinja2 +1 -1
  195. odxtools/templates/macros/printStaticField.xml.jinja2 +15 -0
  196. odxtools/templates/macros/printStructure.xml.jinja2 +1 -1
  197. odxtools/templates/macros/printSubComponent.xml.jinja2 +104 -0
  198. odxtools/templates/macros/printTable.xml.jinja2 +4 -5
  199. odxtools/templates/macros/printUnitSpec.xml.jinja2 +3 -5
  200. odxtools/uds.py +2 -10
  201. odxtools/unit.py +4 -8
  202. odxtools/unitgroup.py +3 -5
  203. odxtools/unitspec.py +17 -17
  204. odxtools/utils.py +38 -20
  205. odxtools/variablegroup.py +32 -0
  206. odxtools/version.py +2 -2
  207. odxtools/{write_pdx_file.py → writepdxfile.py} +22 -12
  208. odxtools/xdoc.py +3 -5
  209. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/METADATA +44 -33
  210. odxtools-9.3.0.dist-info/RECORD +228 -0
  211. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/WHEEL +1 -1
  212. odxtools/createcompanydatas.py +0 -17
  213. odxtools/createsdgs.py +0 -19
  214. odxtools/diaglayertype.py +0 -30
  215. odxtools/load_file.py +0 -13
  216. odxtools/load_odx_d_file.py +0 -6
  217. odxtools/load_pdx_file.py +0 -8
  218. odxtools/templates/macros/printVariant.xml.jinja2 +0 -208
  219. odxtools-6.6.1.dist-info/RECORD +0 -180
  220. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/LICENSE +0 -0
  221. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/entry_points.txt +0 -0
  222. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,124 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from copy import deepcopy
3
+ from dataclasses import dataclass
4
+ from typing import Any, Dict, Iterable, List, Optional, Union, cast
5
+ from xml.etree import ElementTree
6
+
7
+ from typing_extensions import override
8
+
9
+ from ..diagvariable import DiagVariable, HasDiagVariables
10
+ from ..dyndefinedspec import DynDefinedSpec
11
+ from ..ecuvariantpattern import EcuVariantPattern
12
+ from ..exceptions import odxassert
13
+ from ..nameditemlist import NamedItemList
14
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkRef
15
+ from ..parentref import ParentRef
16
+ from ..variablegroup import HasVariableGroups, VariableGroup
17
+ from .diaglayer import DiagLayer
18
+ from .ecuvariantraw import EcuVariantRaw
19
+ from .hierarchyelement import HierarchyElement
20
+
21
+
22
+ @dataclass
23
+ class EcuVariant(HierarchyElement):
24
+
25
+ @property
26
+ def ecu_variant_raw(self) -> EcuVariantRaw:
27
+ return cast(EcuVariantRaw, self.diag_layer_raw)
28
+
29
+ @property
30
+ def diag_variables_raw(self) -> List[Union[DiagVariable, OdxLinkRef]]:
31
+ return self.ecu_variant_raw.diag_variables_raw
32
+
33
+ @property
34
+ def dyn_defined_spec(self) -> Optional[DynDefinedSpec]:
35
+ return self.ecu_variant_raw.dyn_defined_spec
36
+
37
+ @property
38
+ def parent_refs(self) -> List[ParentRef]:
39
+ return self.ecu_variant_raw.parent_refs
40
+
41
+ @property
42
+ def ecu_variant_patterns(self) -> List[EcuVariantPattern]:
43
+ return self.ecu_variant_raw.ecu_variant_patterns
44
+
45
+ #######
46
+ # <properties subject to value inheritance>
47
+ #######
48
+ @property
49
+ def diag_variables(self) -> NamedItemList[DiagVariable]:
50
+ return self._diag_variables
51
+
52
+ @property
53
+ def variable_groups(self) -> NamedItemList[VariableGroup]:
54
+ return self._variable_groups
55
+
56
+ #######
57
+ # </properties subject to value inheritance>
58
+ #######
59
+
60
+ @staticmethod
61
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "EcuVariant":
62
+ ecu_variant_raw = EcuVariantRaw.from_et(et_element, doc_frags)
63
+
64
+ return EcuVariant(diag_layer_raw=ecu_variant_raw)
65
+
66
+ def __post_init__(self) -> None:
67
+ super().__post_init__()
68
+
69
+ odxassert(
70
+ isinstance(self.diag_layer_raw, EcuVariantRaw),
71
+ "The raw diagnostic layer passed to EcuVariant "
72
+ "must be a EcuVariantRaw")
73
+
74
+ def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
75
+ """Create a deep copy of the ECU variant
76
+
77
+ Note that the copied diagnostic layer is not fully
78
+ initialized, so `_finalize_init()` should to be called on it
79
+ before it can be used normally.
80
+ """
81
+
82
+ result = super().__deepcopy__(memo)
83
+
84
+ # note that the self.ecu_variant_raw object is *not* copied at
85
+ # this place because the attribute points to the same object
86
+ # as self.diag_layer_raw.
87
+ result.ecu_variant_raw = deepcopy(self.ecu_variant_raw, memo)
88
+
89
+ return result
90
+
91
+ @override
92
+ def _compute_value_inheritance(self, odxlinks: OdxLinkDatabase) -> None:
93
+ super()._compute_value_inheritance(odxlinks)
94
+
95
+ self._diag_variables = NamedItemList(self._compute_available_diag_variables(odxlinks))
96
+ self._variable_groups = NamedItemList(self._compute_available_variable_groups(odxlinks))
97
+
98
+ def _compute_available_diag_variables(self,
99
+ odxlinks: OdxLinkDatabase) -> Iterable[DiagVariable]:
100
+
101
+ def get_local_objects_fn(dl: DiagLayer) -> Iterable[DiagVariable]:
102
+ if not isinstance(dl.diag_layer_raw, HasDiagVariables):
103
+ return []
104
+
105
+ return dl.diag_layer_raw.diag_variables
106
+
107
+ def not_inherited_fn(parent_ref: ParentRef) -> List[str]:
108
+ return parent_ref.not_inherited_variables
109
+
110
+ return self._compute_available_objects(get_local_objects_fn, not_inherited_fn)
111
+
112
+ def _compute_available_variable_groups(self,
113
+ odxlinks: OdxLinkDatabase) -> Iterable[VariableGroup]:
114
+
115
+ def get_local_objects_fn(dl: DiagLayer) -> Iterable[VariableGroup]:
116
+ if not isinstance(dl.diag_layer_raw, HasVariableGroups):
117
+ return []
118
+
119
+ return dl.diag_layer_raw.variable_groups
120
+
121
+ def not_inherited_fn(parent_ref: ParentRef) -> List[str]:
122
+ return []
123
+
124
+ return self._compute_available_objects(get_local_objects_fn, not_inherited_fn)
@@ -0,0 +1,129 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, List, Optional, Union
4
+ from xml.etree import ElementTree
5
+
6
+ from ..diagvariable import DiagVariable
7
+ from ..dyndefinedspec import DynDefinedSpec
8
+ from ..ecuvariantpattern import EcuVariantPattern
9
+ from ..exceptions import odxraise
10
+ from ..nameditemlist import NamedItemList
11
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
12
+ from ..parentref import ParentRef
13
+ from ..snrefcontext import SnRefContext
14
+ from ..utils import dataclass_fields_asdict
15
+ from ..variablegroup import VariableGroup
16
+ from .hierarchyelementraw import HierarchyElementRaw
17
+
18
+
19
+ @dataclass
20
+ class EcuVariantRaw(HierarchyElementRaw):
21
+ diag_variables_raw: List[Union[DiagVariable, OdxLinkRef]]
22
+ variable_groups: NamedItemList[VariableGroup]
23
+ ecu_variant_patterns: List[EcuVariantPattern]
24
+ dyn_defined_spec: Optional[DynDefinedSpec]
25
+ parent_refs: List[ParentRef]
26
+
27
+ @property
28
+ def diag_variables(self) -> NamedItemList[DiagVariable]:
29
+ return self._diag_variables
30
+
31
+ @staticmethod
32
+ def from_et(et_element: ElementTree.Element,
33
+ doc_frags: List[OdxDocFragment]) -> "EcuVariantRaw":
34
+ # objects contained by diagnostic layers exibit an additional
35
+ # document fragment for the diag layer, so we use the document
36
+ # fragments of the odx id of the diag layer for IDs of
37
+ # contained objects.
38
+ her = HierarchyElementRaw.from_et(et_element, doc_frags)
39
+ kwargs = dataclass_fields_asdict(her)
40
+ doc_frags = her.odx_id.doc_fragments
41
+
42
+ diag_variables_raw: List[Union[DiagVariable, OdxLinkRef]] = []
43
+ if (dv_elems := et_element.find("DIAG-VARIABLES")) is not None:
44
+ for dv_proxy_elem in dv_elems:
45
+ dv_proxy: Union[OdxLinkRef, DiagVariable]
46
+ if dv_proxy_elem.tag == "DIAG-VARIABLE-REF":
47
+ dv_proxy = OdxLinkRef.from_et(dv_proxy_elem, doc_frags)
48
+ elif dv_proxy_elem.tag == "DIAG-VARIABLE":
49
+ dv_proxy = DiagVariable.from_et(dv_proxy_elem, doc_frags)
50
+ else:
51
+ odxraise()
52
+
53
+ diag_variables_raw.append(dv_proxy)
54
+
55
+ variable_groups = NamedItemList([
56
+ VariableGroup.from_et(vg_elem, doc_frags)
57
+ for vg_elem in et_element.iterfind("VARIABLE-GROUPS/VARIABLE-GROUP")
58
+ ])
59
+
60
+ ecu_variant_patterns = None
61
+ ecu_variant_patterns = [
62
+ EcuVariantPattern.from_et(varpat_elem, doc_frags)
63
+ for varpat_elem in et_element.iterfind("ECU-VARIANT-PATTERNS/ECU-VARIANT-PATTERN")
64
+ ]
65
+
66
+ dyn_defined_spec = None
67
+ if (dds_elem := et_element.find("DYN-DEFINED-SPEC")) is not None:
68
+ dyn_defined_spec = DynDefinedSpec.from_et(dds_elem, doc_frags)
69
+
70
+ parent_refs = [
71
+ ParentRef.from_et(pr_el, doc_frags)
72
+ for pr_el in et_element.iterfind("PARENT-REFS/PARENT-REF")
73
+ ]
74
+
75
+ # Create DiagLayer
76
+ return EcuVariantRaw(
77
+ diag_variables_raw=diag_variables_raw,
78
+ variable_groups=variable_groups,
79
+ ecu_variant_patterns=ecu_variant_patterns,
80
+ dyn_defined_spec=dyn_defined_spec,
81
+ parent_refs=parent_refs,
82
+ **kwargs)
83
+
84
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
85
+ result = super()._build_odxlinks()
86
+
87
+ for dv_proxy in self.diag_variables_raw:
88
+ if not isinstance(dv_proxy, OdxLinkRef):
89
+ result.update(dv_proxy._build_odxlinks())
90
+
91
+ if self.dyn_defined_spec is not None:
92
+ result.update(self.dyn_defined_spec._build_odxlinks())
93
+
94
+ for parent_ref in self.parent_refs:
95
+ result.update(parent_ref._build_odxlinks())
96
+
97
+ return result
98
+
99
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
100
+ super()._resolve_odxlinks(odxlinks)
101
+
102
+ self._diag_variables: NamedItemList[DiagVariable] = NamedItemList()
103
+ for dv_proxy in self.diag_variables_raw:
104
+ if isinstance(dv_proxy, OdxLinkRef):
105
+ dv = odxlinks.resolve(dv_proxy, DiagVariable)
106
+ else:
107
+ dv_proxy._resolve_odxlinks(odxlinks)
108
+ dv = dv_proxy
109
+
110
+ self._diag_variables.append(dv)
111
+
112
+ if self.dyn_defined_spec is not None:
113
+ self.dyn_defined_spec._resolve_odxlinks(odxlinks)
114
+
115
+ for parent_ref in self.parent_refs:
116
+ parent_ref._resolve_odxlinks(odxlinks)
117
+
118
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
119
+ super()._resolve_snrefs(context)
120
+
121
+ for dv_proxy in self.diag_variables_raw:
122
+ if not isinstance(dv_proxy, OdxLinkRef):
123
+ dv_proxy._resolve_snrefs(context)
124
+
125
+ if self.dyn_defined_spec is not None:
126
+ self.dyn_defined_spec._resolve_snrefs(context)
127
+
128
+ for parent_ref in self.parent_refs:
129
+ parent_ref._resolve_snrefs(context)
@@ -0,0 +1,110 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from copy import deepcopy
3
+ from dataclasses import dataclass
4
+ from typing import Any, Dict, Iterable, List, Union, cast
5
+ from xml.etree import ElementTree
6
+
7
+ from typing_extensions import override
8
+
9
+ from ..diagvariable import DiagVariable
10
+ from ..exceptions import odxassert
11
+ from ..nameditemlist import NamedItemList
12
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkRef
13
+ from ..parentref import ParentRef
14
+ from ..variablegroup import VariableGroup
15
+ from .diaglayer import DiagLayer
16
+ from .functionalgroupraw import FunctionalGroupRaw
17
+ from .hierarchyelement import HierarchyElement
18
+
19
+
20
+ @dataclass
21
+ class FunctionalGroup(HierarchyElement):
22
+ """This is a diagnostic layer for functionality shared between multiple ECU variants
23
+ """
24
+
25
+ @property
26
+ def functional_group_raw(self) -> FunctionalGroupRaw:
27
+ return cast(FunctionalGroupRaw, self.diag_layer_raw)
28
+
29
+ @property
30
+ def diag_variables_raw(self) -> List[Union[DiagVariable, OdxLinkRef]]:
31
+ return self.functional_group_raw.diag_variables_raw
32
+
33
+ @property
34
+ def diag_variables(self) -> NamedItemList[DiagVariable]:
35
+ return self._diag_variables
36
+
37
+ @property
38
+ def variable_groups(self) -> NamedItemList[VariableGroup]:
39
+ return self._variable_groups
40
+
41
+ @property
42
+ def parent_refs(self) -> List[ParentRef]:
43
+ return self.functional_group_raw.parent_refs
44
+
45
+ @staticmethod
46
+ def from_et(et_element: ElementTree.Element,
47
+ doc_frags: List[OdxDocFragment]) -> "FunctionalGroup":
48
+ functional_group_raw = FunctionalGroupRaw.from_et(et_element, doc_frags)
49
+
50
+ return FunctionalGroup(diag_layer_raw=functional_group_raw)
51
+
52
+ def __post_init__(self) -> None:
53
+ super().__post_init__()
54
+
55
+ odxassert(
56
+ isinstance(self.diag_layer_raw, FunctionalGroupRaw),
57
+ "The raw diagnostic layer passed to FunctionalGroup "
58
+ "must be a FunctionalGroupRaw")
59
+
60
+ @override
61
+ def _compute_value_inheritance(self, odxlinks: OdxLinkDatabase) -> None:
62
+ super()._compute_value_inheritance(odxlinks)
63
+
64
+ self._diag_variables = NamedItemList(self._compute_available_diag_variables(odxlinks))
65
+ self._variable_groups = NamedItemList(self._compute_available_variable_groups(odxlinks))
66
+
67
+ def _compute_available_diag_variables(self,
68
+ odxlinks: OdxLinkDatabase) -> Iterable[DiagVariable]:
69
+
70
+ def get_local_objects_fn(dl: DiagLayer) -> Iterable[DiagVariable]:
71
+ if not hasattr(dl.diag_layer_raw, "diag_variables"):
72
+ return []
73
+
74
+ return dl.diag_layer_raw.diag_variables # type: ignore[no-any-return]
75
+
76
+ def not_inherited_fn(parent_ref: ParentRef) -> List[str]:
77
+ return parent_ref.not_inherited_variables
78
+
79
+ return self._compute_available_objects(get_local_objects_fn, not_inherited_fn)
80
+
81
+ def _compute_available_variable_groups(self,
82
+ odxlinks: OdxLinkDatabase) -> Iterable[VariableGroup]:
83
+
84
+ def get_local_objects_fn(dl: DiagLayer) -> Iterable[VariableGroup]:
85
+ if not hasattr(dl.diag_layer_raw, "variable_groups"):
86
+ return []
87
+
88
+ return dl.diag_layer_raw.variable_groups # type: ignore[no-any-return]
89
+
90
+ def not_inherited_fn(parent_ref: ParentRef) -> List[str]:
91
+ return []
92
+
93
+ return self._compute_available_objects(get_local_objects_fn, not_inherited_fn)
94
+
95
+ def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
96
+ """Create a deep copy of the functional group layer
97
+
98
+ Note that the copied diagnostic layer is not fully
99
+ initialized, so `_finalize_init()` should to be called on it
100
+ before it can be used normally.
101
+ """
102
+
103
+ result = super().__deepcopy__(memo)
104
+
105
+ # note that the self.functional_group_raw object is *not* copied at
106
+ # this place because the attribute points to the same object
107
+ # as self.diag_layer_raw.
108
+ result.functional_group_raw = deepcopy(self.functional_group_raw, memo)
109
+
110
+ return result
@@ -0,0 +1,106 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, List, Union
4
+ from xml.etree import ElementTree
5
+
6
+ from ..diagvariable import DiagVariable
7
+ from ..exceptions import odxraise
8
+ from ..nameditemlist import NamedItemList
9
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
10
+ from ..parentref import ParentRef
11
+ from ..snrefcontext import SnRefContext
12
+ from ..utils import dataclass_fields_asdict
13
+ from ..variablegroup import VariableGroup
14
+ from .hierarchyelementraw import HierarchyElementRaw
15
+
16
+
17
+ @dataclass
18
+ class FunctionalGroupRaw(HierarchyElementRaw):
19
+ """This is a diagnostic layer for common functionality of an ECU
20
+ """
21
+
22
+ diag_variables_raw: List[Union[DiagVariable, OdxLinkRef]]
23
+ variable_groups: NamedItemList[VariableGroup]
24
+ parent_refs: List[ParentRef]
25
+
26
+ @property
27
+ def diag_variables(self) -> NamedItemList[DiagVariable]:
28
+ return self._diag_variables
29
+
30
+ @staticmethod
31
+ def from_et(et_element: ElementTree.Element,
32
+ doc_frags: List[OdxDocFragment]) -> "FunctionalGroupRaw":
33
+ # objects contained by diagnostic layers exibit an additional
34
+ # document fragment for the diag layer, so we use the document
35
+ # fragments of the odx id of the diag layer for IDs of
36
+ # contained objects.
37
+ her = HierarchyElementRaw.from_et(et_element, doc_frags)
38
+ kwargs = dataclass_fields_asdict(her)
39
+ doc_frags = her.odx_id.doc_fragments
40
+
41
+ diag_variables_raw: List[Union[DiagVariable, OdxLinkRef]] = []
42
+ if (dv_elems := et_element.find("DIAG-VARIABLES")) is not None:
43
+ for dv_proxy_elem in dv_elems:
44
+ dv_proxy: Union[OdxLinkRef, DiagVariable]
45
+ if dv_proxy_elem.tag == "DIAG-VARIABLE-REF":
46
+ dv_proxy = OdxLinkRef.from_et(dv_proxy_elem, doc_frags)
47
+ elif dv_proxy_elem.tag == "DIAG-VARIABLE":
48
+ dv_proxy = DiagVariable.from_et(dv_proxy_elem, doc_frags)
49
+ else:
50
+ odxraise()
51
+
52
+ diag_variables_raw.append(dv_proxy)
53
+
54
+ variable_groups = NamedItemList([
55
+ VariableGroup.from_et(vg_elem, doc_frags)
56
+ for vg_elem in et_element.iterfind("VARIABLE-GROUPS/VARIABLE-GROUP")
57
+ ])
58
+
59
+ parent_refs = [
60
+ ParentRef.from_et(pr_elem, doc_frags)
61
+ for pr_elem in et_element.iterfind("PARENT-REFS/PARENT-REF")
62
+ ]
63
+
64
+ return FunctionalGroupRaw(
65
+ diag_variables_raw=diag_variables_raw,
66
+ variable_groups=variable_groups,
67
+ parent_refs=parent_refs,
68
+ **kwargs)
69
+
70
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
71
+ result = super()._build_odxlinks()
72
+
73
+ for dv_proxy in self.diag_variables_raw:
74
+ if not isinstance(dv_proxy, OdxLinkRef):
75
+ result.update(dv_proxy._build_odxlinks())
76
+
77
+ for parent_ref in self.parent_refs:
78
+ result.update(parent_ref._build_odxlinks())
79
+
80
+ return result
81
+
82
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
83
+ super()._resolve_odxlinks(odxlinks)
84
+
85
+ self._diag_variables: NamedItemList[DiagVariable] = NamedItemList()
86
+ for dv_proxy in self.diag_variables_raw:
87
+ if isinstance(dv_proxy, OdxLinkRef):
88
+ dv = odxlinks.resolve(dv_proxy, DiagVariable)
89
+ else:
90
+ dv_proxy._resolve_odxlinks(odxlinks)
91
+ dv = dv_proxy
92
+
93
+ self._diag_variables.append(dv)
94
+
95
+ for parent_ref in self.parent_refs:
96
+ parent_ref._resolve_odxlinks(odxlinks)
97
+
98
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
99
+ super()._resolve_snrefs(context)
100
+
101
+ for dv_proxy in self.diag_variables_raw:
102
+ if not isinstance(dv_proxy, OdxLinkRef):
103
+ dv_proxy._resolve_snrefs(context)
104
+
105
+ for parent_ref in self.parent_refs:
106
+ parent_ref._resolve_snrefs(context)