odxtools 10.1.0__py3-none-any.whl → 10.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/addrdeffilter.py +33 -0
- odxtools/addrdefphyssegment.py +33 -0
- odxtools/checksum.py +67 -0
- odxtools/checksumresult.py +7 -0
- odxtools/cli/compare.py +143 -170
- 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/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/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/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.0.dist-info → odxtools-10.2.0.dist-info}/METADATA +1 -1
- {odxtools-10.1.0.dist-info → odxtools-10.2.0.dist-info}/RECORD +107 -50
- {odxtools-10.1.0.dist-info → odxtools-10.2.0.dist-info}/WHEEL +1 -1
- {odxtools-10.1.0.dist-info → odxtools-10.2.0.dist-info}/entry_points.txt +0 -0
- {odxtools-10.1.0.dist-info → odxtools-10.2.0.dist-info}/licenses/LICENSE +0 -0
- {odxtools-10.1.0.dist-info → odxtools-10.2.0.dist-info}/top_level.txt +0 -0
odxtools/physmem.py
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .addrdefphyssegment import AddrdefPhysSegment
|
7
|
+
from .element import IdentifiableElement
|
8
|
+
from .globals import xsi
|
9
|
+
from .nameditemlist import NamedItemList
|
10
|
+
from .odxdoccontext import OdxDocContext
|
11
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
12
|
+
from .physsegment import PhysSegment
|
13
|
+
from .sizedefphyssegment import SizedefPhysSegment
|
14
|
+
from .snrefcontext import SnRefContext
|
15
|
+
from .utils import dataclass_fields_asdict
|
16
|
+
|
17
|
+
|
18
|
+
@dataclass(kw_only=True)
|
19
|
+
class PhysMem(IdentifiableElement):
|
20
|
+
phys_segments: NamedItemList[PhysSegment]
|
21
|
+
|
22
|
+
@staticmethod
|
23
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "PhysMem":
|
24
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
25
|
+
|
26
|
+
phys_segments: NamedItemList[PhysSegment] = NamedItemList()
|
27
|
+
for phys_segment_elem in et_element.iterfind("PHYS-SEGMENTS/PHYS-SEGMENT"):
|
28
|
+
phys_segment_type = phys_segment_elem.attrib.get(f"{xsi}type")
|
29
|
+
if phys_segment_type == "ADDRDEF-PHYS-SEGMENT":
|
30
|
+
phys_segments.append(AddrdefPhysSegment.from_et(phys_segment_elem, context))
|
31
|
+
elif phys_segment_type == "SIZEDEF-PHYS-SEGMENT":
|
32
|
+
phys_segments.append(SizedefPhysSegment.from_et(phys_segment_elem, context))
|
33
|
+
else:
|
34
|
+
phys_segments.append(PhysSegment.from_et(phys_segment_elem, context))
|
35
|
+
|
36
|
+
return PhysMem(phys_segments=phys_segments, **kwargs)
|
37
|
+
|
38
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
39
|
+
odxlinks = {self.odx_id: self}
|
40
|
+
|
41
|
+
for phys_segment in self.phys_segments:
|
42
|
+
odxlinks.update(phys_segment._build_odxlinks())
|
43
|
+
|
44
|
+
return odxlinks
|
45
|
+
|
46
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
47
|
+
for phys_segment in self.phys_segments:
|
48
|
+
phys_segment._resolve_odxlinks(odxlinks)
|
49
|
+
|
50
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
51
|
+
for phys_segment in self.phys_segments:
|
52
|
+
phys_segment._resolve_snrefs(context)
|
odxtools/physsegment.py
ADDED
@@ -0,0 +1,42 @@
|
|
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 .exceptions import odxrequire
|
8
|
+
from .odxdoccontext import OdxDocContext
|
9
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
10
|
+
from .snrefcontext import SnRefContext
|
11
|
+
from .utils import dataclass_fields_asdict, read_hex_binary
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass(kw_only=True)
|
15
|
+
class PhysSegment(IdentifiableElement):
|
16
|
+
fillbyte: int | None = None
|
17
|
+
block_size: int | None = None
|
18
|
+
start_address: int
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "PhysSegment":
|
22
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
23
|
+
|
24
|
+
fillbyte = read_hex_binary(et_element.find("FILLBYTE"))
|
25
|
+
block_size = 0
|
26
|
+
if (bs_elem := et_element.find("BLOCK-SIZE")) is not None:
|
27
|
+
block_size = int(odxrequire(bs_elem.text) or "0")
|
28
|
+
start_address = odxrequire(read_hex_binary(et_element.find("START-ADDRESS")))
|
29
|
+
|
30
|
+
return PhysSegment(
|
31
|
+
fillbyte=fillbyte, block_size=block_size, start_address=start_address, **kwargs)
|
32
|
+
|
33
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
34
|
+
odxlinks = {self.odx_id: self}
|
35
|
+
|
36
|
+
return odxlinks
|
37
|
+
|
38
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
39
|
+
pass
|
40
|
+
|
41
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
42
|
+
pass
|
odxtools/posoffset.py
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from xml.etree import ElementTree
|
4
|
+
|
5
|
+
from .exceptions import odxrequire
|
6
|
+
from .odxdoccontext import OdxDocContext
|
7
|
+
from .targetaddroffset import TargetAddrOffset
|
8
|
+
from .utils import dataclass_fields_asdict, read_hex_binary
|
9
|
+
|
10
|
+
|
11
|
+
@dataclass(kw_only=True)
|
12
|
+
class PosOffset(TargetAddrOffset):
|
13
|
+
positive_offset: int
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "PosOffset":
|
17
|
+
kwargs = dataclass_fields_asdict(TargetAddrOffset.from_et(et_element, context))
|
18
|
+
|
19
|
+
positive_offset = odxrequire(read_hex_binary(et_element.find("POSITIVE-OFFSET")))
|
20
|
+
|
21
|
+
return PosOffset(positive_offset=positive_offset, **kwargs)
|
odxtools/security.py
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from xml.etree import ElementTree
|
4
|
+
|
5
|
+
from .fwchecksum import FwChecksum
|
6
|
+
from .fwsignature import FwSignature
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .securitymethod import SecurityMethod
|
9
|
+
from .validityfor import ValidityFor
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass(kw_only=True)
|
13
|
+
class Security:
|
14
|
+
security_method: SecurityMethod | None = None
|
15
|
+
fw_signature: FwSignature | None = None
|
16
|
+
fw_checksum: FwChecksum | None = None
|
17
|
+
validity_for: ValidityFor | None = None
|
18
|
+
|
19
|
+
@staticmethod
|
20
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Security":
|
21
|
+
security_method = None
|
22
|
+
if (sm_elem := et_element.find("SECURITY-METHOD")) is not None:
|
23
|
+
security_method = SecurityMethod.from_et(sm_elem, context)
|
24
|
+
|
25
|
+
fw_signature = None
|
26
|
+
if (fws_elem := et_element.find("FW-SIGNATURE")) is not None:
|
27
|
+
fw_signature = FwSignature.from_et(fws_elem, context)
|
28
|
+
|
29
|
+
fw_checksum = None
|
30
|
+
if (fwcs_elem := et_element.find("FW-CHECKSUM")) is not None:
|
31
|
+
fw_checksum = FwChecksum.from_et(fwcs_elem, context)
|
32
|
+
|
33
|
+
validity_for = None
|
34
|
+
if (val_elem := et_element.find("VALIDITY-FOR")) is not None:
|
35
|
+
validity_for = ValidityFor.from_et(val_elem, context)
|
36
|
+
|
37
|
+
return Security(
|
38
|
+
security_method=security_method,
|
39
|
+
fw_signature=fw_signature,
|
40
|
+
fw_checksum=fw_checksum,
|
41
|
+
validity_for=validity_for,
|
42
|
+
)
|
@@ -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
|
+
SecurityMethod = ValidityFor
|
odxtools/segment.py
ADDED
@@ -0,0 +1,63 @@
|
|
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 .encryptcompressmethod import EncryptCompressMethod
|
8
|
+
from .exceptions import odxrequire
|
9
|
+
from .odxdoccontext import OdxDocContext
|
10
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
11
|
+
from .snrefcontext import SnRefContext
|
12
|
+
from .utils import dataclass_fields_asdict, read_hex_binary
|
13
|
+
|
14
|
+
|
15
|
+
@dataclass(kw_only=True)
|
16
|
+
class Segment(IdentifiableElement):
|
17
|
+
source_start_address: int
|
18
|
+
compressed_size: int | None = None
|
19
|
+
|
20
|
+
# exactly one of the two next fields must be not None
|
21
|
+
uncompressed_size: int | None = None
|
22
|
+
source_end_address: int | None = None
|
23
|
+
|
24
|
+
encrypt_compress_method: EncryptCompressMethod | None = None
|
25
|
+
|
26
|
+
@staticmethod
|
27
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Segment":
|
28
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
29
|
+
|
30
|
+
source_start_address = odxrequire(read_hex_binary(et_element.find("SOURCE-START-ADDRESS")))
|
31
|
+
compressed_size = None
|
32
|
+
if (cs_elem := et_element.find("COMPRESSED-SIZE")) is not None:
|
33
|
+
compressed_size = int(odxrequire(cs_elem.text) or "0")
|
34
|
+
|
35
|
+
# exactly one of the two next fields must be not None
|
36
|
+
uncompressed_size = None
|
37
|
+
if (ucs_elem := et_element.find("UNCOMPRESSED-SIZE")) is not None:
|
38
|
+
uncompressed_size = int(odxrequire(ucs_elem.text) or "0")
|
39
|
+
source_end_address = read_hex_binary(et_element.find("SOURCE-END-ADDRESS"))
|
40
|
+
|
41
|
+
encrypt_compress_method = None
|
42
|
+
if (encrypt_compress_method_elem := et_element.find("ENCRYPT-COMPRESS-METHOD")) is not None:
|
43
|
+
encrypt_compress_method = EncryptCompressMethod.from_et(encrypt_compress_method_elem,
|
44
|
+
context)
|
45
|
+
|
46
|
+
return Segment(
|
47
|
+
source_start_address=source_start_address,
|
48
|
+
compressed_size=compressed_size,
|
49
|
+
uncompressed_size=uncompressed_size,
|
50
|
+
source_end_address=source_end_address,
|
51
|
+
encrypt_compress_method=encrypt_compress_method,
|
52
|
+
**kwargs)
|
53
|
+
|
54
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
55
|
+
odxlinks = {self.odx_id: self}
|
56
|
+
|
57
|
+
return odxlinks
|
58
|
+
|
59
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
60
|
+
pass
|
61
|
+
|
62
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
63
|
+
pass
|
odxtools/session.py
ADDED
@@ -0,0 +1,88 @@
|
|
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 .checksum import Checksum
|
7
|
+
from .datablock import Datablock
|
8
|
+
from .element import IdentifiableElement
|
9
|
+
from .expectedident import ExpectedIdent
|
10
|
+
from .nameditemlist import NamedItemList
|
11
|
+
from .odxdoccontext import OdxDocContext
|
12
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
13
|
+
from .security import Security
|
14
|
+
from .snrefcontext import SnRefContext
|
15
|
+
from .specialdatagroup import SpecialDataGroup
|
16
|
+
from .utils import dataclass_fields_asdict
|
17
|
+
|
18
|
+
|
19
|
+
@dataclass(kw_only=True)
|
20
|
+
class Session(IdentifiableElement):
|
21
|
+
expected_idents: NamedItemList[ExpectedIdent] = field(default_factory=NamedItemList)
|
22
|
+
checksums: NamedItemList[Checksum] = field(default_factory=NamedItemList)
|
23
|
+
securities: list[Security] = field(default_factory=list)
|
24
|
+
datablock_refs: list[OdxLinkRef] = field(default_factory=list)
|
25
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
26
|
+
|
27
|
+
@property
|
28
|
+
def datablocks(self) -> NamedItemList[Datablock]:
|
29
|
+
return self._datablocks
|
30
|
+
|
31
|
+
@staticmethod
|
32
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Session":
|
33
|
+
|
34
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
35
|
+
|
36
|
+
expected_idents = NamedItemList([
|
37
|
+
ExpectedIdent.from_et(el, context)
|
38
|
+
for el in et_element.iterfind("EXPECTED-IDENTS/EXPECTED-IDENT")
|
39
|
+
])
|
40
|
+
checksums = NamedItemList(
|
41
|
+
[Checksum.from_et(el, context) for el in et_element.iterfind("CHECKSUMS/CHECKSUM")])
|
42
|
+
securities = [
|
43
|
+
Security.from_et(el, context) for el in et_element.iterfind("SECURITYS/SECURITY")
|
44
|
+
]
|
45
|
+
datablock_refs = [
|
46
|
+
OdxLinkRef.from_et(el, context)
|
47
|
+
for el in et_element.iterfind("DATABLOCK-REFS/DATABLOCK-REF")
|
48
|
+
]
|
49
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
50
|
+
|
51
|
+
return Session(
|
52
|
+
expected_idents=expected_idents,
|
53
|
+
checksums=checksums,
|
54
|
+
securities=securities,
|
55
|
+
datablock_refs=datablock_refs,
|
56
|
+
sdgs=sdgs,
|
57
|
+
**kwargs)
|
58
|
+
|
59
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
60
|
+
odxlinks = {self.odx_id: self}
|
61
|
+
|
62
|
+
for ei in self.expected_idents:
|
63
|
+
odxlinks.update(ei._build_odxlinks())
|
64
|
+
for cs in self.checksums:
|
65
|
+
odxlinks.update(cs._build_odxlinks())
|
66
|
+
for sdg in self.sdgs:
|
67
|
+
odxlinks.update(sdg._build_odxlinks())
|
68
|
+
|
69
|
+
return odxlinks
|
70
|
+
|
71
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
72
|
+
self._datablocks = NamedItemList(
|
73
|
+
[odxlinks.resolve(ref, Datablock) for ref in self.datablock_refs])
|
74
|
+
|
75
|
+
for ei in self.expected_idents:
|
76
|
+
ei._resolve_odxlinks(odxlinks)
|
77
|
+
for cs in self.checksums:
|
78
|
+
cs._resolve_odxlinks(odxlinks)
|
79
|
+
for sdg in self.sdgs:
|
80
|
+
sdg._resolve_odxlinks(odxlinks)
|
81
|
+
|
82
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
83
|
+
for ei in self.expected_idents:
|
84
|
+
ei._resolve_snrefs(context)
|
85
|
+
for cs in self.checksums:
|
86
|
+
cs._resolve_snrefs(context)
|
87
|
+
for sdg in self.sdgs:
|
88
|
+
sdg._resolve_snrefs(context)
|
odxtools/sessiondesc.py
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any, cast
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from .audience import Audience
|
7
|
+
from .direction import Direction
|
8
|
+
from .element import NamedElement
|
9
|
+
from .exceptions import odxraise, odxrequire
|
10
|
+
from .flashclass import FlashClass
|
11
|
+
from .nameditemlist import NamedItemList
|
12
|
+
from .odxdoccontext import OdxDocContext
|
13
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
14
|
+
from .ownident import OwnIdent
|
15
|
+
from .snrefcontext import SnRefContext
|
16
|
+
from .specialdatagroup import SpecialDataGroup
|
17
|
+
from .utils import dataclass_fields_asdict
|
18
|
+
|
19
|
+
|
20
|
+
@dataclass(kw_only=True)
|
21
|
+
class SessionDesc(NamedElement):
|
22
|
+
partnumber: str | None = None
|
23
|
+
priority: int | None = None
|
24
|
+
session_snref: str
|
25
|
+
diag_comm_snref: str | None = None
|
26
|
+
flash_class_refs: list[OdxLinkRef] = field(default_factory=list)
|
27
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
28
|
+
audience: Audience | None = None
|
29
|
+
own_ident: OwnIdent | None = None
|
30
|
+
oid: str | None = None
|
31
|
+
direction: Direction
|
32
|
+
|
33
|
+
@property
|
34
|
+
def flash_classes(self) -> NamedItemList[FlashClass]:
|
35
|
+
return self._flash_classes
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SessionDesc":
|
39
|
+
|
40
|
+
kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, context))
|
41
|
+
|
42
|
+
partnumber = et_element.findtext("PARTNUMBER")
|
43
|
+
priority = None
|
44
|
+
if (priority_str := et_element.findtext("PRIORITY")) is not None:
|
45
|
+
try:
|
46
|
+
priority = int(priority_str)
|
47
|
+
except Exception as e:
|
48
|
+
odxraise(f"Cannot parse PRIORITY: {e}")
|
49
|
+
session_snref = None
|
50
|
+
if (session_snref_elem := odxrequire(et_element.find("SESSION-SNREF"))) is not None:
|
51
|
+
session_snref = odxrequire(session_snref_elem.attrib.get("SHORT-NAME"))
|
52
|
+
diag_comm_snref = None
|
53
|
+
if (diag_comm_snref_elem := et_element.find("DIAG-COMM-SNREF")) is not None:
|
54
|
+
diag_comm_snref = odxrequire(diag_comm_snref_elem.attrib.get("SHORT-NAME"))
|
55
|
+
flash_class_refs = [
|
56
|
+
OdxLinkRef.from_et(el, context)
|
57
|
+
for el in et_element.iterfind("FLASH-CLASS-REFS/FLASH-CLASS-REF")
|
58
|
+
]
|
59
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
60
|
+
audience = None
|
61
|
+
if (audience_elem := et_element.find("AUDIENCE")) is not None:
|
62
|
+
audience = Audience.from_et(audience_elem, context)
|
63
|
+
own_ident = None
|
64
|
+
if (own_ident_elem := et_element.find("OWN-IDENT")) is not None:
|
65
|
+
own_ident = OwnIdent.from_et(own_ident_elem, context)
|
66
|
+
direction_str = odxrequire(et_element.attrib.get("DIRECTION"))
|
67
|
+
try:
|
68
|
+
direction = Direction(direction_str)
|
69
|
+
except ValueError:
|
70
|
+
odxraise(f"Encountered unknown DIRECTION '{direction_str}'")
|
71
|
+
direction = cast(Direction, None)
|
72
|
+
oid = et_element.attrib.get("OID")
|
73
|
+
|
74
|
+
return SessionDesc(
|
75
|
+
partnumber=partnumber,
|
76
|
+
priority=priority,
|
77
|
+
session_snref=session_snref,
|
78
|
+
diag_comm_snref=diag_comm_snref,
|
79
|
+
flash_class_refs=flash_class_refs,
|
80
|
+
sdgs=sdgs,
|
81
|
+
audience=audience,
|
82
|
+
own_ident=own_ident,
|
83
|
+
direction=direction,
|
84
|
+
oid=oid,
|
85
|
+
**kwargs)
|
86
|
+
|
87
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
88
|
+
odxlinks: dict[OdxLinkId, Any] = {}
|
89
|
+
|
90
|
+
if self.own_ident is not None:
|
91
|
+
odxlinks.update(self.own_ident._build_odxlinks())
|
92
|
+
|
93
|
+
return odxlinks
|
94
|
+
|
95
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
96
|
+
self._flash_classes = NamedItemList(
|
97
|
+
[odxlinks.resolve(ref, FlashClass) for ref in self.flash_class_refs])
|
98
|
+
|
99
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
100
|
+
# TODO: resolve session_snref and diag_comm_snref
|
101
|
+
pass
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from enum import Enum
|
3
|
+
|
4
|
+
from .odxtypes import DataType
|
5
|
+
|
6
|
+
|
7
|
+
class SessionSubElemType(Enum):
|
8
|
+
A_UINT32 = "A_UINT32"
|
9
|
+
A_BYTEFIELD = "A_BYTEFIELD"
|
10
|
+
A_ASCIISTRING = "A_ASCIISTRING"
|
11
|
+
|
12
|
+
@property
|
13
|
+
def data_type(self) -> DataType:
|
14
|
+
return DataType(self.value)
|
@@ -0,0 +1,33 @@
|
|
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 .filter import Filter
|
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 SizedefFilter(Filter):
|
16
|
+
filter_size: int
|
17
|
+
|
18
|
+
@staticmethod
|
19
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SizedefFilter":
|
20
|
+
kwargs = dataclass_fields_asdict(Filter.from_et(et_element, context))
|
21
|
+
|
22
|
+
filter_size = int(odxrequire(et_element.findtext("FILTER-SIZE")) or "0")
|
23
|
+
|
24
|
+
return SizedefFilter(filter_size=filter_size, **kwargs)
|
25
|
+
|
26
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
27
|
+
return super()._build_odxlinks()
|
28
|
+
|
29
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
30
|
+
super()._resolve_odxlinks(odxlinks)
|
31
|
+
|
32
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
33
|
+
super()._resolve_snrefs(context)
|
@@ -0,0 +1,33 @@
|
|
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 .physsegment import PhysSegment
|
10
|
+
from .snrefcontext import SnRefContext
|
11
|
+
from .utils import dataclass_fields_asdict
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass(kw_only=True)
|
15
|
+
class SizedefPhysSegment(PhysSegment):
|
16
|
+
size: int
|
17
|
+
|
18
|
+
@staticmethod
|
19
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SizedefPhysSegment":
|
20
|
+
kwargs = dataclass_fields_asdict(PhysSegment.from_et(et_element, context))
|
21
|
+
|
22
|
+
size = int(odxrequire(et_element.findtext("SIZE")) or "0")
|
23
|
+
|
24
|
+
return SizedefPhysSegment(size=size, **kwargs)
|
25
|
+
|
26
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
27
|
+
return super()._build_odxlinks()
|
28
|
+
|
29
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
30
|
+
super()._resolve_odxlinks(odxlinks)
|
31
|
+
|
32
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
33
|
+
super()._resolve_snrefs(context)
|
odxtools/specialdata.py
CHANGED
@@ -6,6 +6,7 @@ from xml.etree import ElementTree
|
|
6
6
|
from .odxdoccontext import OdxDocContext
|
7
7
|
from .odxlink import OdxLinkDatabase, OdxLinkId
|
8
8
|
from .snrefcontext import SnRefContext
|
9
|
+
from .utils import strip_indent
|
9
10
|
|
10
11
|
|
11
12
|
@dataclass(kw_only=True)
|
@@ -19,7 +20,7 @@ class SpecialData:
|
|
19
20
|
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SpecialData":
|
20
21
|
semantic_info = et_element.get("SI")
|
21
22
|
text_identifier = et_element.get("TI")
|
22
|
-
value = et_element.text or ""
|
23
|
+
value = strip_indent(et_element.text) or ""
|
23
24
|
|
24
25
|
return SpecialData(
|
25
26
|
semantic_info=semantic_info, text_identifier=text_identifier, value=value)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from xml.etree import ElementTree
|
4
|
+
|
5
|
+
from .odxdoccontext import OdxDocContext
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass(kw_only=True)
|
9
|
+
class TargetAddrOffset:
|
10
|
+
|
11
|
+
@staticmethod
|
12
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "TargetAddrOffset":
|
13
|
+
return TargetAddrOffset()
|
@@ -12,6 +12,7 @@
|
|
12
12
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
13
13
|
<!-- Written using odxtools {{odxtools_version}} -->
|
14
14
|
<ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
|
15
|
+
{{- set_category_docfrag(comparam_spec.short_name, "COMPARAM-SPEC") }}
|
15
16
|
<COMPARAM-SPEC {{- poc.printOdxCategoryAttribs(comparam_spec) }}>
|
16
17
|
{{- poc.printOdxCategorySubtags(comparam_spec)|indent(3) }}
|
17
18
|
{%- if comparam_spec.prot_stacks %}
|
@@ -15,6 +15,7 @@
|
|
15
15
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
16
16
|
<!-- Written using odxtools {{odxtools_version}} -->
|
17
17
|
<ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
|
18
|
+
{{- set_category_docfrag(comparam_subset.short_name, "COMPARAM-SUBSET") }}
|
18
19
|
<COMPARAM-SUBSET {{- poc.printOdxCategoryAttribs(comparam_subset) }} {{make_xml_attrib("CATEGORY", comparam_subset.category)}}>
|
19
20
|
{{- poc.printOdxCategorySubtags(comparam_subset)|indent(3) }}
|
20
21
|
{%- if comparam_subset.comparams %}
|
@@ -14,6 +14,7 @@
|
|
14
14
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
15
15
|
<!-- Written using odxtools {{odxtools_version}} -->
|
16
16
|
<ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
|
17
|
+
{{- set_category_docfrag(dlc.short_name, "CONTAINER") }}
|
17
18
|
<DIAG-LAYER-CONTAINER {{- poc.printOdxCategoryAttribs(dlc) }}>
|
18
19
|
{{- poc.printOdxCategorySubtags(dlc)|indent(3) }}
|
19
20
|
{%- if dlc.protocols %}
|
@@ -44,7 +45,7 @@
|
|
44
45
|
{%- endfor %}
|
45
46
|
</BASE-VARIANTS>
|
46
47
|
{%- endif %}
|
47
|
-
{%- if
|
48
|
+
{%- if dlc.ecu_variants %}
|
48
49
|
<ECU-VARIANTS>
|
49
50
|
{%- for dl in dlc.ecu_variants %}
|
50
51
|
{{pecuv.printEcuVariant(dl)|indent(3)}}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
{#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
#
|
5
|
+
# This template writes an .odx-cs file for a communication
|
6
|
+
# parameter subset.
|
7
|
+
-#}
|
8
|
+
{%- import('macros/printOdxCategory.xml.jinja2') as poc %}
|
9
|
+
{%- import('macros/printEcuMem.xml.jinja2') as pem %}
|
10
|
+
{%- import('macros/printEcuMemConnector.xml.jinja2') as pemc %}
|
11
|
+
{%- import('macros/printAudience.xml.jinja2') as paud %}
|
12
|
+
{#- -#}
|
13
|
+
|
14
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
15
|
+
<!-- Written using odxtools {{odxtools_version}} -->
|
16
|
+
<ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
|
17
|
+
{{- set_category_docfrag(flash.short_name, "FLASH") }}
|
18
|
+
<FLASH {{- poc.printOdxCategoryAttribs(flash) }}>
|
19
|
+
{{- poc.printOdxCategorySubtags(flash)|indent(4) }}
|
20
|
+
{%- if flash.ecu_mems %}
|
21
|
+
<ECU-MEMS>
|
22
|
+
{%- for ecu_mem in flash.ecu_mems %}
|
23
|
+
{{ pem.printEcuMem(ecu_mem) | indent(6) }}
|
24
|
+
{%- endfor %}
|
25
|
+
</ECU-MEMS>
|
26
|
+
{%- endif %}
|
27
|
+
{%- if flash.ecu_mem_connectors %}
|
28
|
+
<ECU-MEM-CONNECTORS>
|
29
|
+
{%- for ecu_mem_connector in flash.ecu_mem_connectors %}
|
30
|
+
{{ pemc.printEcuMemConnector(ecu_mem_connector) | indent(6) }}
|
31
|
+
{%- endfor %}
|
32
|
+
</ECU-MEM-CONNECTORS>
|
33
|
+
{%- endif %}
|
34
|
+
{%- if flash.additional_audiences %}
|
35
|
+
<ADDITIONAL-AUDIENCES>
|
36
|
+
{%- for audience in flash.additional_audiences %}
|
37
|
+
{{ paud.printAdditionalAudience(audience) | indent(6) }}
|
38
|
+
{%- endfor %}
|
39
|
+
</ADDITIONAL-AUDIENCES>
|
40
|
+
{%- endif %}
|
41
|
+
</FLASH>
|
42
|
+
</ODX>
|
@@ -14,9 +14,9 @@
|
|
14
14
|
<COMPANY-DOC-INFOS>
|
15
15
|
{%- for cdi in admin_data.company_doc_infos %}
|
16
16
|
<COMPANY-DOC-INFO>
|
17
|
-
<COMPANY-DATA-REF
|
17
|
+
<COMPANY-DATA-REF {{make_ref_attribs(cdi.company_data_ref)}} />
|
18
18
|
{%- if cdi.team_member_ref is not none %}
|
19
|
-
<TEAM-MEMBER-REF
|
19
|
+
<TEAM-MEMBER-REF {{make_ref_attribs(cdi.team_member_ref)}} />
|
20
20
|
{%- endif %}
|
21
21
|
{%- if cdi.doc_label is not none %}
|
22
22
|
<DOC-LABEL>{{cdi.doc_label|e}}</DOC-LABEL>
|
@@ -31,7 +31,7 @@
|
|
31
31
|
{%- for doc_revision in admin_data.doc_revisions %}
|
32
32
|
<DOC-REVISION>
|
33
33
|
{%- if doc_revision.team_member_ref is not none %}
|
34
|
-
<TEAM-MEMBER-REF
|
34
|
+
<TEAM-MEMBER-REF {{make_ref_attribs(doc_revision.team_member_ref)}} />
|
35
35
|
{%- endif %}
|
36
36
|
{%- if doc_revision.revision_label is not none %}
|
37
37
|
<REVISION-LABEL>{{doc_revision.revision_label|e}}</REVISION-LABEL>
|
@@ -47,7 +47,7 @@
|
|
47
47
|
<COMPANY-REVISION-INFOS>
|
48
48
|
{%- for cri in doc_revision.company_revision_infos %}
|
49
49
|
<COMPANY-REVISION-INFO>
|
50
|
-
<COMPANY-DATA-REF
|
50
|
+
<COMPANY-DATA-REF {{make_ref_attribs(cri.company_data_ref)}} />
|
51
51
|
{%- if cri.revision_label is not none %}
|
52
52
|
<REVISION-LABEL>{{cri.revision_label|e}}</REVISION-LABEL>
|
53
53
|
{%- endif %}
|
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
{%- macro printAdditionalAudience(audience) -%}
|
9
9
|
<ADDITIONAL-AUDIENCE {{-peid.printElementIdAttribs(audience)}}>
|
10
|
-
|
10
|
+
{{ peid.printElementIdSubtags(audience)|indent(2) }}
|
11
11
|
</ADDITIONAL-AUDIENCE>
|
12
12
|
{%- endmacro -%}
|
13
13
|
|
@@ -20,14 +20,14 @@
|
|
20
20
|
{%- if audience.enabled_audience_refs %}
|
21
21
|
<ENABLED-AUDIENCE-REFS>
|
22
22
|
{%- for ref in audience.enabled_audience_refs %}
|
23
|
-
<ENABLED-AUDIENCE-REF
|
23
|
+
<ENABLED-AUDIENCE-REF {{make_ref_attribs(ref)}} />
|
24
24
|
{%- endfor %}
|
25
25
|
</ENABLED-AUDIENCE-REFS>
|
26
26
|
{%- endif%}
|
27
27
|
{%- if audience.disabled_audience_refs %}
|
28
28
|
<DISABLED-AUDIENCE-REFS>
|
29
29
|
{%- for ref in audience.disabled_audience_refs %}
|
30
|
-
<DISABLED-AUDIENCE-REF
|
30
|
+
<DISABLED-AUDIENCE-REF {{make_ref_attribs(ref)}} />
|
31
31
|
{%- endfor %}
|
32
32
|
</DISABLED-AUDIENCE-REFS>
|
33
33
|
{%- endif%}
|