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
@@ -0,0 +1,288 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from .diagnostictroublecode import DiagnosticTroubleCode
7
+ from .diagservice import DiagService
8
+ from .dtcdop import DtcDop
9
+ from .element import IdentifiableElement, NamedElement
10
+ from .environmentdata import EnvironmentData
11
+ from .environmentdatadescription import EnvironmentDataDescription
12
+ from .exceptions import odxraise, odxrequire
13
+ from .matchingparameter import MatchingParameter
14
+ from .nameditemlist import NamedItemList
15
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
16
+ from .parameters.parameter import Parameter
17
+ from .snrefcontext import SnRefContext
18
+ from .table import Table
19
+ from .tablerow import TableRow
20
+ from .utils import dataclass_fields_asdict
21
+
22
+
23
+ @dataclass
24
+ class SubComponentPattern:
25
+ matching_parameters: List[MatchingParameter]
26
+
27
+ @staticmethod
28
+ def from_et(et_element: ElementTree.Element,
29
+ doc_frags: List[OdxDocFragment]) -> "SubComponentPattern":
30
+
31
+ matching_parameters = [
32
+ MatchingParameter.from_et(el, doc_frags)
33
+ for el in et_element.iterfind("MATCHING-PARAMETERS/MATCHING-PARAMETER")
34
+ ]
35
+
36
+ return SubComponentPattern(matching_parameters=matching_parameters)
37
+
38
+
39
+ @dataclass
40
+ class SubComponentParamConnector(IdentifiableElement):
41
+ diag_comm_snref: str
42
+
43
+ # TODO: we currently only support SNREFs, not SNPATHREFs
44
+ out_param_if_refs: List[str]
45
+ in_param_if_refs: List[str]
46
+
47
+ @property
48
+ def service(self) -> DiagService:
49
+ return self._service
50
+
51
+ @property
52
+ def out_param_ifs(self) -> NamedItemList[Parameter]:
53
+ return self._out_param_ifs
54
+
55
+ @property
56
+ def in_param_ifs(self) -> NamedItemList[Parameter]:
57
+ return self._in_param_ifs
58
+
59
+ @staticmethod
60
+ def from_et(et_element: ElementTree.Element,
61
+ doc_frags: List[OdxDocFragment]) -> "SubComponentParamConnector":
62
+ kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
63
+
64
+ diag_comm_snref = odxrequire(
65
+ odxrequire(et_element.find("DIAG-COMM-SNREF")).get("SHORT-NAME"))
66
+
67
+ out_param_if_refs = []
68
+ for elem in et_element.find("OUT-PARAM-IF-REFS") or []:
69
+ if elem.tag != "OUT-PARAM-IF-SNREF":
70
+ odxraise("Currently, only SNREFS are supported for OUT-PARAM-IF-REFS")
71
+ continue
72
+
73
+ out_param_if_refs.append(odxrequire(elem.get("SHORT-NAME")))
74
+
75
+ in_param_if_refs = []
76
+ for elem in et_element.find("IN-PARAM-IF-REFS") or []:
77
+ if elem.tag != "IN-PARAM-IF-SNREF":
78
+ odxraise("Currently, only SNREFS are supported for IN-PARAM-IF-REFS")
79
+ continue
80
+
81
+ in_param_if_refs.append(odxrequire(elem.get("SHORT-NAME")))
82
+
83
+ return SubComponentParamConnector(
84
+ diag_comm_snref=diag_comm_snref,
85
+ out_param_if_refs=out_param_if_refs,
86
+ in_param_if_refs=in_param_if_refs,
87
+ **kwargs)
88
+
89
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
90
+ return {}
91
+
92
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
93
+ pass
94
+
95
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
96
+ service = resolve_snref(self.diag_comm_snref,
97
+ odxrequire(context.diag_layer).diag_comms, DiagService)
98
+ self._service = service
99
+
100
+ if self._service.request is not None:
101
+ odxraise()
102
+ return
103
+ if not self._service.positive_responses:
104
+ odxraise()
105
+ return
106
+ request = odxrequire(service.request)
107
+ response = service.positive_responses[0]
108
+
109
+ in_param_ifs = []
110
+ for x in self.in_param_if_refs:
111
+ in_param_ifs.append(resolve_snref(x, request.parameters, Parameter))
112
+
113
+ out_param_ifs = []
114
+ for x in self.out_param_if_refs:
115
+ out_param_ifs.append(resolve_snref(x, response.parameters, Parameter))
116
+
117
+ self._in_param_ifs = NamedItemList(in_param_ifs)
118
+ self._out_param_ifs = NamedItemList(out_param_ifs)
119
+
120
+
121
+ @dataclass
122
+ class TableRowConnector(NamedElement):
123
+ table_ref: OdxLinkRef
124
+ table_row_snref: str
125
+
126
+ @property
127
+ def table(self) -> Table:
128
+ return self._table
129
+
130
+ @property
131
+ def table_row(self) -> TableRow:
132
+ return self._table_row
133
+
134
+ @staticmethod
135
+ def from_et(et_element: ElementTree.Element,
136
+ doc_frags: List[OdxDocFragment]) -> "TableRowConnector":
137
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
138
+
139
+ table_ref = odxrequire(OdxLinkRef.from_et(et_element.find("TABLE-REF"), doc_frags))
140
+ table_row_snref_el = odxrequire(et_element.find("TABLE-ROW-SNREF"))
141
+ table_row_snref = odxrequire(table_row_snref_el.get("SHORT-NAME"))
142
+
143
+ return TableRowConnector(table_ref=table_ref, table_row_snref=table_row_snref, **kwargs)
144
+
145
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
146
+ return {}
147
+
148
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
149
+ self._table = odxlinks.resolve(self.table_ref, Table)
150
+
151
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
152
+ self._table_row = resolve_snref(self.table_row_snref, self._table.table_rows, TableRow)
153
+
154
+
155
+ @dataclass
156
+ class DtcConnector(NamedElement):
157
+ dtc_dop_ref: OdxLinkRef
158
+ dtc_snref: str
159
+
160
+ @property
161
+ def dtc_dop(self) -> DtcDop:
162
+ return self._dtc_dop
163
+
164
+ @property
165
+ def dtc(self) -> DiagnosticTroubleCode:
166
+ return self._dtc
167
+
168
+ @staticmethod
169
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "DtcConnector":
170
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
171
+
172
+ dtc_dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DTC-DOP-REF"), doc_frags))
173
+ dtc_snref_el = odxrequire(et_element.find("DTC-SNREF"))
174
+ dtc_snref = odxrequire(dtc_snref_el.get("SHORT-NAME"))
175
+
176
+ return DtcConnector(dtc_dop_ref=dtc_dop_ref, dtc_snref=dtc_snref, **kwargs)
177
+
178
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
179
+ return {}
180
+
181
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
182
+ self._dtc_dop = odxlinks.resolve(self.dtc_dop_ref, DtcDop)
183
+
184
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
185
+ self._dtc = resolve_snref(self.dtc_snref, self._dtc_dop.dtcs, DiagnosticTroubleCode)
186
+
187
+
188
+ @dataclass
189
+ class EnvDataConnector(NamedElement):
190
+ env_data_desc_ref: OdxLinkRef
191
+ env_data_snref: str
192
+
193
+ @property
194
+ def env_data_desc(self) -> EnvironmentDataDescription:
195
+ return self._env_data_desc
196
+
197
+ @property
198
+ def env_data(self) -> EnvironmentData:
199
+ return self._env_data
200
+
201
+ @staticmethod
202
+ def from_et(et_element: ElementTree.Element,
203
+ doc_frags: List[OdxDocFragment]) -> "EnvDataConnector":
204
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
205
+
206
+ env_data_desc_ref = odxrequire(
207
+ OdxLinkRef.from_et(et_element.find("ENV-DATA-DESC-REF"), doc_frags))
208
+ env_data_snref_el = odxrequire(et_element.find("ENV-DATA-SNREF"))
209
+ env_data_snref = odxrequire(env_data_snref_el.get("SHORT-NAME"))
210
+
211
+ return EnvDataConnector(
212
+ env_data_desc_ref=env_data_desc_ref, env_data_snref=env_data_snref, **kwargs)
213
+
214
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
215
+ return {}
216
+
217
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
218
+ self._env_data_desc = odxlinks.resolve(self.env_data_desc_ref, EnvironmentDataDescription)
219
+
220
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
221
+ self._env_data = resolve_snref(self.env_data_snref, self._env_data_desc.env_datas,
222
+ EnvironmentData)
223
+
224
+
225
+ @dataclass
226
+ class SubComponent(IdentifiableElement):
227
+ """Sub-components describe collections of related diagnostic variables
228
+
229
+ Note that the communication paradigm via diagnostic variables is
230
+ somewhat uncommon. If your ECU does not define any, there's no
231
+ need for it to define sub-components.
232
+
233
+ """
234
+
235
+ #sub_component_patterns: NamedItemList[SubComponentPattern]
236
+ sub_component_param_connectors: NamedItemList[SubComponentParamConnector]
237
+ table_row_connectors: NamedItemList[TableRowConnector]
238
+ env_data_connectors: NamedItemList[EnvDataConnector]
239
+ dtc_connectors: NamedItemList[DtcConnector]
240
+
241
+ semantic: Optional[str]
242
+
243
+ @staticmethod
244
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "SubComponent":
245
+ kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
246
+
247
+ semantic = et_element.get("SEMANTIC")
248
+
249
+ sub_component_param_connectors = [
250
+ SubComponentParamConnector.from_et(el, doc_frags) for el in et_element.iterfind(
251
+ "SUB-COMPONENT-PARAM-CONNECTORS/SUB-COMPONENT-PARAM-CONNECTOR")
252
+ ]
253
+ table_row_connectors = [
254
+ TableRowConnector.from_et(el, doc_frags)
255
+ for el in et_element.iterfind("TABLE-ROW-CONNECTORS/TABLE-ROW-CONNECTOR")
256
+ ]
257
+ env_data_connectors = [
258
+ EnvDataConnector.from_et(el, doc_frags)
259
+ for el in et_element.iterfind("ENV-DATA-CONNECTORS/ENV-DATA-CONNECTOR")
260
+ ]
261
+ dtc_connectors = [
262
+ DtcConnector.from_et(el, doc_frags)
263
+ for el in et_element.iterfind("DTC-CONNECTORS/DTC-CONNECTOR")
264
+ ]
265
+
266
+ return SubComponent(
267
+ semantic=semantic,
268
+ sub_component_param_connectors=NamedItemList(sub_component_param_connectors),
269
+ table_row_connectors=NamedItemList(table_row_connectors),
270
+ env_data_connectors=NamedItemList(env_data_connectors),
271
+ dtc_connectors=NamedItemList(dtc_connectors),
272
+ **kwargs)
273
+
274
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
275
+ result = {}
276
+
277
+ for dtc_conn in self.dtc_connectors:
278
+ result.update(dtc_conn._build_odxlinks())
279
+
280
+ return result
281
+
282
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
283
+ for dtc_conn in self.dtc_connectors:
284
+ dtc_conn._resolve_odxlinks(odxlinks)
285
+
286
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
287
+ for dtc_conn in self.dtc_connectors:
288
+ dtc_conn._resolve_snrefs(context)
odxtools/swvariable.py ADDED
@@ -0,0 +1,21 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from .element import NamedElement
7
+ from .odxlink import OdxDocFragment
8
+ from .utils import dataclass_fields_asdict
9
+
10
+
11
+ @dataclass
12
+ class SwVariable(NamedElement):
13
+ origin: Optional[str]
14
+
15
+ @staticmethod
16
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "SwVariable":
17
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
18
+
19
+ origin = et_element.findtext("ORIGIN")
20
+
21
+ return SwVariable(origin=origin, **kwargs)
odxtools/table.py CHANGED
@@ -1,22 +1,19 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
3
+ from typing import Any, Dict, List, Optional, Union
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .admindata import AdminData
7
- from .createsdgs import create_sdgs_from_et
8
7
  from .dataobjectproperty import DataObjectProperty
