odxtools 9.7.0__py3-none-any.whl → 10.1.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/additionalaudience.py +7 -7
- odxtools/admindata.py +14 -13
- odxtools/audience.py +17 -17
- odxtools/basecomparam.py +9 -8
- odxtools/basevariantpattern.py +9 -10
- odxtools/basicstructure.py +15 -15
- odxtools/cli/_print_utils.py +34 -22
- odxtools/cli/browse.py +8 -8
- odxtools/cli/compare.py +24 -24
- odxtools/cli/decode.py +3 -4
- odxtools/cli/find.py +4 -5
- odxtools/cli/list.py +6 -6
- odxtools/cli/main.py +2 -2
- odxtools/cli/snoop.py +3 -3
- odxtools/codec.py +3 -3
- odxtools/commrelation.py +18 -17
- odxtools/companydata.py +13 -13
- odxtools/companydocinfo.py +15 -17
- odxtools/companyrevisioninfo.py +9 -9
- odxtools/companyspecificinfo.py +11 -13
- odxtools/comparam.py +8 -7
- odxtools/comparaminstance.py +14 -14
- odxtools/comparamspec.py +10 -11
- odxtools/comparamsubset.py +17 -25
- odxtools/complexcomparam.py +14 -14
- odxtools/complexdop.py +1 -1
- odxtools/compositecodec.py +8 -8
- odxtools/compumethods/compucodecompumethod.py +7 -7
- odxtools/compumethods/compuconst.py +5 -6
- odxtools/compumethods/compudefaultvalue.py +2 -3
- odxtools/compumethods/compuinternaltophys.py +13 -12
- odxtools/compumethods/compumethod.py +10 -9
- odxtools/compumethods/compuphystointernal.py +13 -12
- odxtools/compumethods/compurationalcoeffs.py +7 -7
- odxtools/compumethods/compuscale.py +15 -16
- odxtools/compumethods/createanycompumethod.py +12 -13
- odxtools/compumethods/identicalcompumethod.py +4 -5
- odxtools/compumethods/limit.py +14 -14
- odxtools/compumethods/linearcompumethod.py +5 -5
- odxtools/compumethods/linearsegment.py +10 -11
- odxtools/compumethods/ratfunccompumethod.py +6 -6
- odxtools/compumethods/ratfuncsegment.py +7 -8
- odxtools/compumethods/scalelinearcompumethod.py +9 -9
- odxtools/compumethods/scaleratfunccompumethod.py +7 -7
- odxtools/compumethods/tabintpcompumethod.py +10 -13
- odxtools/compumethods/texttablecompumethod.py +6 -6
- odxtools/createanycomparam.py +5 -7
- odxtools/createanydiagcodedtype.py +7 -8
- odxtools/database.py +34 -31
- odxtools/dataobjectproperty.py +19 -20
- odxtools/decodestate.py +5 -5
- odxtools/description.py +9 -9
- odxtools/determinenumberofitems.py +8 -7
- odxtools/diagcodedtype.py +10 -10
- odxtools/diagcomm.py +29 -30
- odxtools/diagdatadictionaryspec.py +36 -36
- odxtools/diaglayercontainer.py +35 -34
- odxtools/diaglayers/basevariant.py +14 -12
- odxtools/diaglayers/basevariantraw.py +22 -23
- odxtools/diaglayers/diaglayer.py +24 -22
- odxtools/diaglayers/diaglayerraw.py +43 -52
- odxtools/diaglayers/diaglayertype.py +1 -2
- odxtools/diaglayers/ecushareddata.py +9 -9
- odxtools/diaglayers/ecushareddataraw.py +15 -16
- odxtools/diaglayers/ecuvariant.py +15 -13
- odxtools/diaglayers/ecuvariantraw.py +21 -22
- odxtools/diaglayers/functionalgroup.py +12 -11
- odxtools/diaglayers/functionalgroupraw.py +17 -18
- odxtools/diaglayers/hierarchyelement.py +48 -54
- odxtools/diaglayers/hierarchyelementraw.py +10 -11
- odxtools/diaglayers/protocol.py +7 -7
- odxtools/diaglayers/protocolraw.py +13 -14
- odxtools/diagnostictroublecode.py +15 -17
- odxtools/diagservice.py +28 -27
- odxtools/diagvariable.py +24 -25
- odxtools/docrevision.py +18 -17
- odxtools/dopbase.py +13 -14
- odxtools/dtcconnector.py +8 -7
- odxtools/dtcdop.py +24 -20
- odxtools/dynamicendmarkerfield.py +10 -9
- odxtools/dynamiclengthfield.py +10 -9
- odxtools/dyndefinedspec.py +10 -10
- odxtools/dynenddopref.py +9 -9
- odxtools/dyniddefmodeinfo.py +21 -21
- odxtools/ecuvariantpattern.py +8 -10
- odxtools/element.py +12 -13
- odxtools/encodestate.py +11 -11
- odxtools/encoding.py +2 -3
- odxtools/endofpdufield.py +9 -10
- odxtools/envdataconnector.py +8 -8
- odxtools/environmentdata.py +7 -9
- odxtools/environmentdatadescription.py +18 -17
- odxtools/exceptions.py +5 -5
- odxtools/externalaccessmethod.py +4 -6
- odxtools/externaldoc.py +6 -6
- odxtools/field.py +15 -15
- odxtools/functionalclass.py +9 -9
- odxtools/inputparam.py +11 -10
- odxtools/internalconstr.py +10 -11
- odxtools/isotp_state_machine.py +12 -11
- odxtools/leadinglengthinfotype.py +4 -6
- odxtools/library.py +9 -8
- odxtools/linkeddtcdop.py +9 -8
- odxtools/loadfile.py +5 -6
- odxtools/matchingbasevariantparameter.py +5 -6
- odxtools/matchingparameter.py +10 -10
- odxtools/message.py +1 -1
- odxtools/minmaxlengthtype.py +6 -7
- odxtools/modification.py +7 -6
- odxtools/multiplexer.py +54 -18
- odxtools/multiplexercase.py +13 -13
- odxtools/multiplexerdefaultcase.py +11 -10
- odxtools/multiplexerswitchkey.py +8 -8
- odxtools/nameditemlist.py +13 -13
- odxtools/negoutputparam.py +8 -8
- odxtools/obd.py +1 -2
- odxtools/odxcategory.py +14 -26
- odxtools/odxdoccontext.py +16 -0
- odxtools/odxlink.py +23 -25
- odxtools/odxtypes.py +18 -15
- odxtools/outputparam.py +9 -8
- odxtools/parameterinfo.py +1 -1
- odxtools/parameters/codedconstparameter.py +10 -10
- odxtools/parameters/createanyparameter.py +15 -16
- odxtools/parameters/dynamicparameter.py +5 -7
- odxtools/parameters/lengthkeyparameter.py +10 -10
- odxtools/parameters/matchingrequestparameter.py +6 -7
- odxtools/parameters/nrcconstparameter.py +13 -13
- odxtools/parameters/parameter.py +17 -18
- odxtools/parameters/parameterwithdop.py +13 -13
- odxtools/parameters/physicalconstantparameter.py +8 -7
- odxtools/parameters/reservedparameter.py +6 -8
- odxtools/parameters/systemparameter.py +5 -7
- odxtools/parameters/tableentryparameter.py +8 -8
- odxtools/parameters/tablekeyparameter.py +17 -17
- odxtools/parameters/tablestructparameter.py +11 -11
- odxtools/parameters/valueparameter.py +11 -11
- odxtools/paramlengthinfotype.py +10 -9
- odxtools/parentref.py +15 -13
- odxtools/physicaldimension.py +15 -15
- odxtools/physicaltype.py +5 -6
- odxtools/posresponsesuppressible.py +11 -12
- odxtools/preconditionstateref.py +11 -11
- odxtools/progcode.py +11 -10
- odxtools/protstack.py +10 -9
- odxtools/relateddiagcommref.py +5 -6
- odxtools/relateddoc.py +11 -10
- odxtools/request.py +18 -19
- odxtools/response.py +19 -20
- odxtools/scaleconstr.py +8 -9
- odxtools/servicebinner.py +5 -5
- odxtools/singleecujob.py +16 -15
- odxtools/snrefcontext.py +3 -3
- odxtools/specialdata.py +8 -7
- odxtools/specialdatagroup.py +17 -17
- odxtools/specialdatagroupcaption.py +7 -6
- odxtools/standardlengthtype.py +14 -22
- odxtools/state.py +7 -6
- odxtools/statechart.py +12 -11
- odxtools/statemachine.py +4 -3
- odxtools/statetransition.py +9 -9
- odxtools/statetransitionref.py +19 -19
- odxtools/staticfield.py +9 -7
- odxtools/structure.py +5 -6
- odxtools/subcomponent.py +20 -18
- odxtools/subcomponentparamconnector.py +10 -9
- odxtools/subcomponentpattern.py +9 -9
- odxtools/swvariable.py +6 -7
- odxtools/table.py +25 -26
- odxtools/tablediagcommconnector.py +9 -8
- odxtools/tablerow.py +64 -43
- odxtools/tablerowconnector.py +8 -8
- odxtools/teammember.py +16 -15
- odxtools/templates/macros/printParentRef.xml.jinja2 +3 -1
- odxtools/text.py +4 -5
- odxtools/uds.py +2 -3
- odxtools/unit.py +14 -13
- odxtools/unitgroup.py +11 -10
- odxtools/unitspec.py +18 -19
- odxtools/utils.py +3 -3
- odxtools/variablegroup.py +5 -6
- odxtools/variantmatcher.py +10 -10
- odxtools/variantpattern.py +5 -6
- odxtools/version.py +2 -2
- odxtools/writepdxfile.py +5 -24
- odxtools/xdoc.py +13 -12
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/METADATA +4 -5
- odxtools-10.1.0.dist-info/RECORD +265 -0
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/WHEEL +1 -1
- odxtools-9.7.0.dist-info/RECORD +0 -264
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/entry_points.txt +0 -0
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/licenses/LICENSE +0 -0
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
2
|
+
from dataclasses import dataclass, field
|
3
3
|
from itertools import chain
|
4
|
-
from typing import Any
|
4
|
+
from typing import Any
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .admindata import AdminData
|
@@ -15,7 +15,8 @@ from .environmentdata import EnvironmentData
|
|
15
15
|
from .environmentdatadescription import EnvironmentDataDescription
|
16
16
|
from .multiplexer import Multiplexer
|
17
17
|
from .nameditemlist import NamedItemList
|
18
|
-
from .
|
18
|
+
from .odxdoccontext import OdxDocContext
|
19
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
19
20
|
from .snrefcontext import SnRefContext
|
20
21
|
from .specialdatagroup import SpecialDataGroup
|
21
22
|
from .staticfield import StaticField
|
@@ -24,72 +25,73 @@ from .table import Table
|
|
24
25
|
from .unitspec import UnitSpec
|
25
26
|
|
26
27
|
|
27
|
-
@dataclass
|
28
|
+
@dataclass(kw_only=True)
|
28
29
|
class DiagDataDictionarySpec:
|
29
|
-
admin_data:
|
30
|
-
dtc_dops: NamedItemList[DtcDop]
|
31
|
-
env_data_descs: NamedItemList[EnvironmentDataDescription]
|
32
|
-
data_object_props: NamedItemList[DataObjectProperty]
|
33
|
-
structures: NamedItemList[Structure]
|
34
|
-
static_fields: NamedItemList[StaticField]
|
35
|
-
dynamic_length_fields: NamedItemList[DynamicLengthField]
|
36
|
-
dynamic_endmarker_fields: NamedItemList[DynamicEndmarkerField]
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
30
|
+
admin_data: AdminData | None = None
|
31
|
+
dtc_dops: NamedItemList[DtcDop] = field(default_factory=NamedItemList)
|
32
|
+
env_data_descs: NamedItemList[EnvironmentDataDescription] = field(default_factory=NamedItemList)
|
33
|
+
data_object_props: NamedItemList[DataObjectProperty] = field(default_factory=NamedItemList)
|
34
|
+
structures: NamedItemList[Structure] = field(default_factory=NamedItemList)
|
35
|
+
static_fields: NamedItemList[StaticField] = field(default_factory=NamedItemList)
|
36
|
+
dynamic_length_fields: NamedItemList[DynamicLengthField] = field(default_factory=NamedItemList)
|
37
|
+
dynamic_endmarker_fields: NamedItemList[DynamicEndmarkerField] = field(
|
38
|
+
default_factory=NamedItemList)
|
39
|
+
end_of_pdu_fields: NamedItemList[EndOfPduField] = field(default_factory=NamedItemList)
|
40
|
+
muxs: NamedItemList[Multiplexer] = field(default_factory=NamedItemList)
|
41
|
+
env_datas: NamedItemList[EnvironmentData] = field(default_factory=NamedItemList)
|
42
|
+
unit_spec: UnitSpec | None = None
|
43
|
+
tables: NamedItemList[Table] = field(default_factory=NamedItemList)
|
44
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
43
45
|
|
44
46
|
@staticmethod
|
45
47
|
def from_et(et_element: ElementTree.Element,
|
46
|
-
|
48
|
+
context: OdxDocContext) -> "DiagDataDictionarySpec":
|
47
49
|
admin_data = None
|
48
50
|
if (admin_data_elem := et_element.find("ADMIN-DATA")) is not None:
|
49
|
-
admin_data = AdminData.from_et(admin_data_elem,
|
51
|
+
admin_data = AdminData.from_et(admin_data_elem, context)
|
50
52
|
|
51
53
|
dtc_dops = NamedItemList([
|
52
|
-
DtcDop.from_et(dtc_dop_elem,
|
54
|
+
DtcDop.from_et(dtc_dop_elem, context)
|
53
55
|
for dtc_dop_elem in et_element.iterfind("DTC-DOPS/DTC-DOP")
|
54
56
|
])
|
55
57
|
|
56
58
|
env_data_descs = NamedItemList([
|
57
|
-
EnvironmentDataDescription.from_et(env_data_desc_element,
|
59
|
+
EnvironmentDataDescription.from_et(env_data_desc_element, context)
|
58
60
|
for env_data_desc_element in et_element.iterfind("ENV-DATA-DESCS/ENV-DATA-DESC")
|
59
61
|
])
|
60
62
|
|
61
63
|
data_object_props = NamedItemList([
|
62
|
-
DataObjectProperty.from_et(dop_element,
|
64
|
+
DataObjectProperty.from_et(dop_element, context)
|
63
65
|
for dop_element in et_element.iterfind("DATA-OBJECT-PROPS/DATA-OBJECT-PROP")
|
64
66
|
])
|
65
67
|
|
66
68
|
structures = NamedItemList([
|
67
|
-
Structure.from_et(structure_element,
|
69
|
+
Structure.from_et(structure_element, context)
|
68
70
|
for structure_element in et_element.iterfind("STRUCTURES/STRUCTURE")
|
69
71
|
])
|
70
72
|
|
71
73
|
static_fields = NamedItemList([
|
72
|
-
StaticField.from_et(dl_element,
|
74
|
+
StaticField.from_et(dl_element, context)
|
73
75
|
for dl_element in et_element.iterfind("STATIC-FIELDS/STATIC-FIELD")
|
74
76
|
])
|
75
77
|
|
76
78
|
dynamic_length_fields = NamedItemList([
|
77
|
-
DynamicLengthField.from_et(dl_element,
|
79
|
+
DynamicLengthField.from_et(dl_element, context)
|
78
80
|
for dl_element in et_element.iterfind("DYNAMIC-LENGTH-FIELDS/DYNAMIC-LENGTH-FIELD")
|
79
81
|
])
|
80
82
|
|
81
83
|
dynamic_endmarker_fields = NamedItemList([
|
82
|
-
DynamicEndmarkerField.from_et(dl_element,
|
84
|
+
DynamicEndmarkerField.from_et(dl_element, context) for dl_element in
|
83
85
|
et_element.iterfind("DYNAMIC-ENDMARKER-FIELDS/DYNAMIC-ENDMARKER-FIELD")
|
84
86
|
])
|
85
87
|
|
86
88
|
end_of_pdu_fields = NamedItemList([
|
87
|
-
EndOfPduField.from_et(eofp_element,
|
89
|
+
EndOfPduField.from_et(eofp_element, context)
|
88
90
|
for eofp_element in et_element.iterfind("END-OF-PDU-FIELDS/END-OF-PDU-FIELD")
|
89
91
|
])
|
90
92
|
|
91
93
|
muxs = NamedItemList([
|
92
|
-
Multiplexer.from_et(mux_element,
|
94
|
+
Multiplexer.from_et(mux_element, context)
|
93
95
|
for mux_element in et_element.iterfind("MUXS/MUX")
|
94
96
|
])
|
95
97
|
|
@@ -99,23 +101,21 @@ class DiagDataDictionarySpec:
|
|
99
101
|
et_element.iterfind("ENV-DATA-DESCS/ENV-DATA-DESC/ENV-DATAS/ENV-DATA"),
|
100
102
|
)
|
101
103
|
env_datas = NamedItemList([
|
102
|
-
EnvironmentData.from_et(env_data_element,
|
104
|
+
EnvironmentData.from_et(env_data_element, context)
|
103
105
|
for env_data_element in env_data_elements
|
104
106
|
])
|
105
107
|
|
106
108
|
if (spec_elem := et_element.find("UNIT-SPEC")) is not None:
|
107
|
-
unit_spec = UnitSpec.from_et(spec_elem,
|
109
|
+
unit_spec = UnitSpec.from_et(spec_elem, context)
|
108
110
|
else:
|
109
111
|
unit_spec = None
|
110
112
|
|
111
113
|
tables = NamedItemList([
|
112
|
-
Table.from_et(table_element,
|
114
|
+
Table.from_et(table_element, context)
|
113
115
|
for table_element in et_element.iterfind("TABLES/TABLE")
|
114
116
|
])
|
115
117
|
|
116
|
-
sdgs = [
|
117
|
-
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
118
|
-
]
|
118
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
119
119
|
|
120
120
|
return DiagDataDictionarySpec(
|
121
121
|
admin_data=admin_data,
|
@@ -149,7 +149,7 @@ class DiagDataDictionarySpec:
|
|
149
149
|
self.env_datas,
|
150
150
|
))
|
151
151
|
|
152
|
-
def _build_odxlinks(self) ->
|
152
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
153
153
|
# note that DataDictionarySpec objects do not exhibit an ODXLINK id.
|
154
154
|
odxlinks = {}
|
155
155
|
|
odxtools/diaglayercontainer.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
2
|
+
from dataclasses import dataclass, field
|
3
3
|
from itertools import chain
|
4
|
-
from typing import TYPE_CHECKING, Any
|
4
|
+
from typing import TYPE_CHECKING, Any
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .diaglayers.basevariant import BaseVariant
|
@@ -10,8 +10,10 @@ from .diaglayers.ecushareddata import EcuSharedData
|
|
10
10
|
from .diaglayers.ecuvariant import EcuVariant
|
11
11
|
from .diaglayers.functionalgroup import FunctionalGroup
|
12
12
|
from .diaglayers.protocol import Protocol
|
13
|
+
from .exceptions import odxrequire
|
13
14
|
from .nameditemlist import NamedItemList
|
14
15
|
from .odxcategory import OdxCategory
|
16
|
+
from .odxdoccontext import OdxDocContext
|
15
17
|
from .odxlink import DocType, OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
16
18
|
from .snrefcontext import SnRefContext
|
17
19
|
from .utils import dataclass_fields_asdict
|
@@ -20,13 +22,13 @@ if TYPE_CHECKING:
|
|
20
22
|
from .database import Database
|
21
23
|
|
22
24
|
|
23
|
-
@dataclass
|
25
|
+
@dataclass(kw_only=True)
|
24
26
|
class DiagLayerContainer(OdxCategory):
|
25
|
-
protocols: NamedItemList[Protocol]
|
26
|
-
functional_groups: NamedItemList[FunctionalGroup]
|
27
|
-
ecu_shared_datas: NamedItemList[EcuSharedData]
|
28
|
-
base_variants: NamedItemList[BaseVariant]
|
29
|
-
ecu_variants: NamedItemList[EcuVariant]
|
27
|
+
protocols: NamedItemList[Protocol] = field(default_factory=NamedItemList)
|
28
|
+
functional_groups: NamedItemList[FunctionalGroup] = field(default_factory=NamedItemList)
|
29
|
+
ecu_shared_datas: NamedItemList[EcuSharedData] = field(default_factory=NamedItemList)
|
30
|
+
base_variants: NamedItemList[BaseVariant] = field(default_factory=NamedItemList)
|
31
|
+
ecu_variants: NamedItemList[EcuVariant] = field(default_factory=NamedItemList)
|
30
32
|
|
31
33
|
@property
|
32
34
|
def diag_layers(self) -> NamedItemList[DiagLayer]:
|
@@ -40,33 +42,32 @@ class DiagLayerContainer(OdxCategory):
|
|
40
42
|
return self.ecu_variants
|
41
43
|
|
42
44
|
@staticmethod
|
43
|
-
def from_et(et_element: ElementTree.Element,
|
44
|
-
doc_frags: List[OdxDocFragment]) -> "DiagLayerContainer":
|
45
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DiagLayerContainer":
|
45
46
|
|
46
|
-
cat = OdxCategory.
|
47
|
-
doc_frags = cat.odx_id.doc_fragments
|
47
|
+
cat = OdxCategory.from_et(et_element, context)
|
48
48
|
kwargs = dataclass_fields_asdict(cat)
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
for
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
50
|
+
def get_layer_context(diag_layer_et: ElementTree.Element) -> OdxDocContext:
|
51
|
+
layer_sn = odxrequire(diag_layer_et.findtext("SHORT-NAME"))
|
52
|
+
layer_docfrag = OdxDocFragment(layer_sn, DocType.LAYER)
|
53
|
+
# add layer doc fragment to container doc fragment
|
54
|
+
return OdxDocContext(context.version, (context.doc_fragments[0], layer_docfrag))
|
55
|
+
|
56
|
+
protocols = NamedItemList(
|
57
|
+
Protocol.from_et(layer_et, get_layer_context(layer_et))
|
58
|
+
for layer_et in et_element.iterfind("PROTOCOLS/PROTOCOL"))
|
59
|
+
functional_groups = NamedItemList(
|
60
|
+
FunctionalGroup.from_et(layer_et, get_layer_context(layer_et))
|
61
|
+
for layer_et in et_element.iterfind("FUNCTIONAL-GROUPS/FUNCTIONAL-GROUP"))
|
62
|
+
ecu_shared_datas = NamedItemList(
|
63
|
+
EcuSharedData.from_et(layer_et, get_layer_context(layer_et))
|
64
|
+
for layer_et in et_element.iterfind("ECU-SHARED-DATAS/ECU-SHARED-DATA"))
|
65
|
+
base_variants = NamedItemList(
|
66
|
+
BaseVariant.from_et(layer_et, get_layer_context(layer_et))
|
67
|
+
for layer_et in et_element.iterfind("BASE-VARIANTS/BASE-VARIANT"))
|
68
|
+
ecu_variants = NamedItemList(
|
69
|
+
EcuVariant.from_et(layer_et, get_layer_context(layer_et))
|
70
|
+
for layer_et in et_element.iterfind("ECU-VARIANTS/ECU-VARIANT"))
|
70
71
|
|
71
72
|
return DiagLayerContainer(
|
72
73
|
protocols=protocols,
|
@@ -85,7 +86,7 @@ class DiagLayerContainer(OdxCategory):
|
|
85
86
|
self.ecu_variants,
|
86
87
|
),)
|
87
88
|
|
88
|
-
def _build_odxlinks(self) ->
|
89
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
89
90
|
result = super()._build_odxlinks()
|
90
91
|
|
91
92
|
for protocol in self.protocols:
|
@@ -132,5 +133,5 @@ class DiagLayerContainer(OdxCategory):
|
|
132
133
|
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
133
134
|
super()._resolve_snrefs(context)
|
134
135
|
|
135
|
-
def __getitem__(self, key:
|
136
|
+
def __getitem__(self, key: int | str) -> DiagLayer:
|
136
137
|
return self.diag_layers[key]
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
+
from collections.abc import Iterable
|
2
3
|
from copy import deepcopy
|
3
4
|
from dataclasses import dataclass
|
4
|
-
from typing import Any,
|
5
|
+
from typing import Any, cast
|
5
6
|
from xml.etree import ElementTree
|
6
7
|
|
7
8
|
from typing_extensions import override
|
@@ -11,7 +12,8 @@ from ..diagvariable import DiagVariable
|
|
11
12
|
from ..dyndefinedspec import DynDefinedSpec
|
12
13
|
from ..exceptions import odxassert
|
13
14
|
from ..nameditemlist import NamedItemList
|
14
|
-
from ..
|
15
|
+
from ..odxdoccontext import OdxDocContext
|
16
|
+
from ..odxlink import OdxLinkDatabase, OdxLinkRef
|
15
17
|
from ..parentref import ParentRef
|
16
18
|
from ..variablegroup import VariableGroup
|
17
19
|
from .basevariantraw import BaseVariantRaw
|
@@ -19,7 +21,7 @@ from .diaglayer import DiagLayer
|
|
19
21
|
from .hierarchyelement import HierarchyElement
|
20
22
|
|
21
23
|
|
22
|
-
@dataclass
|
24
|
+
@dataclass(kw_only=True)
|
23
25
|
class BaseVariant(HierarchyElement):
|
24
26
|
"""This is a diagnostic layer for common functionality of an ECU
|
25
27
|
"""
|
@@ -32,19 +34,19 @@ class BaseVariant(HierarchyElement):
|
|
32
34
|
# <properties forwarded to the "raw" base variant>
|
33
35
|
#####
|
34
36
|
@property
|
35
|
-
def diag_variables_raw(self) ->
|
37
|
+
def diag_variables_raw(self) -> list[DiagVariable | OdxLinkRef]:
|
36
38
|
return self.base_variant_raw.diag_variables_raw
|
37
39
|
|
38
40
|
@property
|
39
|
-
def dyn_defined_spec(self) ->
|
41
|
+
def dyn_defined_spec(self) -> DynDefinedSpec | None:
|
40
42
|
return self.base_variant_raw.dyn_defined_spec
|
41
43
|
|
42
44
|
@property
|
43
|
-
def base_variant_pattern(self) ->
|
45
|
+
def base_variant_pattern(self) -> BaseVariantPattern | None:
|
44
46
|
return self.base_variant_raw.base_variant_pattern
|
45
47
|
|
46
48
|
@property
|
47
|
-
def parent_refs(self) ->
|
49
|
+
def parent_refs(self) -> list[ParentRef]:
|
48
50
|
return self.base_variant_raw.parent_refs
|
49
51
|
|
50
52
|
#####
|
@@ -67,8 +69,8 @@ class BaseVariant(HierarchyElement):
|
|
67
69
|
#######
|
68
70
|
|
69
71
|
@staticmethod
|
70
|
-
def from_et(et_element: ElementTree.Element,
|
71
|
-
base_variant_raw = BaseVariantRaw.from_et(et_element,
|
72
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "BaseVariant":
|
73
|
+
base_variant_raw = BaseVariantRaw.from_et(et_element, context)
|
72
74
|
|
73
75
|
return BaseVariant(diag_layer_raw=base_variant_raw)
|
74
76
|
|
@@ -80,7 +82,7 @@ class BaseVariant(HierarchyElement):
|
|
80
82
|
"The raw diagnostic layer passed to BaseVariant "
|
81
83
|
"must be a BaseVariantRaw")
|
82
84
|
|
83
|
-
def __deepcopy__(self, memo:
|
85
|
+
def __deepcopy__(self, memo: dict[int, Any]) -> Any:
|
84
86
|
"""Create a deep copy of the base variant
|
85
87
|
|
86
88
|
Note that the copied diagnostic layer is not fully
|
@@ -113,7 +115,7 @@ class BaseVariant(HierarchyElement):
|
|
113
115
|
|
114
116
|
return dl.diag_layer_raw.diag_variables # type: ignore[no-any-return]
|
115
117
|
|
116
|
-
def not_inherited_fn(parent_ref: ParentRef) ->
|
118
|
+
def not_inherited_fn(parent_ref: ParentRef) -> list[str]:
|
117
119
|
return parent_ref.not_inherited_variables
|
118
120
|
|
119
121
|
return self._compute_available_objects(get_local_objects_fn, not_inherited_fn)
|
@@ -127,7 +129,7 @@ class BaseVariant(HierarchyElement):
|
|
127
129
|
|
128
130
|
return dl.diag_layer_raw.variable_groups # type: ignore[no-any-return]
|
129
131
|
|
130
|
-
def not_inherited_fn(parent_ref: ParentRef) ->
|
132
|
+
def not_inherited_fn(parent_ref: ParentRef) -> list[str]:
|
131
133
|
return []
|
132
134
|
|
133
135
|
return self._compute_available_objects(get_local_objects_fn, not_inherited_fn)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..basevariantpattern import BaseVariantPattern
|
@@ -8,7 +8,8 @@ from ..diagvariable import DiagVariable
|
|
8
8
|
from ..dyndefinedspec import DynDefinedSpec
|
9
9
|
from ..exceptions import odxraise
|
10
10
|
from ..nameditemlist import NamedItemList
|
11
|
-
from ..
|
11
|
+
from ..odxdoccontext import OdxDocContext
|
12
|
+
from ..odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
12
13
|
from ..parentref import ParentRef
|
13
14
|
from ..snrefcontext import SnRefContext
|
14
15
|
from ..utils import dataclass_fields_asdict
|
@@ -16,60 +17,58 @@ from ..variablegroup import VariableGroup
|
|
16
17
|
from .hierarchyelementraw import HierarchyElementRaw
|
17
18
|
|
18
19
|
|
19
|
-
@dataclass
|
20
|
+
@dataclass(kw_only=True)
|
20
21
|
class BaseVariantRaw(HierarchyElementRaw):
|
21
22
|
"""This is a diagnostic layer for common functionality of an ECU
|
22
23
|
"""
|
23
24
|
|
24
|
-
diag_variables_raw:
|
25
|
-
variable_groups: NamedItemList[VariableGroup]
|
26
|
-
dyn_defined_spec:
|
27
|
-
base_variant_pattern:
|
28
|
-
parent_refs:
|
25
|
+
diag_variables_raw: list[DiagVariable | OdxLinkRef] = field(default_factory=list)
|
26
|
+
variable_groups: NamedItemList[VariableGroup] = field(default_factory=NamedItemList)
|
27
|
+
dyn_defined_spec: DynDefinedSpec | None = None
|
28
|
+
base_variant_pattern: BaseVariantPattern | None = None
|
29
|
+
parent_refs: list[ParentRef] = field(default_factory=list)
|
29
30
|
|
30
31
|
@property
|
31
32
|
def diag_variables(self) -> NamedItemList[DiagVariable]:
|
32
33
|
return self._diag_variables
|
33
34
|
|
34
35
|
@staticmethod
|
35
|
-
def from_et(et_element: ElementTree.Element,
|
36
|
-
|
37
|
-
# objects contained by diagnostic layers exibit an additional
|
36
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "BaseVariantRaw":
|
37
|
+
# objects contained by diagnostic layers exhibit an additional
|
38
38
|
# document fragment for the diag layer, so we use the document
|
39
39
|
# fragments of the odx id of the diag layer for IDs of
|
40
40
|
# contained objects.
|
41
|
-
her = HierarchyElementRaw.from_et(et_element,
|
41
|
+
her = HierarchyElementRaw.from_et(et_element, context)
|
42
42
|
kwargs = dataclass_fields_asdict(her)
|
43
|
-
doc_frags = her.odx_id.doc_fragments
|
44
43
|
|
45
|
-
diag_variables_raw:
|
44
|
+
diag_variables_raw: list[DiagVariable | OdxLinkRef] = []
|
46
45
|
if (dv_elems := et_element.find("DIAG-VARIABLES")) is not None:
|
47
46
|
for dv_proxy_elem in dv_elems:
|
48
|
-
dv_proxy:
|
47
|
+
dv_proxy: OdxLinkRef | DiagVariable
|
49
48
|
if dv_proxy_elem.tag == "DIAG-VARIABLE-REF":
|
50
|
-
dv_proxy = OdxLinkRef.from_et(dv_proxy_elem,
|
49
|
+
dv_proxy = OdxLinkRef.from_et(dv_proxy_elem, context)
|
51
50
|
elif dv_proxy_elem.tag == "DIAG-VARIABLE":
|
52
|
-
dv_proxy = DiagVariable.from_et(dv_proxy_elem,
|
51
|
+
dv_proxy = DiagVariable.from_et(dv_proxy_elem, context)
|
53
52
|
else:
|
54
53
|
odxraise()
|
55
54
|
|
56
55
|
diag_variables_raw.append(dv_proxy)
|
57
56
|
|
58
57
|
variable_groups = NamedItemList([
|
59
|
-
VariableGroup.from_et(vg_elem,
|
58
|
+
VariableGroup.from_et(vg_elem, context)
|
60
59
|
for vg_elem in et_element.iterfind("VARIABLE-GROUPS/VARIABLE-GROUP")
|
61
60
|
])
|
62
61
|
|
63
62
|
dyn_defined_spec = None
|
64
63
|
if (dds_elem := et_element.find("DYN-DEFINED-SPEC")) is not None:
|
65
|
-
dyn_defined_spec = DynDefinedSpec.from_et(dds_elem,
|
64
|
+
dyn_defined_spec = DynDefinedSpec.from_et(dds_elem, context)
|
66
65
|
|
67
66
|
base_variant_pattern = None
|
68
67
|
if (bvp_elem := et_element.find("BASE-VARIANT-PATTERN")) is not None:
|
69
|
-
base_variant_pattern = BaseVariantPattern.from_et(bvp_elem,
|
68
|
+
base_variant_pattern = BaseVariantPattern.from_et(bvp_elem, context)
|
70
69
|
|
71
70
|
parent_refs = [
|
72
|
-
ParentRef.from_et(pr_elem,
|
71
|
+
ParentRef.from_et(pr_elem, context)
|
73
72
|
for pr_elem in et_element.iterfind("PARENT-REFS/PARENT-REF")
|
74
73
|
]
|
75
74
|
|
@@ -81,7 +80,7 @@ class BaseVariantRaw(HierarchyElementRaw):
|
|
81
80
|
parent_refs=parent_refs,
|
82
81
|
**kwargs)
|
83
82
|
|
84
|
-
def _build_odxlinks(self) ->
|
83
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
85
84
|
result = super()._build_odxlinks()
|
86
85
|
|
87
86
|
for dv_proxy in self.diag_variables_raw:
|
odxtools/diaglayers/diaglayer.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
+
from collections.abc import Callable, Iterable
|
2
3
|
from copy import copy, deepcopy
|
3
4
|
from dataclasses import dataclass
|
4
5
|
from functools import cached_property
|
5
6
|
from itertools import chain
|
6
|
-
from typing import Any,
|
7
|
+
from typing import Any, Union, cast
|
7
8
|
from xml.etree import ElementTree
|
8
9
|
|
9
10
|
from ..admindata import AdminData
|
@@ -16,7 +17,8 @@ from ..exceptions import DecodeError, odxassert, odxraise
|
|
16
17
|
from ..library import Library
|
17
18
|
from ..message import Message
|
18
19
|
from ..nameditemlist import NamedItemList, TNamed
|
19
|
-
from ..
|
20
|
+
from ..odxdoccontext import OdxDocContext
|
21
|
+
from ..odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
20
22
|
from ..parentref import ParentRef
|
21
23
|
from ..request import Request
|
22
24
|
from ..response import Response
|
@@ -29,10 +31,10 @@ from ..unitgroup import UnitGroup
|
|
29
31
|
from .diaglayerraw import DiagLayerRaw
|
30
32
|
from .diaglayertype import DiagLayerType
|
31
33
|
|
32
|
-
PrefixTree =
|
34
|
+
PrefixTree = dict[int, Union[list[DiagService], "PrefixTree"]]
|
33
35
|
|
34
36
|
|
35
|
-
@dataclass
|
37
|
+
@dataclass(kw_only=True)
|
36
38
|
class DiagLayer:
|
37
39
|
"""This class represents a "logical view" upon a diagnostic layer
|
38
40
|
according to the ODX standard.
|
@@ -44,8 +46,8 @@ class DiagLayer:
|
|
44
46
|
diag_layer_raw: DiagLayerRaw
|
45
47
|
|
46
48
|
@staticmethod
|
47
|
-
def from_et(et_element: ElementTree.Element,
|
48
|
-
diag_layer_raw = DiagLayerRaw.from_et(et_element,
|
49
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DiagLayer":
|
50
|
+
diag_layer_raw = DiagLayerRaw.from_et(et_element, context)
|
49
51
|
|
50
52
|
# Create DiagLayer
|
51
53
|
return DiagLayer(diag_layer_raw=diag_layer_raw)
|
@@ -72,7 +74,7 @@ class DiagLayer:
|
|
72
74
|
else:
|
73
75
|
self._diag_data_dictionary_spec = self.diag_layer_raw.diag_data_dictionary_spec
|
74
76
|
|
75
|
-
def _build_odxlinks(self) ->
|
77
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
76
78
|
"""Construct a mapping from IDs to all objects that are contained in this diagnostic layer."""
|
77
79
|
result = self.diag_layer_raw._build_odxlinks()
|
78
80
|
|
@@ -91,7 +93,7 @@ class DiagLayer:
|
|
91
93
|
# reference. This mechanism can thus be seen as a kind of
|
92
94
|
# "poor man's inheritance".
|
93
95
|
if self.import_refs:
|
94
|
-
imported_links:
|
96
|
+
imported_links: dict[OdxLinkId, Any] = {}
|
95
97
|
for import_ref in self.import_refs:
|
96
98
|
imported_dl = odxlinks.resolve(import_ref, DiagLayer)
|
97
99
|
|
@@ -168,7 +170,7 @@ class DiagLayer:
|
|
168
170
|
"""
|
169
171
|
return get_local_objects(self)
|
170
172
|
|
171
|
-
def __deepcopy__(self, memo:
|
173
|
+
def __deepcopy__(self, memo: dict[int, Any]) -> Any:
|
172
174
|
"""Create a deep copy of the diagnostic layer
|
173
175
|
|
174
176
|
Note that the copied diagnostic layer is not fully
|
@@ -210,15 +212,15 @@ class DiagLayer:
|
|
210
212
|
return self.diag_layer_raw.short_name
|
211
213
|
|
212
214
|
@property
|
213
|
-
def long_name(self) ->
|
215
|
+
def long_name(self) -> str | None:
|
214
216
|
return self.diag_layer_raw.long_name
|
215
217
|
|
216
218
|
@property
|
217
|
-
def description(self) ->
|
219
|
+
def description(self) -> Description | None:
|
218
220
|
return self.diag_layer_raw.description
|
219
221
|
|
220
222
|
@property
|
221
|
-
def admin_data(self) ->
|
223
|
+
def admin_data(self) -> AdminData | None:
|
222
224
|
return self.diag_layer_raw.admin_data
|
223
225
|
|
224
226
|
@property
|
@@ -258,7 +260,7 @@ class DiagLayer:
|
|
258
260
|
return self.diag_layer_raw.global_negative_responses
|
259
261
|
|
260
262
|
@property
|
261
|
-
def import_refs(self) ->
|
263
|
+
def import_refs(self) -> list[OdxLinkRef]:
|
262
264
|
return self.diag_layer_raw.import_refs
|
263
265
|
|
264
266
|
@property
|
@@ -270,7 +272,7 @@ class DiagLayer:
|
|
270
272
|
return self.diag_layer_raw.sub_components
|
271
273
|
|
272
274
|
@property
|
273
|
-
def sdgs(self) ->
|
275
|
+
def sdgs(self) -> list[SpecialDataGroup]:
|
274
276
|
return self.diag_layer_raw.sdgs
|
275
277
|
|
276
278
|
@property
|
@@ -359,13 +361,13 @@ class DiagLayer:
|
|
359
361
|
if sub_tree.get(-1) is None:
|
360
362
|
sub_tree[-1] = [service]
|
361
363
|
else:
|
362
|
-
cast(
|
364
|
+
cast(list[DiagService], sub_tree[-1]).append(service)
|
363
365
|
|
364
|
-
def _find_services_for_uds(self, message: bytes) ->
|
366
|
+
def _find_services_for_uds(self, message: bytes) -> list[DiagService]:
|
365
367
|
prefix_tree = self._prefix_tree
|
366
368
|
|
367
369
|
# Find matching service(s) in prefix tree
|
368
|
-
possible_services:
|
370
|
+
possible_services: list[DiagService] = []
|
369
371
|
for b in message:
|
370
372
|
if b in prefix_tree:
|
371
373
|
odxassert(isinstance(prefix_tree[b], dict))
|
@@ -373,11 +375,11 @@ class DiagLayer:
|
|
373
375
|
else:
|
374
376
|
break
|
375
377
|
if -1 in prefix_tree:
|
376
|
-
possible_services += cast(
|
378
|
+
possible_services += cast(list[DiagService], prefix_tree[-1])
|
377
379
|
return possible_services
|
378
380
|
|
379
|
-
def _decode(self, message: bytes, candidate_services: Iterable[DiagService]) ->
|
380
|
-
decoded_messages:
|
381
|
+
def _decode(self, message: bytes, candidate_services: Iterable[DiagService]) -> list[Message]:
|
382
|
+
decoded_messages: list[Message] = []
|
381
383
|
|
382
384
|
for service in candidate_services:
|
383
385
|
try:
|
@@ -415,12 +417,12 @@ class DiagLayer:
|
|
415
417
|
|
416
418
|
return decoded_messages
|
417
419
|
|
418
|
-
def decode(self, message: bytes) ->
|
420
|
+
def decode(self, message: bytes) -> list[Message]:
|
419
421
|
candidate_services = self._find_services_for_uds(message)
|
420
422
|
|
421
423
|
return self._decode(message, candidate_services)
|
422
424
|
|
423
|
-
def decode_response(self, response: bytes, request: bytes) ->
|
425
|
+
def decode_response(self, response: bytes, request: bytes) -> list[Message]:
|
424
426
|
candidate_services = self._find_services_for_uds(request)
|
425
427
|
if candidate_services is None:
|
426
428
|
raise DecodeError(f"Couldn't find corresponding service for request {request.hex()}.")
|