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