odxtools 10.1.1__py3-none-any.whl → 10.2.1__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/addrdeffilter.py +33 -0
- odxtools/addrdefphyssegment.py +33 -0
- odxtools/checksum.py +67 -0
- odxtools/checksumresult.py +7 -0
- odxtools/database.py +24 -4
- odxtools/datablock.py +153 -0
- odxtools/datafile.py +23 -0
- odxtools/dataformat.py +39 -0
- odxtools/dataformatselection.py +9 -0
- odxtools/description.py +2 -5
- odxtools/diagdatadictionaryspec.py +1 -3
- odxtools/diaglayers/diaglayer.py +31 -11
- odxtools/diaglayers/ecuvariant.py +12 -19
- odxtools/diaglayers/hierarchyelement.py +5 -5
- odxtools/diaglayers/protocol.py +14 -0
- odxtools/direction.py +7 -0
- odxtools/ecumem.py +71 -0
- odxtools/ecumemconnector.py +136 -0
- odxtools/encryptcompressmethod.py +39 -0
- odxtools/encryptcompressmethodtype.py +13 -0
- odxtools/expectedident.py +40 -0
- odxtools/externflashdata.py +34 -0
- odxtools/filter.py +32 -0
- odxtools/flash.py +88 -0
- odxtools/flashclass.py +32 -0
- odxtools/flashdata.py +70 -0
- odxtools/fwchecksum.py +7 -0
- odxtools/fwsignature.py +7 -0
- odxtools/identdesc.py +54 -0
- odxtools/identvalue.py +32 -0
- odxtools/identvaluetype.py +14 -0
- odxtools/internflashdata.py +33 -0
- odxtools/loadfile.py +1 -1
- odxtools/mem.py +80 -0
- odxtools/modification.py +3 -2
- odxtools/negoffset.py +21 -0
- odxtools/odxlink.py +4 -2
- odxtools/ownident.py +38 -0
- odxtools/physicaltype.py +12 -10
- odxtools/physmem.py +52 -0
- odxtools/physsegment.py +42 -0
- odxtools/posoffset.py +21 -0
- odxtools/security.py +42 -0
- odxtools/securitymethod.py +7 -0
- odxtools/segment.py +63 -0
- odxtools/session.py +88 -0
- odxtools/sessiondesc.py +101 -0
- odxtools/sessionsubelemtype.py +14 -0
- odxtools/sizedeffilter.py +33 -0
- odxtools/sizedefphyssegment.py +33 -0
- odxtools/specialdata.py +2 -1
- odxtools/subcomponentparamconnector.py +1 -1
- odxtools/targetaddroffset.py +13 -0
- odxtools/templates/comparam-spec.odx-c.xml.jinja2 +1 -0
- odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +1 -0
- odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +2 -1
- odxtools/templates/flash.odx-f.xml.jinja2 +42 -0
- odxtools/templates/macros/printAdminData.xml.jinja2 +4 -4
- odxtools/templates/macros/printAudience.xml.jinja2 +3 -3
- odxtools/templates/macros/printChecksum.xml.jinja2 +36 -0
- odxtools/templates/macros/printComparam.xml.jinja2 +1 -1
- odxtools/templates/macros/printComparamRef.xml.jinja2 +1 -3
- odxtools/templates/macros/printCompuMethod.xml.jinja2 +1 -1
- odxtools/templates/macros/printDOP.xml.jinja2 +3 -3
- odxtools/templates/macros/printDatablock.xml.jinja2 +78 -0
- odxtools/templates/macros/printDiagComm.xml.jinja2 +2 -2
- odxtools/templates/macros/printDiagLayer.xml.jinja2 +2 -1
- odxtools/templates/macros/printDiagVariable.xml.jinja2 +4 -4
- odxtools/templates/macros/printDynDefinedSpec.xml.jinja2 +3 -3
- odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +2 -2
- odxtools/templates/macros/printDynamicLengthField.xml.jinja2 +2 -2
- odxtools/templates/macros/printEcuMem.xml.jinja2 +24 -0
- odxtools/templates/macros/printEcuMemConnector.xml.jinja2 +58 -0
- odxtools/templates/macros/printEndOfPdu.xml.jinja2 +1 -1
- odxtools/templates/macros/printEnvDataDesc.xml.jinja2 +1 -1
- odxtools/templates/macros/printExpectedIdent.xml.jinja2 +21 -0
- odxtools/templates/macros/printFlashdata.xml.jinja2 +43 -0
- odxtools/templates/macros/printIdentDesc.xml.jinja2 +17 -0
- odxtools/templates/macros/printMem.xml.jinja2 +35 -0
- odxtools/templates/macros/printMux.xml.jinja2 +3 -3
- odxtools/templates/macros/printOdxCategory.xml.jinja2 +4 -4
- odxtools/templates/macros/printOwnIdent.xml.jinja2 +17 -0
- odxtools/templates/macros/printParam.xml.jinja2 +4 -4
- odxtools/templates/macros/printParentRef.xml.jinja2 +1 -5
- odxtools/templates/macros/printPhysMem.xml.jinja2 +20 -0
- odxtools/templates/macros/printPhysSegment.xml.jinja2 +33 -0
- odxtools/templates/macros/printPreConditionStateRef.xml.jinja2 +1 -1
- odxtools/templates/macros/printProtStack.xml.jinja2 +1 -1
- odxtools/templates/macros/printProtocol.xml.jinja2 +1 -1
- odxtools/templates/macros/printSecurity.xml.jinja2 +37 -0
- odxtools/templates/macros/printSegment.xml.jinja2 +31 -0
- odxtools/templates/macros/printService.xml.jinja2 +3 -3
- odxtools/templates/macros/printSession.xml.jinja2 +45 -0
- odxtools/templates/macros/printSessionDesc.xml.jinja2 +40 -0
- odxtools/templates/macros/printSingleEcuJob.xml.jinja2 +3 -3
- odxtools/templates/macros/printSpecialData.xml.jinja2 +2 -2
- odxtools/templates/macros/printStateTransitionRef.xml.jinja2 +1 -1
- odxtools/templates/macros/printStaticField.xml.jinja2 +1 -1
- odxtools/templates/macros/printSubComponent.xml.jinja2 +3 -3
- odxtools/templates/macros/printTable.xml.jinja2 +6 -6
- odxtools/templates/macros/printUnitSpec.xml.jinja2 +2 -2
- odxtools/text.py +2 -6
- odxtools/utils.py +22 -1
- odxtools/validityfor.py +30 -0
- odxtools/version.py +2 -2
- odxtools/writepdxfile.py +70 -21
- {odxtools-10.1.1.dist-info → odxtools-10.2.1.dist-info}/METADATA +1 -1
- {odxtools-10.1.1.dist-info → odxtools-10.2.1.dist-info}/RECORD +112 -55
- {odxtools-10.1.1.dist-info → odxtools-10.2.1.dist-info}/WHEEL +1 -1
- {odxtools-10.1.1.dist-info → odxtools-10.2.1.dist-info}/entry_points.txt +0 -0
- {odxtools-10.1.1.dist-info → odxtools-10.2.1.dist-info}/licenses/LICENSE +0 -0
- {odxtools-10.1.1.dist-info → odxtools-10.2.1.dist-info}/top_level.txt +0 -0
odxtools/diaglayers/protocol.py
CHANGED
@@ -7,6 +7,8 @@ from xml.etree import ElementTree
|
|
7
7
|
from ..comparamspec import ComparamSpec
|
8
8
|
from ..exceptions import odxassert
|
9
9
|
from ..odxdoccontext import OdxDocContext
|
10
|
+
from ..odxlink import OdxLinkRef
|
11
|
+
from ..parentref import ParentRef
|
10
12
|
from ..protstack import ProtStack
|
11
13
|
from .hierarchyelement import HierarchyElement
|
12
14
|
from .protocolraw import ProtocolRaw
|
@@ -24,14 +26,26 @@ class Protocol(HierarchyElement):
|
|
24
26
|
def protocol_raw(self) -> ProtocolRaw:
|
25
27
|
return cast(ProtocolRaw, self.diag_layer_raw)
|
26
28
|
|
29
|
+
@property
|
30
|
+
def comparam_spec_ref(self) -> OdxLinkRef:
|
31
|
+
return self.protocol_raw.comparam_spec_ref
|
32
|
+
|
27
33
|
@property
|
28
34
|
def comparam_spec(self) -> ComparamSpec:
|
29
35
|
return self.protocol_raw.comparam_spec
|
30
36
|
|
37
|
+
@property
|
38
|
+
def prot_stack_snref(self) -> str | None:
|
39
|
+
return self.protocol_raw.prot_stack_snref
|
40
|
+
|
31
41
|
@property
|
32
42
|
def prot_stack(self) -> ProtStack | None:
|
33
43
|
return self.protocol_raw.prot_stack
|
34
44
|
|
45
|
+
@property
|
46
|
+
def parent_refs(self) -> list[ParentRef]:
|
47
|
+
return self.protocol_raw.parent_refs
|
48
|
+
|
35
49
|
@staticmethod
|
36
50
|
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Protocol":
|
37
51
|
protocol_raw = ProtocolRaw.from_et(et_element, context)
|
odxtools/direction.py
ADDED
odxtools/ecumem.py
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .admindata import AdminData
|
7
|
+
from .element import IdentifiableElement
|
8
|
+
from .exceptions import odxrequire
|
9
|
+
from .mem import Mem
|
10
|
+
from .odxdoccontext import OdxDocContext
|
11
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
12
|
+
from .physmem import PhysMem
|
13
|
+
from .snrefcontext import SnRefContext
|
14
|
+
from .specialdatagroup import SpecialDataGroup
|
15
|
+
from .utils import dataclass_fields_asdict
|
16
|
+
|
17
|
+
|
18
|
+
@dataclass(kw_only=True)
|
19
|
+
class EcuMem(IdentifiableElement):
|
20
|
+
admin_data: AdminData | None = None
|
21
|
+
mem: Mem
|
22
|
+
phys_mem: PhysMem | None = None
|
23
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EcuMem":
|
27
|
+
|
28
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
29
|
+
|
30
|
+
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), context)
|
31
|
+
mem = Mem.from_et(odxrequire(et_element.find("MEM")), context)
|
32
|
+
phys_mem = None
|
33
|
+
if (phys_mem_elem := et_element.find("PHYS-MEM")) is not None:
|
34
|
+
phys_mem = PhysMem.from_et(phys_mem_elem, context)
|
35
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
36
|
+
|
37
|
+
return EcuMem(admin_data=admin_data, mem=mem, phys_mem=phys_mem, sdgs=sdgs, **kwargs)
|
38
|
+
|
39
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
40
|
+
odxlinks = {self.odx_id: self}
|
41
|
+
|
42
|
+
if self.admin_data is not None:
|
43
|
+
odxlinks.update(self.admin_data._build_odxlinks())
|
44
|
+
|
45
|
+
odxlinks.update(self.mem._build_odxlinks())
|
46
|
+
if self.phys_mem is not None:
|
47
|
+
odxlinks.update(self.phys_mem._build_odxlinks())
|
48
|
+
for sdg in self.sdgs:
|
49
|
+
odxlinks.update(sdg._build_odxlinks())
|
50
|
+
|
51
|
+
return odxlinks
|
52
|
+
|
53
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
54
|
+
if self.admin_data is not None:
|
55
|
+
self.admin_data._resolve_odxlinks(odxlinks)
|
56
|
+
|
57
|
+
self.mem._resolve_odxlinks(odxlinks)
|
58
|
+
if self.phys_mem is not None:
|
59
|
+
self.phys_mem._resolve_odxlinks(odxlinks)
|
60
|
+
for sdg in self.sdgs:
|
61
|
+
sdg._resolve_odxlinks(odxlinks)
|
62
|
+
|
63
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
64
|
+
if self.admin_data is not None:
|
65
|
+
self.admin_data._resolve_snrefs(context)
|
66
|
+
|
67
|
+
self.mem._resolve_snrefs(context)
|
68
|
+
if self.phys_mem is not None:
|
69
|
+
self.phys_mem._resolve_snrefs(context)
|
70
|
+
for sdg in self.sdgs:
|
71
|
+
sdg._resolve_snrefs(context)
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .admindata import AdminData
|
7
|
+
from .diaglayers.basevariant import BaseVariant
|
8
|
+
from .diaglayers.ecuvariant import EcuVariant
|
9
|
+
from .ecumem import EcuMem
|
10
|
+
from .element import IdentifiableElement
|
11
|
+
from .exceptions import odxraise, odxrequire
|
12
|
+
from .flashclass import FlashClass
|
13
|
+
from .identdesc import IdentDesc
|
14
|
+
from .nameditemlist import NamedItemList
|
15
|
+
from .odxdoccontext import OdxDocContext
|
16
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
17
|
+
from .sessiondesc import SessionDesc
|
18
|
+
from .snrefcontext import SnRefContext
|
19
|
+
from .specialdatagroup import SpecialDataGroup
|
20
|
+
from .utils import dataclass_fields_asdict
|
21
|
+
|
22
|
+
|
23
|
+
@dataclass(kw_only=True)
|
24
|
+
class EcuMemConnector(IdentifiableElement):
|
25
|
+
admin_data: AdminData | None = None
|
26
|
+
flash_classes: NamedItemList[FlashClass]
|
27
|
+
session_descs: NamedItemList[SessionDesc] = field(default_factory=NamedItemList)
|
28
|
+
ident_descs: list[IdentDesc] = field(default_factory=list)
|
29
|
+
ecu_mem_ref: OdxLinkRef
|
30
|
+
layer_refs: list[OdxLinkRef]
|
31
|
+
all_variant_refs: list[OdxLinkRef]
|
32
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
33
|
+
|
34
|
+
@property
|
35
|
+
def ecu_mem(self) -> EcuMem:
|
36
|
+
return self._ecu_mem
|
37
|
+
|
38
|
+
@property
|
39
|
+
def layers(self) -> NamedItemList[EcuVariant | BaseVariant]:
|
40
|
+
return self._layers
|
41
|
+
|
42
|
+
@property
|
43
|
+
def all_variants(self) -> NamedItemList[BaseVariant]:
|
44
|
+
return self._all_variants
|
45
|
+
|
46
|
+
@staticmethod
|
47
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EcuMemConnector":
|
48
|
+
|
49
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
50
|
+
|
51
|
+
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), context)
|
52
|
+
flash_classes = NamedItemList([
|
53
|
+
FlashClass.from_et(el, context)
|
54
|
+
for el in et_element.iterfind("FLASH-CLASSS/FLASH-CLASS")
|
55
|
+
])
|
56
|
+
session_descs = NamedItemList([
|
57
|
+
SessionDesc.from_et(el, context)
|
58
|
+
for el in et_element.iterfind("SESSION-DESCS/SESSION-DESC")
|
59
|
+
])
|
60
|
+
ident_descs = [
|
61
|
+
IdentDesc.from_et(el, context) for el in et_element.iterfind("IDENT-DESCS/IDENT-DESC")
|
62
|
+
]
|
63
|
+
ecu_mem_ref = OdxLinkRef.from_et(odxrequire(et_element.find("ECU-MEM-REF")), context)
|
64
|
+
layer_refs = [
|
65
|
+
OdxLinkRef.from_et(el, context) for el in et_element.iterfind("LAYER-REFS/LAYER-REF")
|
66
|
+
]
|
67
|
+
all_variant_refs = [
|
68
|
+
OdxLinkRef.from_et(el, context)
|
69
|
+
for el in et_element.iterfind("ALL-VARIANT-REFS/ALL-VARIANT-REF")
|
70
|
+
]
|
71
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
72
|
+
|
73
|
+
return EcuMemConnector(
|
74
|
+
admin_data=admin_data,
|
75
|
+
flash_classes=flash_classes,
|
76
|
+
session_descs=session_descs,
|
77
|
+
ident_descs=ident_descs,
|
78
|
+
ecu_mem_ref=ecu_mem_ref,
|
79
|
+
layer_refs=layer_refs,
|
80
|
+
all_variant_refs=all_variant_refs,
|
81
|
+
sdgs=sdgs,
|
82
|
+
**kwargs)
|
83
|
+
|
84
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
85
|
+
odxlinks = {self.odx_id: self}
|
86
|
+
|
87
|
+
if self.admin_data is not None:
|
88
|
+
odxlinks.update(self.admin_data._build_odxlinks())
|
89
|
+
for flash_class in self.flash_classes:
|
90
|
+
odxlinks.update(flash_class._build_odxlinks())
|
91
|
+
for session_desc in self.session_descs:
|
92
|
+
odxlinks.update(session_desc._build_odxlinks())
|
93
|
+
for ident_desc in self.ident_descs:
|
94
|
+
odxlinks.update(ident_desc._build_odxlinks())
|
95
|
+
for sdg in self.sdgs:
|
96
|
+
odxlinks.update(sdg._build_odxlinks())
|
97
|
+
|
98
|
+
return odxlinks
|
99
|
+
|
100
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
101
|
+
self._ecu_mem = odxlinks.resolve(self.ecu_mem_ref, EcuMem)
|
102
|
+
|
103
|
+
tmp = []
|
104
|
+
for ref in self.layer_refs:
|
105
|
+
x = odxlinks.resolve(ref)
|
106
|
+
if not isinstance(x, (BaseVariant, EcuVariant)):
|
107
|
+
odxraise("Invalid type of referenced object")
|
108
|
+
tmp.append(x)
|
109
|
+
self._layers = NamedItemList(tmp)
|
110
|
+
|
111
|
+
self._all_variants = NamedItemList(
|
112
|
+
[odxlinks.resolve(ref, BaseVariant) for ref in self.all_variant_refs])
|
113
|
+
self._ecu_mem = odxlinks.resolve(self.ecu_mem_ref, EcuMem)
|
114
|
+
|
115
|
+
if self.admin_data is not None:
|
116
|
+
self.admin_data._resolve_odxlinks(odxlinks)
|
117
|
+
for flash_class in self.flash_classes:
|
118
|
+
flash_class._resolve_odxlinks(odxlinks)
|
119
|
+
for session_desc in self.session_descs:
|
120
|
+
session_desc._resolve_odxlinks(odxlinks)
|
121
|
+
for ident_desc in self.ident_descs:
|
122
|
+
ident_desc._resolve_odxlinks(odxlinks)
|
123
|
+
for sdg in self.sdgs:
|
124
|
+
sdg._resolve_odxlinks(odxlinks)
|
125
|
+
|
126
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
127
|
+
if self.admin_data is not None:
|
128
|
+
self.admin_data._resolve_snrefs(context)
|
129
|
+
for flash_class in self.flash_classes:
|
130
|
+
flash_class._resolve_snrefs(context)
|
131
|
+
for session_desc in self.session_descs:
|
132
|
+
session_desc._resolve_snrefs(context)
|
133
|
+
for ident_desc in self.ident_descs:
|
134
|
+
ident_desc._resolve_snrefs(context)
|
135
|
+
for sdg in self.sdgs:
|
136
|
+
sdg._resolve_snrefs(context)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import Any, cast
|
3
|
+
from xml.etree import ElementTree
|
4
|
+
|
5
|
+
from .encryptcompressmethodtype import EncryptCompressMethodType
|
6
|
+
from .exceptions import odxraise, odxrequire
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
9
|
+
from .snrefcontext import SnRefContext
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass(kw_only=True)
|
13
|
+
class EncryptCompressMethod:
|
14
|
+
value: str
|
15
|
+
value_type: EncryptCompressMethodType
|
16
|
+
|
17
|
+
@staticmethod
|
18
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "EncryptCompressMethod":
|
19
|
+
value = et_element.text or ""
|
20
|
+
|
21
|
+
value_type_str = odxrequire(et_element.attrib.get("TYPE"))
|
22
|
+
try:
|
23
|
+
value_type = EncryptCompressMethodType(value_type_str)
|
24
|
+
except ValueError:
|
25
|
+
value_type = cast(EncryptCompressMethodType, None)
|
26
|
+
odxraise(f"Encountered unknown addressing type '{value_type_str}'")
|
27
|
+
|
28
|
+
return EncryptCompressMethod(value=value, value_type=value_type)
|
29
|
+
|
30
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
31
|
+
odxlinks: dict[OdxLinkId, Any] = {}
|
32
|
+
|
33
|
+
return odxlinks
|
34
|
+
|
35
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
36
|
+
pass
|
37
|
+
|
38
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
39
|
+
pass
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from enum import Enum
|
3
|
+
|
4
|
+
from .odxtypes import DataType
|
5
|
+
|
6
|
+
|
7
|
+
class EncryptCompressMethodType(Enum):
|
8
|
+
A_UINT32 = "A_UINT32"
|
9
|
+
A_BYTEFIELD = "A_BYTEFIELD"
|
10
|
+
|
11
|
+
@property
|
12
|
+
def data_type(self) -> DataType:
|
13
|
+
return DataType(self.value)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .element import IdentifiableElement
|
7
|
+
from .identvalue import IdentValue
|
8
|
+
from .odxdoccontext import OdxDocContext
|
9
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
10
|
+
from .snrefcontext import SnRefContext
|
11
|
+
from .utils import dataclass_fields_asdict
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass(kw_only=True)
|
15
|
+
class ExpectedIdent(IdentifiableElement):
|
16
|
+
"""
|
17
|
+
Corresponds to EXPECTED-IDENT.
|
18
|
+
"""
|
19
|
+
|
20
|
+
ident_values: list[IdentValue]
|
21
|
+
|
22
|
+
@staticmethod
|
23
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "ExpectedIdent":
|
24
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
25
|
+
|
26
|
+
ident_values = [
|
27
|
+
IdentValue.from_et(ive, context)
|
28
|
+
for ive in et_element.iterfind("IDENT-VALUES/IDENT-VALUE")
|
29
|
+
]
|
30
|
+
|
31
|
+
return ExpectedIdent(ident_values=ident_values, **kwargs)
|
32
|
+
|
33
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
34
|
+
return {self.odx_id: self}
|
35
|
+
|
36
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
37
|
+
pass
|
38
|
+
|
39
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
40
|
+
pass
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .datafile import Datafile
|
7
|
+
from .exceptions import odxrequire
|
8
|
+
from .flashdata import Flashdata
|
9
|
+
from .odxdoccontext import OdxDocContext
|
10
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
11
|
+
from .snrefcontext import SnRefContext
|
12
|
+
from .utils import dataclass_fields_asdict
|
13
|
+
|
14
|
+
|
15
|
+
@dataclass(kw_only=True)
|
16
|
+
class ExternFlashdata(Flashdata):
|
17
|
+
datafile: Datafile
|
18
|
+
|
19
|
+
@staticmethod
|
20
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "ExternFlashdata":
|
21
|
+
kwargs = dataclass_fields_asdict(Flashdata.from_et(et_element, context))
|
22
|
+
|
23
|
+
datafile = Datafile.from_et(odxrequire(et_element.find("DATAFILE")), context)
|
24
|
+
|
25
|
+
return ExternFlashdata(datafile=datafile, **kwargs)
|
26
|
+
|
27
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
28
|
+
return super()._build_odxlinks()
|
29
|
+
|
30
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
31
|
+
super()._resolve_odxlinks(odxlinks)
|
32
|
+
|
33
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
34
|
+
super()._resolve_snrefs(context)
|
odxtools/filter.py
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .exceptions import odxrequire
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
9
|
+
from .snrefcontext import SnRefContext
|
10
|
+
from .utils import read_hex_binary
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass(kw_only=True)
|
14
|
+
class Filter:
|
15
|
+
filter_start: int
|
16
|
+
|
17
|
+
@staticmethod
|
18
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Filter":
|
19
|
+
filter_start = odxrequire(read_hex_binary(et_element.find("FILTER-START")))
|
20
|
+
|
21
|
+
return Filter(filter_start=filter_start)
|
22
|
+
|
23
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
24
|
+
odxlinks: dict[OdxLinkId, Any] = {}
|
25
|
+
|
26
|
+
return odxlinks
|
27
|
+
|
28
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
29
|
+
pass
|
30
|
+
|
31
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
32
|
+
pass
|
odxtools/flash.py
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import TYPE_CHECKING, Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .additionalaudience import AdditionalAudience
|
7
|
+
from .ecumem import EcuMem
|
8
|
+
from .ecumemconnector import EcuMemConnector
|
9
|
+
from .nameditemlist import NamedItemList
|
10
|
+
from .odxcategory import OdxCategory
|
11
|
+
from .odxdoccontext import OdxDocContext
|
12
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
13
|
+
from .snrefcontext import SnRefContext
|
14
|
+
from .utils import dataclass_fields_asdict
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from .database import Database
|
18
|
+
|
19
|
+
|
20
|
+
@dataclass(kw_only=True)
|
21
|
+
class Flash(OdxCategory):
|
22
|
+
ecu_mems: NamedItemList[EcuMem] = field(default_factory=NamedItemList)
|
23
|
+
ecu_mem_connectors: NamedItemList[EcuMemConnector] = field(default_factory=NamedItemList)
|
24
|
+
additional_audiences: NamedItemList[AdditionalAudience] = field(default_factory=NamedItemList)
|
25
|
+
|
26
|
+
@staticmethod
|
27
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Flash":
|
28
|
+
|
29
|
+
base_obj = OdxCategory.from_et(et_element, context)
|
30
|
+
kwargs = dataclass_fields_asdict(base_obj)
|
31
|
+
|
32
|
+
ecu_mems = NamedItemList(
|
33
|
+
[EcuMem.from_et(el, context) for el in et_element.iterfind("ECU-MEMS/ECU-MEM")])
|
34
|
+
ecu_mem_connectors = NamedItemList([
|
35
|
+
EcuMemConnector.from_et(el, context)
|
36
|
+
for el in et_element.iterfind("ECU-MEM-CONNECTORS/ECU-MEM-CONNECTOR")
|
37
|
+
])
|
38
|
+
additional_audiences = NamedItemList([
|
39
|
+
AdditionalAudience.from_et(el, context)
|
40
|
+
for el in et_element.iterfind("ADDITIONAL-AUDIENCES/ADDITIONAL-AUDIENCE")
|
41
|
+
])
|
42
|
+
|
43
|
+
return Flash(
|
44
|
+
ecu_mems=ecu_mems,
|
45
|
+
ecu_mem_connectors=ecu_mem_connectors,
|
46
|
+
additional_audiences=additional_audiences,
|
47
|
+
**kwargs)
|
48
|
+
|
49
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
50
|
+
odxlinks = super()._build_odxlinks()
|
51
|
+
|
52
|
+
for ecu_mem in self.ecu_mems:
|
53
|
+
odxlinks.update(ecu_mem._build_odxlinks())
|
54
|
+
|
55
|
+
for ecu_mem_connector in self.ecu_mem_connectors:
|
56
|
+
odxlinks.update(ecu_mem_connector._build_odxlinks())
|
57
|
+
|
58
|
+
for additional_audiences in self.additional_audiences:
|
59
|
+
odxlinks.update(additional_audiences._build_odxlinks())
|
60
|
+
|
61
|
+
return odxlinks
|
62
|
+
|
63
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
64
|
+
super()._resolve_odxlinks(odxlinks)
|
65
|
+
|
66
|
+
for ecu_mem in self.ecu_mems:
|
67
|
+
ecu_mem._resolve_odxlinks(odxlinks)
|
68
|
+
|
69
|
+
for ecu_mem_connector in self.ecu_mem_connectors:
|
70
|
+
ecu_mem_connector._resolve_odxlinks(odxlinks)
|
71
|
+
|
72
|
+
for additional_audiences in self.additional_audiences:
|
73
|
+
additional_audiences._resolve_odxlinks(odxlinks)
|
74
|
+
|
75
|
+
def _finalize_init(self, database: "Database", odxlinks: OdxLinkDatabase) -> None:
|
76
|
+
super()._finalize_init(database, odxlinks)
|
77
|
+
|
78
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
79
|
+
super()._resolve_snrefs(context)
|
80
|
+
|
81
|
+
for ecu_mem in self.ecu_mems:
|
82
|
+
ecu_mem._resolve_snrefs(context)
|
83
|
+
|
84
|
+
for ecu_mem_connector in self.ecu_mem_connectors:
|
85
|
+
ecu_mem_connector._resolve_snrefs(context)
|
86
|
+
|
87
|
+
for additional_audiences in self.additional_audiences:
|
88
|
+
additional_audiences._resolve_snrefs(context)
|
odxtools/flashclass.py
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .element import IdentifiableElement
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
9
|
+
from .snrefcontext import SnRefContext
|
10
|
+
from .utils import dataclass_fields_asdict
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass(kw_only=True)
|
14
|
+
class FlashClass(IdentifiableElement):
|
15
|
+
"""
|
16
|
+
Corresponds to FLASH-CLASS.
|
17
|
+
"""
|
18
|
+
|
19
|
+
@staticmethod
|
20
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "FlashClass":
|
21
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
22
|
+
|
23
|
+
return FlashClass(**kwargs)
|
24
|
+
|
25
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
26
|
+
return {self.odx_id: self}
|
27
|
+
|
28
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
29
|
+
pass
|
30
|
+
|
31
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
32
|
+
pass
|
odxtools/flashdata.py
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .dataformat import Dataformat
|
7
|
+
from .element import IdentifiableElement
|
8
|
+
from .encryptcompressmethod import EncryptCompressMethod
|
9
|
+
from .exceptions import odxrequire
|
10
|
+
from .odxdoccontext import OdxDocContext
|
11
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
12
|
+
from .snrefcontext import SnRefContext
|
13
|
+
from .utils import dataclass_fields_asdict
|
14
|
+
|
15
|
+
|
16
|
+
@dataclass(kw_only=True)
|
17
|
+
class Flashdata(IdentifiableElement):
|
18
|
+
size_length: int | None = None
|
19
|
+
address_length: int | None = None
|
20
|
+
dataformat: Dataformat
|
21
|
+
encrypt_compress_method: EncryptCompressMethod | None = None
|
22
|
+
|
23
|
+
@staticmethod
|
24
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Flashdata":
|
25
|
+
|
26
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
27
|
+
|
28
|
+
size_length = None
|
29
|
+
if (size_length_str := et_element.findtext("SIZE-LENGTH")) is not None:
|
30
|
+
size_length = int(size_length_str)
|
31
|
+
|
32
|
+
address_length = None
|
33
|
+
if (address_length_str := et_element.findtext("ADDRESS-LENGTH")) is not None:
|
34
|
+
address_length = int(address_length_str)
|
35
|
+
|
36
|
+
dataformat = Dataformat.from_et(odxrequire(et_element.find("DATAFORMAT")), context)
|
37
|
+
|
38
|
+
encrypt_compress_method = None
|
39
|
+
if (encrypt_compress_method_elem := et_element.find("ENCRYPT-COMPRESS-METHOD")) is not None:
|
40
|
+
encrypt_compress_method = EncryptCompressMethod.from_et(encrypt_compress_method_elem,
|
41
|
+
context)
|
42
|
+
|
43
|
+
return Flashdata(
|
44
|
+
size_length=size_length,
|
45
|
+
address_length=address_length,
|
46
|
+
dataformat=dataformat,
|
47
|
+
encrypt_compress_method=encrypt_compress_method,
|
48
|
+
**kwargs)
|
49
|
+
|
50
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
51
|
+
odxlinks = {self.odx_id: self}
|
52
|
+
|
53
|
+
if self.dataformat is not None:
|
54
|
+
odxlinks.update(self.dataformat._build_odxlinks())
|
55
|
+
if self.encrypt_compress_method is not None:
|
56
|
+
odxlinks.update(self.encrypt_compress_method._build_odxlinks())
|
57
|
+
|
58
|
+
return odxlinks
|
59
|
+
|
60
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
61
|
+
if self.dataformat is not None:
|
62
|
+
self.dataformat._resolve_odxlinks(odxlinks)
|
63
|
+
if self.encrypt_compress_method is not None:
|
64
|
+
self.encrypt_compress_method._resolve_odxlinks(odxlinks)
|
65
|
+
|
66
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
67
|
+
if self.dataformat is not None:
|
68
|
+
self.dataformat._resolve_snrefs(context)
|
69
|
+
if self.encrypt_compress_method is not None:
|
70
|
+
self.encrypt_compress_method._resolve_snrefs(context)
|
odxtools/fwchecksum.py
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from .validityfor import ValidityFor
|
3
|
+
|
4
|
+
# Note that the ODX specification specifies a separate tag for this,
|
5
|
+
# but this tag is identical to VALIDITY-FOR, so let's use a type alias
|
6
|
+
# to reduce the amount of copy-and-pasted code
|
7
|
+
FwChecksum = ValidityFor
|
odxtools/fwsignature.py
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from .validityfor import ValidityFor
|
3
|
+
|
4
|
+
# Note that the ODX specification specifies a separate tag for this,
|
5
|
+
# but this tag is identical to VALIDITY-FOR, so let's use a type alias
|
6
|
+
# to reduce the amount of copy-and-pasted code
|
7
|
+
FwSignature = ValidityFor
|
odxtools/identdesc.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .exceptions import odxrequire
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
9
|
+
from .snrefcontext import SnRefContext
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass(kw_only=True)
|
13
|
+
class IdentDesc:
|
14
|
+
diag_comm_snref: str
|
15
|
+
ident_if_snref: str
|
16
|
+
|
17
|
+
# exactly one of the two attributes below must be defined
|
18
|
+
out_param_if_snref: str | None = None
|
19
|
+
out_param_if_snpathref: str | None = None
|
20
|
+
|
21
|
+
@staticmethod
|
22
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "IdentDesc":
|
23
|
+
diag_comm_snref = odxrequire(
|
24
|
+
odxrequire(et_element.find("DIAG-COMM-SNREF")).attrib.get("SHORT-NAME"))
|
25
|
+
ident_if_snref = odxrequire(
|
26
|
+
odxrequire(et_element.find("IDENT-IF-SNREF")).attrib.get("SHORT-NAME"))
|
27
|
+
out_param_if_snref = None
|
28
|
+
if (out_param_if_snref_elem := et_element.find("OUT-PARAM-IF-SNREF")) is not None:
|
29
|
+
out_param_if_snref = odxrequire(out_param_if_snref_elem.attrib.get("SHORT-NAME"))
|
30
|
+
|
31
|
+
out_param_if_snpathref = None
|
32
|
+
if (out_param_if_snpathref_elem := et_element.find("OUT-PARAM-IF-SNPATHREF")) is not None:
|
33
|
+
out_param_if_snpathref = odxrequire(
|
34
|
+
out_param_if_snpathref_elem.attrib.get("SHORT-NAME-PATH"))
|
35
|
+
|
36
|
+
return IdentDesc(
|
37
|
+
diag_comm_snref=diag_comm_snref,
|
38
|
+
ident_if_snref=ident_if_snref,
|
39
|
+
out_param_if_snref=out_param_if_snref,
|
40
|
+
out_param_if_snpathref=out_param_if_snpathref,
|
41
|
+
)
|
42
|
+
|
43
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
44
|
+
odxlinks: dict[OdxLinkId, Any] = {}
|
45
|
+
|
46
|
+
return odxlinks
|
47
|
+
|
48
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
49
|
+
pass
|
50
|
+
|
51
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
52
|
+
# TODO: resolve the short name references. for IdentDesc this
|
53
|
+
# is (probably) not possible ahead of time...
|
54
|
+
pass
|