odxtools 7.1.1__py3-none-any.whl → 7.2.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.
- odxtools/__init__.py +6 -4
- odxtools/additionalaudience.py +3 -5
- odxtools/admindata.py +5 -7
- odxtools/audience.py +3 -5
- odxtools/basecomparam.py +3 -5
- odxtools/basicstructure.py +10 -17
- odxtools/cli/_parser_utils.py +1 -1
- odxtools/cli/_print_utils.py +3 -2
- odxtools/cli/compare.py +1 -1
- odxtools/companydata.py +5 -7
- odxtools/companydocinfo.py +7 -8
- odxtools/companyrevisioninfo.py +3 -5
- odxtools/companyspecificinfo.py +8 -9
- odxtools/comparam.py +4 -6
- odxtools/comparaminstance.py +6 -8
- odxtools/comparamspec.py +14 -13
- odxtools/comparamsubset.py +17 -16
- odxtools/complexcomparam.py +5 -7
- odxtools/compumethods/compuconst.py +31 -0
- odxtools/compumethods/compudefaultvalue.py +27 -0
- odxtools/compumethods/compuinternaltophys.py +39 -0
- odxtools/compumethods/compuinversevalue.py +7 -0
- odxtools/compumethods/compumethod.py +67 -12
- odxtools/compumethods/compuphystointernal.py +39 -0
- odxtools/compumethods/compuscale.py +15 -26
- odxtools/compumethods/createanycompumethod.py +14 -160
- odxtools/compumethods/identicalcompumethod.py +31 -6
- odxtools/compumethods/linearcompumethod.py +69 -189
- odxtools/compumethods/linearsegment.py +193 -0
- odxtools/compumethods/scalelinearcompumethod.py +132 -26
- odxtools/compumethods/tabintpcompumethod.py +119 -99
- odxtools/compumethods/texttablecompumethod.py +107 -43
- odxtools/createanydiagcodedtype.py +10 -67
- odxtools/database.py +68 -62
- odxtools/dataobjectproperty.py +10 -19
- odxtools/description.py +47 -0
- odxtools/determinenumberofitems.py +4 -5
- odxtools/diagcodedtype.py +29 -12
- odxtools/diagcomm.py +10 -6
- odxtools/diagdatadictionaryspec.py +20 -21
- odxtools/diaglayer.py +34 -5
- odxtools/diaglayercontainer.py +17 -11
- odxtools/diaglayerraw.py +20 -21
- odxtools/diagnostictroublecode.py +7 -8
- odxtools/diagservice.py +9 -7
- odxtools/docrevision.py +5 -7
- odxtools/dopbase.py +7 -8
- odxtools/dtcdop.py +5 -8
- odxtools/dynamicendmarkerfield.py +22 -9
- odxtools/dynamiclengthfield.py +5 -11
- odxtools/element.py +4 -3
- odxtools/endofpdufield.py +0 -2
- odxtools/environmentdatadescription.py +4 -6
- odxtools/exceptions.py +1 -1
- odxtools/field.py +9 -9
- odxtools/functionalclass.py +3 -5
- odxtools/inputparam.py +3 -5
- odxtools/leadinglengthinfotype.py +15 -2
- odxtools/loadfile.py +64 -0
- odxtools/minmaxlengthtype.py +20 -2
- odxtools/modification.py +3 -5
- odxtools/multiplexer.py +7 -14
- odxtools/multiplexercase.py +4 -6
- odxtools/multiplexerdefaultcase.py +4 -6
- odxtools/multiplexerswitchkey.py +4 -5
- odxtools/negoutputparam.py +3 -5
- odxtools/outputparam.py +3 -5
- odxtools/parameterinfo.py +3 -3
- odxtools/parameters/codedconstparameter.py +2 -14
- odxtools/parameters/lengthkeyparameter.py +3 -17
- odxtools/parameters/nrcconstparameter.py +2 -14
- odxtools/parameters/parameter.py +22 -22
- odxtools/parameters/parameterwithdop.py +6 -8
- odxtools/parameters/physicalconstantparameter.py +5 -8
- odxtools/parameters/reservedparameter.py +4 -3
- odxtools/parameters/tablekeyparameter.py +6 -9
- odxtools/parameters/tablestructparameter.py +6 -8
- odxtools/parameters/valueparameter.py +5 -8
- odxtools/paramlengthinfotype.py +19 -6
- odxtools/parentref.py +15 -1
- odxtools/physicaldimension.py +3 -5
- odxtools/progcode.py +18 -7
- odxtools/protstack.py +3 -5
- odxtools/relateddoc.py +7 -9
- odxtools/request.py +8 -0
- odxtools/response.py +8 -0
- odxtools/scaleconstr.py +3 -3
- odxtools/singleecujob.py +12 -10
- odxtools/snrefcontext.py +29 -0
- odxtools/specialdata.py +3 -5
- odxtools/specialdatagroup.py +5 -7
- odxtools/specialdatagroupcaption.py +3 -6
- odxtools/standardlengthtype.py +27 -2
- odxtools/state.py +3 -5
- odxtools/statechart.py +9 -11
- odxtools/statetransition.py +4 -9
- odxtools/staticfield.py +4 -8
- odxtools/table.py +7 -8
- odxtools/tablerow.py +7 -6
- odxtools/teammember.py +3 -5
- odxtools/templates/comparam-spec.odx-c.xml.jinja2 +2 -5
- odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +2 -5
- odxtools/templates/macros/printCompanyData.xml.jinja2 +2 -5
- odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
- odxtools/templates/macros/printCompuMethod.xml.jinja2 +153 -0
- odxtools/templates/macros/printDOP.xml.jinja2 +10 -132
- odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
- odxtools/templates/macros/printElementId.xml.jinja2 +3 -3
- odxtools/templates/macros/printMux.xml.jinja2 +3 -2
- odxtools/templates/macros/printTable.xml.jinja2 +2 -3
- odxtools/unit.py +3 -5
- odxtools/unitgroup.py +3 -5
- odxtools/unitspec.py +9 -10
- odxtools/utils.py +1 -26
- odxtools/version.py +2 -2
- odxtools/{write_pdx_file.py → writepdxfile.py} +19 -10
- odxtools/xdoc.py +3 -5
- {odxtools-7.1.1.dist-info → odxtools-7.2.0.dist-info}/METADATA +1 -1
- odxtools-7.2.0.dist-info/RECORD +192 -0
- {odxtools-7.1.1.dist-info → odxtools-7.2.0.dist-info}/WHEEL +1 -1
- odxtools/createcompanydatas.py +0 -17
- odxtools/createsdgs.py +0 -19
- odxtools/load_file.py +0 -13
- odxtools/load_odx_d_file.py +0 -6
- odxtools/load_pdx_file.py +0 -8
- odxtools-7.1.1.dist-info/RECORD +0 -186
- /odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +0 -0
- {odxtools-7.1.1.dist-info → odxtools-7.2.0.dist-info}/LICENSE +0 -0
- {odxtools-7.1.1.dist-info → odxtools-7.2.0.dist-info}/entry_points.txt +0 -0
- {odxtools-7.1.1.dist-info → odxtools-7.2.0.dist-info}/top_level.txt +0 -0
odxtools/diaglayercontainer.py
CHANGED
@@ -1,13 +1,11 @@
|
|
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, Optional, Union
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .admindata import AdminData
|
8
8
|
from .companydata import CompanyData
|
9
|
-
from .createcompanydatas import create_company_datas_from_et
|
10
|
-
from .createsdgs import create_sdgs_from_et
|
11
9
|
from .diaglayer import DiagLayer
|
12
10
|
from .element import IdentifiableElement
|
13
11
|
from .exceptions import odxrequire
|
@@ -16,6 +14,9 @@ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
|
16
14
|
from .specialdatagroup import SpecialDataGroup
|
17
15
|
from .utils import dataclass_fields_asdict
|
18
16
|
|
17
|
+
if TYPE_CHECKING:
|
18
|
+
from .database import Database
|
19
|
+
|
19
20
|
|
20
21
|
@dataclass
|
21
22
|
class DiagLayerContainer(IdentifiableElement):
|
@@ -48,7 +49,10 @@ class DiagLayerContainer(IdentifiableElement):
|
|
48
49
|
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
|
49
50
|
|
50
51
|
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
|
51
|
-
company_datas =
|
52
|
+
company_datas = NamedItemList([
|
53
|
+
CompanyData.from_et(cde, doc_frags)
|
54
|
+
for cde in et_element.iterfind("COMPANY-DATAS/COMPANY-DATA")
|
55
|
+
])
|
52
56
|
ecu_shared_datas = NamedItemList([
|
53
57
|
DiagLayer.from_et(dl_element, doc_frags)
|
54
58
|
for dl_element in et_element.iterfind("ECU-SHARED-DATAS/ECU-SHARED-DATA")
|
@@ -69,7 +73,9 @@ class DiagLayerContainer(IdentifiableElement):
|
|
69
73
|
DiagLayer.from_et(dl_element, doc_frags)
|
70
74
|
for dl_element in et_element.iterfind("ECU-VARIANTS/ECU-VARIANT")
|
71
75
|
])
|
72
|
-
sdgs =
|
76
|
+
sdgs = [
|
77
|
+
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
78
|
+
]
|
73
79
|
|
74
80
|
return DiagLayerContainer(
|
75
81
|
admin_data=admin_data,
|
@@ -124,17 +130,17 @@ class DiagLayerContainer(IdentifiableElement):
|
|
124
130
|
for ecu_variant in self.ecu_variants:
|
125
131
|
ecu_variant._resolve_odxlinks(odxlinks)
|
126
132
|
|
127
|
-
def _finalize_init(self, odxlinks: OdxLinkDatabase) -> None:
|
133
|
+
def _finalize_init(self, database: "Database", odxlinks: OdxLinkDatabase) -> None:
|
128
134
|
for ecu_shared_data in self.ecu_shared_datas:
|
129
|
-
ecu_shared_data._finalize_init(odxlinks)
|
135
|
+
ecu_shared_data._finalize_init(database, odxlinks)
|
130
136
|
for protocol in self.protocols:
|
131
|
-
protocol._finalize_init(odxlinks)
|
137
|
+
protocol._finalize_init(database, odxlinks)
|
132
138
|
for functional_group in self.functional_groups:
|
133
|
-
functional_group._finalize_init(odxlinks)
|
139
|
+
functional_group._finalize_init(database, odxlinks)
|
134
140
|
for base_variant in self.base_variants:
|
135
|
-
base_variant._finalize_init(odxlinks)
|
141
|
+
base_variant._finalize_init(database, odxlinks)
|
136
142
|
for ecu_variant in self.ecu_variants:
|
137
|
-
ecu_variant._finalize_init(odxlinks)
|
143
|
+
ecu_variant._finalize_init(database, odxlinks)
|
138
144
|
|
139
145
|
@property
|
140
146
|
def diag_layers(self) -> NamedItemList[DiagLayer]:
|
odxtools/diaglayerraw.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from copy import copy
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import
|
4
|
+
from typing import Any, Dict, List, Optional, Union, cast
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .additionalaudience import AdditionalAudience
|
@@ -10,7 +10,6 @@ from .companydata import CompanyData
|
|
10
10
|
from .comparaminstance import ComparamInstance
|
11
11
|
from .comparamspec import ComparamSpec
|
12
12
|
from .comparamsubset import ComparamSubset
|
13
|
-
from .createsdgs import create_sdgs_from_et
|
14
13
|
from .diagcomm import DiagComm
|
15
14
|
from .diagdatadictionaryspec import DiagDataDictionarySpec
|
16
15
|
from .diaglayertype import DiagLayerType
|
@@ -26,13 +25,11 @@ from .protstack import ProtStack
|
|
26
25
|
from .request import Request
|
27
26
|
from .response import Response
|
28
27
|
from .singleecujob import SingleEcuJob
|
28
|
+
from .snrefcontext import SnRefContext
|
29
29
|
from .specialdatagroup import SpecialDataGroup
|
30
30
|
from .statechart import StateChart
|
31
31
|
from .utils import dataclass_fields_asdict
|
32
32
|
|
33
|
-
if TYPE_CHECKING:
|
34
|
-
from .diaglayer import DiagLayer
|
35
|
-
|
36
33
|
|
37
34
|
@dataclass
|
38
35
|
class DiagLayerRaw(IdentifiableElement):
|
@@ -153,7 +150,9 @@ class DiagLayerRaw(IdentifiableElement):
|
|
153
150
|
for el in et_element.iterfind("ADDITIONAL-AUDIENCES/ADDITIONAL-AUDIENCE")
|
154
151
|
]
|
155
152
|
|
156
|
-
sdgs =
|
153
|
+
sdgs = [
|
154
|
+
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
155
|
+
]
|
157
156
|
|
158
157
|
parent_refs = [
|
159
158
|
ParentRef.from_et(pr_el, doc_frags)
|
@@ -282,7 +281,7 @@ class DiagLayerRaw(IdentifiableElement):
|
|
282
281
|
for comparam in self.comparams:
|
283
282
|
comparam._resolve_odxlinks(odxlinks)
|
284
283
|
|
285
|
-
def _resolve_snrefs(self,
|
284
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
286
285
|
self._prot_stack: Optional[ProtStack] = None
|
287
286
|
if self.prot_stack_snref is not None:
|
288
287
|
cp_spec = self.comparam_spec
|
@@ -292,36 +291,36 @@ class DiagLayerRaw(IdentifiableElement):
|
|
292
291
|
|
293
292
|
# do short-name reference resolution
|
294
293
|
if self.admin_data is not None:
|
295
|
-
self.admin_data._resolve_snrefs(
|
294
|
+
self.admin_data._resolve_snrefs(context)
|
296
295
|
if self.diag_data_dictionary_spec is not None:
|
297
|
-
self.diag_data_dictionary_spec._resolve_snrefs(
|
296
|
+
self.diag_data_dictionary_spec._resolve_snrefs(context)
|
298
297
|
|
299
298
|
for company_data in self.company_datas:
|
300
|
-
company_data._resolve_snrefs(
|
299
|
+
company_data._resolve_snrefs(context)
|
301
300
|
for functional_class in self.functional_classes:
|
302
|
-
functional_class._resolve_snrefs(
|
301
|
+
functional_class._resolve_snrefs(context)
|
303
302
|
for diag_comm in self.diag_comms:
|
304
303
|
if isinstance(diag_comm, OdxLinkRef):
|
305
304
|
continue
|
306
|
-
diag_comm._resolve_snrefs(
|
305
|
+
diag_comm._resolve_snrefs(context)
|
307
306
|
for request in self.requests:
|
308
|
-
request._resolve_snrefs(
|
307
|
+
request._resolve_snrefs(context)
|
309
308
|
for positive_response in self.positive_responses:
|
310
|
-
positive_response._resolve_snrefs(
|
309
|
+
positive_response._resolve_snrefs(context)
|
311
310
|
for negative_response in self.negative_responses:
|
312
|
-
negative_response._resolve_snrefs(
|
311
|
+
negative_response._resolve_snrefs(context)
|
313
312
|
for global_negative_response in self.global_negative_responses:
|
314
|
-
global_negative_response._resolve_snrefs(
|
313
|
+
global_negative_response._resolve_snrefs(context)
|
315
314
|
for state_chart in self.state_charts:
|
316
|
-
state_chart._resolve_snrefs(
|
315
|
+
state_chart._resolve_snrefs(context)
|
317
316
|
for additional_audience in self.additional_audiences:
|
318
|
-
additional_audience._resolve_snrefs(
|
317
|
+
additional_audience._resolve_snrefs(context)
|
319
318
|
for sdg in self.sdgs:
|
320
|
-
sdg._resolve_snrefs(
|
319
|
+
sdg._resolve_snrefs(context)
|
321
320
|
for parent_ref in self.parent_refs:
|
322
|
-
parent_ref._resolve_snrefs(
|
321
|
+
parent_ref._resolve_snrefs(context)
|
323
322
|
for comparam in self.comparams:
|
324
|
-
comparam._resolve_snrefs(
|
323
|
+
comparam._resolve_snrefs(context)
|
325
324
|
|
326
325
|
@property
|
327
326
|
def comparam_spec(self) -> Optional[Union[ComparamSpec, ComparamSubset]]:
|
@@ -1,19 +1,16 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional, Union
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
-
from .createsdgs import create_sdgs_from_et
|
7
6
|
from .element import IdentifiableElement
|
8
7
|
from .exceptions import odxrequire
|
9
8
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
10
9
|
from .odxtypes import odxstr_to_bool
|
10
|
+
from .snrefcontext import SnRefContext
|
11
11
|
from .specialdatagroup import SpecialDataGroup
|
12
12
|
from .utils import dataclass_fields_asdict
|
13
13
|
|
14
|
-
if TYPE_CHECKING:
|
15
|
-
from .diaglayer import DiagLayer
|
16
|
-
|
17
14
|
|
18
15
|
@dataclass
|
19
16
|
class DiagnosticTroubleCode(IdentifiableElement):
|
@@ -43,7 +40,9 @@ class DiagnosticTroubleCode(IdentifiableElement):
|
|
43
40
|
level = None
|
44
41
|
|
45
42
|
is_temporary_raw = odxstr_to_bool(et_element.get("IS-TEMPORARY"))
|
46
|
-
sdgs =
|
43
|
+
sdgs = [
|
44
|
+
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
45
|
+
]
|
47
46
|
|
48
47
|
return DiagnosticTroubleCode(
|
49
48
|
trouble_code=int(odxrequire(et_element.findtext("TROUBLE-CODE"))),
|
@@ -69,6 +68,6 @@ class DiagnosticTroubleCode(IdentifiableElement):
|
|
69
68
|
for sdg in self.sdgs:
|
70
69
|
sdg._resolve_odxlinks(odxlinks)
|
71
70
|
|
72
|
-
def _resolve_snrefs(self,
|
71
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
73
72
|
for sdg in self.sdgs:
|
74
|
-
sdg._resolve_snrefs(
|
73
|
+
sdg._resolve_snrefs(context)
|
odxtools/diagservice.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from enum import Enum
|
4
|
-
from typing import
|
4
|
+
from typing import Any, Dict, List, Optional, Union, cast
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .comparaminstance import ComparamInstance
|
@@ -14,11 +14,9 @@ from .odxtypes import ParameterValue, odxstr_to_bool
|
|
14
14
|
from .parameters.parameter import Parameter
|
15
15
|
from .request import Request
|
16
16
|
from .response import Response
|
17
|
+
from .snrefcontext import SnRefContext
|
17
18
|
from .utils import dataclass_fields_asdict
|
18
19
|
|
19
|
-
if TYPE_CHECKING:
|
20
|
-
from .diaglayer import DiagLayer
|
21
|
-
|
22
20
|
|
23
21
|
class Addressing(Enum):
|
24
22
|
FUNCTIONAL = "FUNCTIONAL"
|
@@ -175,16 +173,20 @@ class DiagService(DiagComm):
|
|
175
173
|
self._negative_responses = NamedItemList[Response](
|
176
174
|
[odxlinks.resolve(x, Response) for x in self.neg_response_refs])
|
177
175
|
|
178
|
-
def _resolve_snrefs(self,
|
179
|
-
|
176
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
177
|
+
context.diag_service = self
|
178
|
+
|
179
|
+
super()._resolve_snrefs(context)
|
180
180
|
|
181
181
|
for cpr in self.comparam_refs:
|
182
|
-
cpr._resolve_snrefs(
|
182
|
+
cpr._resolve_snrefs(context)
|
183
183
|
|
184
184
|
# comparams named list is lazy loaded
|
185
185
|
# since ComparamInstance short_name is only valid after resolution
|
186
186
|
self._comparams = NamedItemList(self.comparam_refs)
|
187
187
|
|
188
|
+
context.diag_service = None
|
189
|
+
|
188
190
|
def decode_message(self, raw_message: bytes) -> Message:
|
189
191
|
request_prefix = b''
|
190
192
|
candidate_coding_objects: List[Union[Request, Response]] = [
|
odxtools/docrevision.py
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .companyrevisioninfo import CompanyRevisionInfo
|
7
7
|
from .exceptions import odxrequire
|
8
8
|
from .modification import Modification
|
9
9
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
10
|
+
from .snrefcontext import SnRefContext
|
10
11
|
from .teammember import TeamMember
|
11
12
|
|
12
|
-
if TYPE_CHECKING:
|
13
|
-
from .diaglayer import DiagLayer
|
14
|
-
|
15
13
|
|
16
14
|
@dataclass
|
17
15
|
class DocRevision:
|
@@ -75,9 +73,9 @@ class DocRevision:
|
|
75
73
|
for mod in self.modifications:
|
76
74
|
mod._resolve_odxlinks(odxlinks)
|
77
75
|
|
78
|
-
def _resolve_snrefs(self,
|
76
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
79
77
|
for cri in self.company_revision_infos:
|
80
|
-
cri._resolve_snrefs(
|
78
|
+
cri._resolve_snrefs(context)
|
81
79
|
|
82
80
|
for mod in self.modifications:
|
83
|
-
mod._resolve_snrefs(
|
81
|
+
mod._resolve_snrefs(context)
|
odxtools/dopbase.py
CHANGED
@@ -1,21 +1,18 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional
|
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 .decodestate import DecodeState
|
9
8
|
from .element import IdentifiableElement
|
10
9
|
from .encodestate import EncodeState
|
11
10
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
12
11
|
from .odxtypes import ParameterValue
|
12
|
+
from .snrefcontext import SnRefContext
|
13
13
|
from .specialdatagroup import SpecialDataGroup
|
14
14
|
from .utils import dataclass_fields_asdict
|
15
15
|
|
16
|
-
if TYPE_CHECKING:
|
17
|
-
from .diaglayer import DiagLayer
|
18
|
-
|
19
16
|
|
20
17
|
@dataclass
|
21
18
|
class DopBase(IdentifiableElement):
|
@@ -37,7 +34,9 @@ class DopBase(IdentifiableElement):
|
|
37
34
|
if (admin_data_elem := et_element.find("ADMIN-DATA")) is not None:
|
38
35
|
admin_data = AdminData.from_et(admin_data_elem, doc_frags)
|
39
36
|
|
40
|
-
sdgs =
|
37
|
+
sdgs = [
|
38
|
+
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
39
|
+
]
|
41
40
|
|
42
41
|
return DopBase(admin_data=admin_data, sdgs=sdgs, **kwargs)
|
43
42
|
|
@@ -53,9 +52,9 @@ class DopBase(IdentifiableElement):
|
|
53
52
|
for sdg in self.sdgs:
|
54
53
|
sdg._resolve_odxlinks(odxlinks)
|
55
54
|
|
56
|
-
def _resolve_snrefs(self,
|
55
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
57
56
|
for sdg in self.sdgs:
|
58
|
-
sdg._resolve_snrefs(
|
57
|
+
sdg._resolve_snrefs(context)
|
59
58
|
|
60
59
|
def get_static_bit_length(self) -> Optional[int]:
|
61
60
|
return None
|
odxtools/dtcdop.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
# from dataclasses import dataclass, field
|
3
2
|
from dataclasses import dataclass
|
4
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional, Union, cast
|
5
4
|
from xml.etree import ElementTree
|
6
5
|
|
7
6
|
from typing_extensions import override
|
@@ -19,11 +18,9 @@ from .nameditemlist import NamedItemList
|
|
19
18
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
20
19
|
from .odxtypes import ParameterValue, odxstr_to_bool
|
21
20
|
from .physicaltype import PhysicalType
|
21
|
+
from .snrefcontext import SnRefContext
|
22
22
|
from .utils import dataclass_fields_asdict
|
23
23
|
|
24
|
-
if TYPE_CHECKING:
|
25
|
-
from .diaglayer import DiagLayer
|
26
|
-
|
27
24
|
|
28
25
|
@dataclass
|
29
26
|
class DtcDop(DopBase):
|
@@ -177,9 +174,9 @@ class DtcDop(DopBase):
|
|
177
174
|
linked_dtc_dops = [odxlinks.resolve(x, DtcDop) for x in self.linked_dtc_dop_refs]
|
178
175
|
self._linked_dtc_dops = NamedItemList(linked_dtc_dops)
|
179
176
|
|
180
|
-
def _resolve_snrefs(self,
|
181
|
-
super()._resolve_snrefs(
|
177
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
178
|
+
super()._resolve_snrefs(context)
|
182
179
|
|
183
180
|
for dtc_proxy in self.dtcs_raw:
|
184
181
|
if isinstance(dtc_proxy, DiagnosticTroubleCode):
|
185
|
-
dtc_proxy._resolve_snrefs(
|
182
|
+
dtc_proxy._resolve_snrefs(context)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Sequence
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -13,11 +13,9 @@ from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequir
|
|
13
13
|
from .field import Field
|
14
14
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
15
15
|
from .odxtypes import AtomicOdxType, ParameterValue
|
16
|
+
from .snrefcontext import SnRefContext
|
16
17
|
from .utils import dataclass_fields_asdict
|
17
18
|
|
18
|
-
if TYPE_CHECKING:
|
19
|
-
from .diaglayer import DiagLayer
|
20
|
-
|
21
19
|
|
22
20
|
@dataclass
|
23
21
|
class DynamicEndmarkerField(Field):
|
@@ -49,8 +47,8 @@ class DynamicEndmarkerField(Field):
|
|
49
47
|
|
50
48
|
self._termination_value = tv_physical
|
51
49
|
|
52
|
-
def _resolve_snrefs(self,
|
53
|
-
super()._resolve_snrefs(
|
50
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
51
|
+
super()._resolve_snrefs(context)
|
54
52
|
|
55
53
|
@property
|
56
54
|
def dyn_end_dop(self) -> DataObjectProperty:
|
@@ -81,8 +79,17 @@ class DynamicEndmarkerField(Field):
|
|
81
79
|
encode_state.is_end_of_pdu = orig_is_end_of_pdu
|
82
80
|
|
83
81
|
if not encode_state.is_end_of_pdu:
|
84
|
-
# only add an endmarker if we are not at the end of the
|
82
|
+
# only add an endmarker if we are not at the end of the
|
83
|
+
# PDU. note that since section 7.3.6.10.5 of the MCD-2
|
84
|
+
# specification states that the data used by the endmarker
|
85
|
+
# ought to be considered to be not consumed (why?!), we
|
86
|
+
# need to keep the cursor where it is before adding the
|
87
|
+
# endmarker. (we still consider its bits to be used
|
88
|
+
# "used", in order to produce a warning if it is attempted
|
89
|
+
# to be overridden.)
|
90
|
+
tmp_cursor = encode_state.cursor_byte_position
|
85
91
|
self.dyn_end_dop.encode_into_pdu(self.termination_value, encode_state)
|
92
|
+
encode_state.cursor_byte_position = tmp_cursor
|
86
93
|
|
87
94
|
@override
|
88
95
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -91,7 +98,6 @@ class DynamicEndmarkerField(Field):
|
|
91
98
|
"No bit position can be specified for dynamic endmarker fields!")
|
92
99
|
|
93
100
|
orig_origin = decode_state.origin_byte_position
|
94
|
-
orig_cursor = decode_state.cursor_byte_position
|
95
101
|
decode_state.origin_byte_position = decode_state.cursor_byte_position
|
96
102
|
|
97
103
|
result: List[ParameterValue] = []
|
@@ -106,6 +112,14 @@ class DynamicEndmarkerField(Field):
|
|
106
112
|
try:
|
107
113
|
tv_candidate = self.dyn_end_dop.decode_from_pdu(decode_state)
|
108
114
|
if tv_candidate == self.termination_value:
|
115
|
+
# note that section 7.3.6.10.5 of the MCD-2
|
116
|
+
# specification states that the bytes occupied by
|
117
|
+
# the endmarker ought to be considered to be not
|
118
|
+
# consumed (why?!), i.e., we need to keep the
|
119
|
+
# cursor where it is before adding the
|
120
|
+
# endmarker. (we still consider its to be used
|
121
|
+
# "used", though.)
|
122
|
+
decode_state.cursor_byte_position = tmp_cursor
|
109
123
|
break
|
110
124
|
except DecodeError:
|
111
125
|
pass
|
@@ -114,6 +128,5 @@ class DynamicEndmarkerField(Field):
|
|
114
128
|
result.append(self.structure.decode_from_pdu(decode_state))
|
115
129
|
|
116
130
|
decode_state.origin_byte_position = orig_origin
|
117
|
-
decode_state.cursor_byte_position = max(orig_cursor, decode_state.cursor_byte_position)
|
118
131
|
|
119
132
|
return result
|
odxtools/dynamiclengthfield.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Sequence
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -12,11 +12,9 @@ from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequir
|
|
12
12
|
from .field import Field
|
13
13
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
14
14
|
from .odxtypes import ParameterValue
|
15
|
+
from .snrefcontext import SnRefContext
|
15
16
|
from .utils import dataclass_fields_asdict
|
16
17
|
|
17
|
-
if TYPE_CHECKING:
|
18
|
-
from .diaglayer import DiagLayer
|
19
|
-
|
20
18
|
|
21
19
|
@dataclass
|
22
20
|
class DynamicLengthField(Field):
|
@@ -45,9 +43,9 @@ class DynamicLengthField(Field):
|
|
45
43
|
super()._resolve_odxlinks(odxlinks)
|
46
44
|
self.determine_number_of_items._resolve_odxlinks(odxlinks)
|
47
45
|
|
48
|
-
def _resolve_snrefs(self,
|
49
|
-
super()._resolve_snrefs(
|
50
|
-
self.determine_number_of_items._resolve_snrefs(
|
46
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
47
|
+
super()._resolve_snrefs(context)
|
48
|
+
self.determine_number_of_items._resolve_snrefs(context)
|
51
49
|
|
52
50
|
@override
|
53
51
|
def encode_into_pdu(self, physical_value: ParameterValue, encode_state: EncodeState) -> None:
|
@@ -61,7 +59,6 @@ class DynamicLengthField(Field):
|
|
61
59
|
f"got {type(physical_value)}", EncodeError)
|
62
60
|
|
63
61
|
# move the origin to the cursor position
|
64
|
-
orig_cursor = encode_state.cursor_byte_position
|
65
62
|
orig_origin = encode_state.origin_byte_position
|
66
63
|
encode_state.origin_byte_position = encode_state.cursor_byte_position
|
67
64
|
|
@@ -92,7 +89,6 @@ class DynamicLengthField(Field):
|
|
92
89
|
|
93
90
|
# move cursor and origin positions
|
94
91
|
encode_state.origin_byte_position = orig_origin
|
95
|
-
encode_state.cursor_byte_position = max(orig_cursor, encode_state.cursor_byte_position)
|
96
92
|
|
97
93
|
@override
|
98
94
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -101,7 +97,6 @@ class DynamicLengthField(Field):
|
|
101
97
|
"No bit position can be specified for dynamic length fields!")
|
102
98
|
|
103
99
|
orig_origin = decode_state.origin_byte_position
|
104
|
-
orig_cursor = decode_state.cursor_byte_position
|
105
100
|
|
106
101
|
det_num_items = self.determine_number_of_items
|
107
102
|
decode_state.origin_byte_position = decode_state.cursor_byte_position
|
@@ -125,6 +120,5 @@ class DynamicLengthField(Field):
|
|
125
120
|
result.append(self.structure.decode_from_pdu(decode_state))
|
126
121
|
|
127
122
|
decode_state.origin_byte_position = orig_origin
|
128
|
-
decode_state.cursor_byte_position = max(orig_cursor, decode_state.cursor_byte_position)
|
129
123
|
|
130
124
|
return result
|
odxtools/element.py
CHANGED
@@ -2,16 +2,17 @@ from dataclasses import dataclass
|
|
2
2
|
from typing import List, Optional
|
3
3
|
from xml.etree import ElementTree
|
4
4
|
|
5
|
+
from .description import Description
|
5
6
|
from .exceptions import odxrequire
|
6
7
|
from .odxlink import OdxDocFragment, OdxLinkId
|
7
|
-
from .utils import
|
8
|
+
from .utils import dataclass_fields_asdict
|
8
9
|
|
9
10
|
|
10
11
|
@dataclass
|
11
12
|
class NamedElement:
|
12
13
|
short_name: str
|
13
14
|
long_name: Optional[str]
|
14
|
-
description: Optional[
|
15
|
+
description: Optional[Description]
|
15
16
|
|
16
17
|
@staticmethod
|
17
18
|
def from_et(
|
@@ -22,7 +23,7 @@ class NamedElement:
|
|
22
23
|
return NamedElement(
|
23
24
|
short_name=odxrequire(et_element.findtext("SHORT-NAME")),
|
24
25
|
long_name=et_element.findtext("LONG-NAME"),
|
25
|
-
description=
|
26
|
+
description=Description.from_et(et_element.find("DESC"), doc_frags),
|
26
27
|
)
|
27
28
|
|
28
29
|
|
odxtools/endofpdufield.py
CHANGED
@@ -72,7 +72,6 @@ class EndOfPduField(Field):
|
|
72
72
|
"No bit position can be specified for end-of-pdu fields!")
|
73
73
|
|
74
74
|
orig_origin = decode_state.origin_byte_position
|
75
|
-
orig_cursor = decode_state.cursor_byte_position
|
76
75
|
decode_state.origin_byte_position = decode_state.cursor_byte_position
|
77
76
|
|
78
77
|
result: List[ParameterValue] = []
|
@@ -84,6 +83,5 @@ class EndOfPduField(Field):
|
|
84
83
|
result.append(self.structure.decode_from_pdu(decode_state))
|
85
84
|
|
86
85
|
decode_state.origin_byte_position = orig_origin
|
87
|
-
decode_state.cursor_byte_position = max(orig_cursor, decode_state.cursor_byte_position)
|
88
86
|
|
89
87
|
return result
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -12,11 +12,9 @@ from .environmentdata import EnvironmentData
|
|
12
12
|
from .exceptions import odxraise, odxrequire
|
13
13
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
14
14
|
from .odxtypes import ParameterValue
|
15
|
+
from .snrefcontext import SnRefContext
|
15
16
|
from .utils import dataclass_fields_asdict
|
16
17
|
|
17
|
-
if TYPE_CHECKING:
|
18
|
-
from .diaglayer import DiagLayer
|
19
|
-
|
20
18
|
|
21
19
|
@dataclass
|
22
20
|
class EnvironmentDataDescription(ComplexDop):
|
@@ -87,12 +85,12 @@ class EnvironmentDataDescription(ComplexDop):
|
|
87
85
|
for ed in self.env_datas:
|
88
86
|
ed._resolve_odxlinks(odxlinks)
|
89
87
|
|
90
|
-
def _resolve_snrefs(self,
|
88
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
91
89
|
# ODX 2.0 specifies environment data objects here, ODX 2.2
|
92
90
|
# uses references
|
93
91
|
if self.env_data_refs:
|
94
92
|
for ed in self.env_datas:
|
95
|
-
ed._resolve_snrefs(
|
93
|
+
ed._resolve_snrefs(context)
|
96
94
|
|
97
95
|
@override
|
98
96
|
def encode_into_pdu(self, physical_value: Optional[ParameterValue],
|
odxtools/exceptions.py
CHANGED
odxtools/field.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
1
2
|
from dataclasses import dataclass
|
2
|
-
from typing import
|
3
|
+
from typing import List, Optional
|
3
4
|
from xml.etree import ElementTree
|
4
5
|
|
5
6
|
from .basicstructure import BasicStructure
|
@@ -8,11 +9,9 @@ from .environmentdatadescription import EnvironmentDataDescription
|
|
8
9
|
from .exceptions import odxassert, odxrequire
|
9
10
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkRef, resolve_snref
|
10
11
|
from .odxtypes import odxstr_to_bool
|
12
|
+
from .snrefcontext import SnRefContext
|
11
13
|
from .utils import dataclass_fields_asdict
|
12
14
|
|
13
|
-
if TYPE_CHECKING:
|
14
|
-
from .diaglayer import DiagLayer
|
15
|
-
|
16
15
|
|
17
16
|
@dataclass
|
18
17
|
class Field(ComplexDop):
|
@@ -80,13 +79,14 @@ class Field(ComplexDop):
|
|
80
79
|
self._env_data_desc = odxlinks.resolve(self.env_data_desc_ref,
|
81
80
|
EnvironmentDataDescription)
|
82
81
|
|
83
|
-
def _resolve_snrefs(self,
|
82
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
84
83
|
"""Recursively resolve any short-name references"""
|
84
|
+
ddd_spec = odxrequire(context.diag_layer).diag_data_dictionary_spec
|
85
|
+
|
85
86
|
if self.structure_snref is not None:
|
86
|
-
|
87
|
-
|
87
|
+
self._structure = resolve_snref(self.structure_snref, ddd_spec.structures,
|
88
|
+
BasicStructure)
|
88
89
|
|
89
90
|
if self.env_data_desc_snref is not None:
|
90
|
-
|
91
|
-
self._env_data_desc = resolve_snref(self.env_data_desc_snref, env_data_descs,
|
91
|
+
self._env_data_desc = resolve_snref(self.env_data_desc_snref, ddd_spec.env_data_descs,
|
92
92
|
EnvironmentDataDescription)
|