9
8
  from .element import IdentifiableElement
10
9
  from .exceptions import odxassert
11
10
  from .nameditemlist import NamedItemList
12
11
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
12
+ from .snrefcontext import SnRefContext
13
13
  from .specialdatagroup import SpecialDataGroup
14
14
  from .tablerow import TableRow
15
15
  from .utils import dataclass_fields_asdict
16
16
 
17
- if TYPE_CHECKING:
18
- from .diaglayer import DiagLayer
19
-
20
17
 
21
18
  @dataclass
22
19
  class Table(IdentifiableElement):
@@ -50,7 +47,9 @@ class Table(IdentifiableElement):
50
47
  elif sub_elem.tag == "TABLE-ROW-REF":
51
48
  table_rows_raw.append(OdxLinkRef.from_et(sub_elem, doc_frags))
52
49
 
53
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
50
+ sdgs = [
51
+ SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
52
+ ]
54
53
 
55
54
  return Table(
56
55
  semantic=semantic,
@@ -99,7 +98,7 @@ class Table(IdentifiableElement):
99
98
 
100
99
  self._table_rows = NamedItemList(table_rows)
101
100
 
102
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
101
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
103
102
  for table_row_wrapper in self.table_rows_raw:
104
103
  if isinstance(table_row_wrapper, TableRow):
105
- table_row_wrapper._resolve_snrefs(diag_layer)
104
+ table_row_wrapper._resolve_snrefs(context)
odxtools/tablerow.py CHANGED
@@ -1,21 +1,20 @@
1
1
  # SPDX-License-Identifier: MIT
2
- from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
2
+ from dataclasses import dataclass, fields
3
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .basicstructure import BasicStructure
7
- from .createsdgs import create_sdgs_from_et
8
7
  from .dataobjectproperty import DataObjectProperty
9
8
  from .dtcdop import DtcDop
10
9
  from .element import IdentifiableElement
11
10
  from .exceptions import odxassert, odxraise, odxrequire
12
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
11
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
13
12
  from .odxtypes import AtomicOdxType
13
+ from .snrefcontext import SnRefContext
14
14
  from .specialdatagroup import SpecialDataGroup
15
15
  from .utils import dataclass_fields_asdict
16
16
 
17
17
  if TYPE_CHECKING:
18
- from .diaglayer import DiagLayer
19
18
  from .table import Table
20
19
 
21
20
 
@@ -70,7 +69,9 @@ class TableRow(IdentifiableElement):
70
69
  dop_snref: Optional[str] = None
71
70
  if (dop_snref_elem := et_element.find("DATA-OBJECT-PROP-SNREF")) is not None:
72
71
  dop_snref = dop_snref_elem.attrib["SHORT-NAME"]
73
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
72
+ sdgs = [
73
+ SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
74
+ ]
74
75
 
75
76
  return TableRow(
76
77
  table_ref=table_ref,
@@ -107,7 +108,7 @@ class TableRow(IdentifiableElement):
107
108
  for sdg in self.sdgs:
108
109
  sdg._resolve_odxlinks(odxlinks)
109
110
 
110
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
111
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
111
112
  # convert the raw key into the proper internal
112
113
  # representation. note that we cannot do this earlier because
113
114
  # the table's ODXLINKs must be resolved and the order of
@@ -125,15 +126,17 @@ class TableRow(IdentifiableElement):
125
126
  else:
126
127
  self._key = key_dop.physical_type.base_data_type.from_string(self.key_raw)
127
128
 
128
- ddd_spec = diag_layer.diag_data_dictionary_spec
129
+ ddd_spec = odxrequire(context.diag_layer).diag_data_dictionary_spec
129
130
 
130
131
  if self.structure_snref is not None:
131
- self._structure = odxrequire(ddd_spec.structures.get(self.structure_snref))
132
+ self._structure = resolve_snref(self.structure_snref, ddd_spec.structures,
133
+ BasicStructure)
132
134
  if self.dop_snref is not None:
133
- self._dop = odxrequire(ddd_spec.data_object_props.get(self.dop_snref))
135
+ self._dop = resolve_snref(self.dop_snref, ddd_spec.data_object_props,
136
+ DataObjectProperty)
134
137
 
135
138
  for sdg in self.sdgs:
136
- sdg._resolve_snrefs(diag_layer)
139
+ sdg._resolve_snrefs(context)
137
140
 
138
141
  @property
139
142
  def table(self) -> "Table":
@@ -154,3 +157,8 @@ class TableRow(IdentifiableElement):
154
157
  def dop(self) -> Optional[DataObjectProperty]:
155
158
  """The data object property object resolved by dop_ref."""
156
159
  return self._dop
160
+
161
+ def __reduce__(self) -> Tuple[Any, ...]:
162
+ """This ensures that the object can be correctly reconstructed during unpickling."""
163
+ state = self.__dict__.copy()
164
+ return self.__class__, tuple([getattr(self, x.name) for x in fields(self)]), state
odxtools/teammember.py CHANGED
@@ -1,16 +1,14 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
7
7
  from .exceptions import odxrequire
8
8
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
9
+ from .snrefcontext import SnRefContext
9
10
  from .utils import dataclass_fields_asdict
10
11
 
11
- if TYPE_CHECKING:
12
- from .diaglayer import DiagLayer
13
-
14
12
 
15
13
  @dataclass
16
14
  class TeamMember(IdentifiableElement):
@@ -55,5 +53,5 @@ class TeamMember(IdentifiableElement):
55
53
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
56
54
  pass
57
55
 
58
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
56
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
59
57
  pass
@@ -5,35 +5,15 @@
5
5
  # This template writes an .odx-c file for a communication
6
6
  # parameter specification.
7
7
  -#}
8
- {%- import('macros/printAdminData.xml.jinja2') as pad -%}
9
- {%- import('macros/printCompanyData.xml.jinja2') as pcd -%}
8
+ {%- import('macros/printOdxCategory.xml.jinja2') as poc %}
10
9
  {%- import('macros/printProtStack.xml.jinja2') as pps %}
11
10
  {#- -#}
12
11
 
13
12
  <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
14
- <ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
15
13
  <!-- Written using odxtools {{odxtools_version}} -->
16
- <COMPARAM-SPEC ID="{{comparam_spec.odx_id.local_id}}">
17
- <SHORT-NAME>{{comparam_spec.short_name}}</SHORT-NAME>
18
- {%- if comparam_spec.long_name is not none %}
19
- <LONG-NAME>{{comparam_spec.long_name|e}}</LONG-NAME>
20
- {%- endif %}
21
- {%- if comparam_spec.description and comparam_spec.description.strip() %}
22
- <DESC>
23
- {{comparam_spec.description}}
24
- </DESC>
25
- {%- endif %}
26
- {%- if comparam_spec.admin_data is not none %}
27
- {{- pad.printAdminData(comparam_spec.admin_data) | indent(3) }}
28
- {%- endif %}
29
- {%- if comparam_spec.company_datas %}
30
- <COMPANY-DATAS>
31
- {%- for cd in comparam_spec.company_datas %}
32
- {{- pcd.printCompanyData(cd) | indent(5) -}}
33
- {%- endfor %}
34
- </COMPANY-DATAS>
35
- {%- endif %}
36
-
14
+ <ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
15
+ <COMPARAM-SPEC {{- poc.printOdxCategoryAttribs(comparam_spec) }}>
16
+ {{- poc.printOdxCategorySubtags(comparam_spec)|indent(3) }}
37
17
  {%- if comparam_spec.prot_stacks %}
38
18
  <PROT-STACKS>
39
19
  {%- for ps in comparam_spec.prot_stacks %}
@@ -5,39 +5,18 @@
5
5
  # This template writes an .odx-cs file for a communication
6
6
  # parameter subset.
7
7
  -#}
8
+ {%- import('macros/printOdxCategory.xml.jinja2') as poc %}
8
9
  {%- import('macros/printComparam.xml.jinja2') as pcp -%}
9
- {%- import('macros/printAdminData.xml.jinja2') as pad -%}
10
- {%- import('macros/printCompanyData.xml.jinja2') as pcd -%}
11
10
  {%- import('macros/printDOP.xml.jinja2') as pdop %}
12
11
  {%- import('macros/printUnitSpec.xml.jinja2') as pus %}
13
- {%- import('macros/printSpecialData.xml.jinja2') as psd %}
12
+ {%- import('macros/printDescription.xml.jinja2') as pd %}
14
13
  {#- -#}
15
14
 
16
15
  <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
17
- <ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
18
16
  <!-- Written using odxtools {{odxtools_version}} -->
19
- <COMPARAM-SUBSET ID="{{comparam_subset.odx_id.local_id}}"
20
- CATEGORY="{{comparam_subset.category}}" >
21
- <SHORT-NAME>{{comparam_subset.short_name}}</SHORT-NAME>
22
- {%- if comparam_subset.long_name is not none %}
23
- <LONG-NAME>{{comparam_subset.long_name|e}}</LONG-NAME>
24
- {%- endif %}
25
- {%- if comparam_subset.description and comparam_subset.description.strip() %}
26
- <DESC>
27
- {{comparam_subset.description}}
28
- </DESC>
29
- {%- endif %}
30
- {%- if comparam_subset.admin_data is not none %}
31
- {{- pad.printAdminData(comparam_subset.admin_data) | indent(3) }}
32
- {%- endif %}
33
- {%- if comparam_subset.company_datas %}
34
- <COMPANY-DATAS>
35
- {%- for cd in comparam_subset.company_datas %}
36
- {{- pcd.printCompanyData(cd) | indent(5, first=True) }}
37
- {%- endfor %}
38
- </COMPANY-DATAS>
39
- {%- endif %}
40
- {{- psd.printSpecialDataGroups(comparam_subset.sdgs)|indent(3, first=True) }}
17
+ <ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
18
+ <COMPARAM-SUBSET {{- poc.printOdxCategoryAttribs(comparam_subset) }} {{make_xml_attrib("CATEGORY", comparam_subset.category)}}>
19
+ {{- poc.printOdxCategorySubtags(comparam_subset)|indent(3) }}
41
20
  {%- if comparam_subset.comparams %}
42
21
  <COMPARAMS>
43
22
  {%- for cp in comparam_subset.comparams %}
@@ -2,68 +2,52 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
  -#}
5
- {%- import('macros/printVariant.xml.jinja2') as pv -%}
6
- {%- import('macros/printAdminData.xml.jinja2') as pad -%}
7
- {%- import('macros/printCompanyData.xml.jinja2') as pcd -%}
8
- {%- import('macros/printSpecialData.xml.jinja2') as psd %}
5
+ {%- import('macros/printOdxCategory.xml.jinja2') as poc %}
6
+ {%- import('macros/printEcuSharedData.xml.jinja2') as pecusd -%}
7
+ {%- import('macros/printProtocol.xml.jinja2') as pprot %}
8
+ {%- import('macros/printFunctionalGroup.xml.jinja2') as pfuncgroup %}
9
+ {%- import('macros/printEcuSharedData.xml.jinja2') as pecusd %}
10
+ {%- import('macros/printBaseVariant.xml.jinja2') as pbv %}
11
+ {%- import('macros/printEcuVariant.xml.jinja2') as pecuv %}
9
12
  {#- -#}
10
13
 
11
14
  <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
15
+ <!-- Written using odxtools {{odxtools_version}} -->
12
16
  <ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
13
- <!-- Written using odxtools {{odxtools_version}} -->
14
- <DIAG-LAYER-CONTAINER ID="{{dlc.odx_id.local_id}}">
15
- <SHORT-NAME>{{dlc.short_name}}</SHORT-NAME>
16
- {%- if dlc.long_name %}
17
- <LONG-NAME>{{dlc.long_name|e}}</LONG-NAME>
18
- {%- endif %}
19
- {%- if dlc.description %}
20
- <DESC>
21
- {{dlc.description}}
22
- </DESC>
23
- {%- endif %}
24
- {%- if dlc.admin_data %}
25
- {{pad.printAdminData(dlc.admin_data)|indent(2)}}
26
- {%- endif %}
27
- {%- if dlc.company_datas %}
28
- <COMPANY-DATAS>
29
- {%- for cd in dlc.company_datas %}
30
- {{pcd.printCompanyData(cd)|indent(3)}}
31
- {%- endfor %}
32
- </COMPANY-DATAS>
33
- {%- endif %}
34
- {{- psd.printSpecialDataGroups(dlc.sdgs)|indent(2, first=True) }}
17
+ <DIAG-LAYER-CONTAINER {{- poc.printOdxCategoryAttribs(dlc) }}>
18
+ {{- poc.printOdxCategorySubtags(dlc)|indent(3) }}
35
19
  {%- if dlc.protocols %}
36
20
  <PROTOCOLS>
37
21
  {%- for dl in dlc.protocols %}
38
- {{pv.printVariant(dl)|indent(3)}}
22
+ {{pprot.printProtocol(dl)|indent(3)}}
39
23
  {%- endfor %}
40
24
  </PROTOCOLS>
41
25
  {%- endif %}
42
26
  {%- if dlc.functional_groups %}
43
27
  <FUNCTIONAL-GROUPS>
44
28
  {%- for dl in dlc.functional_groups %}
45
- {{pv.printVariant(dl)|indent(3)}}
29
+ {{pfuncgroup.printFunctionalGroup(dl)|indent(3)}}
46
30
  {%- endfor %}
47
31
  </FUNCTIONAL-GROUPS>
48
32
  {%- endif %}
49
33
  {%- if dlc.ecu_shared_datas %}
50
34
  <ECU-SHARED-DATAS>
51
35
  {%- for dl in dlc.ecu_shared_datas %}
52
- {{pv.printVariant(dl)|indent(3)}}
36
+ {{pecusd.printEcuSharedData(dl)|indent(3)}}
53
37
  {%- endfor %}
54
38
  </ECU-SHARED-DATAS>
55
39
  {%- endif %}
56
40
  {%- if dlc.base_variants %}
57
41
  <BASE-VARIANTS>
58
42
  {%- for dl in dlc.base_variants %}
59
- {{pv.printVariant(dl)|indent(3)}}
43
+ {{pbv.printBaseVariant(dl)|indent(3)}}
60
44
  {%- endfor %}
61
45
  </BASE-VARIANTS>
62
46
  {%- endif %}
63
47
  {%- if dlc.ecu_variants %}
64
48
  <ECU-VARIANTS>
65
49
  {%- for dl in dlc.ecu_variants %}
66
- {{pv.printVariant(dl)|indent(3)}}
50
+ {{pecuv.printEcuVariant(dl)|indent(3)}}
67
51
  {%- endfor %}
68
52
  </ECU-VARIANTS>
69
53
  {%- endif %}
@@ -4,7 +4,7 @@
4
4
  -#}
5
5
  <?xml version="1.0" encoding="UTF-8"?>
6
6
  <CATALOG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" F-DTD-VERSION="ODX-2.2.0" xsi:noNamespaceSchemaLocation="odx-cc.xsd">
7
- <SHORT-NAME>{{ecu_name}}</SHORT-NAME>
7
+ <SHORT-NAME>{{database.short_name}}</SHORT-NAME>
8
8
  <ABLOCKS>
9
9
  {%- for file_name, creation_date, mime_type in file_index %}
10
10
  <ABLOCK UPD="UNCHANGED">
@@ -6,7 +6,7 @@
6
6
  {%- import('macros/printElementId.xml.jinja2') as peid %}
7
7
 
8
8
  {%- macro printAdditionalAudience(audience) -%}
9
- <ADDITIONAL-AUDIENCE ID="{{audience.odx_id.local_id}}">
9
+ <ADDITIONAL-AUDIENCE {{-peid.printElementIdAttribs(audience)}}>
10
10
  {{ peid.printElementIdSubtags(audience)|indent(1) }}
11
11
  </ADDITIONAL-AUDIENCE>
12
12
  {%- endmacro -%}