odxtools 7.1.1__py3-none-any.whl → 7.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odxtools/__init__.py +6 -4
- odxtools/additionalaudience.py +3 -5
- odxtools/admindata.py +5 -7
- odxtools/audience.py +3 -5
- odxtools/basecomparam.py +3 -5
- odxtools/basicstructure.py +19 -23
- odxtools/cli/_parser_utils.py +1 -1
- odxtools/cli/_print_utils.py +3 -2
- odxtools/cli/compare.py +1 -1
- odxtools/companydata.py +5 -7
- odxtools/companydocinfo.py +7 -8
- odxtools/companyrevisioninfo.py +3 -5
- odxtools/companyspecificinfo.py +8 -9
- odxtools/comparam.py +4 -6
- odxtools/comparaminstance.py +6 -8
- odxtools/comparamspec.py +14 -13
- odxtools/comparamsubset.py +17 -16
- odxtools/complexcomparam.py +5 -7
- odxtools/compumethods/compuconst.py +31 -0
- odxtools/compumethods/compudefaultvalue.py +27 -0
- odxtools/compumethods/compuinternaltophys.py +39 -0
- odxtools/compumethods/compuinversevalue.py +7 -0
- odxtools/compumethods/compumethod.py +67 -12
- odxtools/compumethods/compuphystointernal.py +39 -0
- odxtools/compumethods/compuscale.py +15 -26
- odxtools/compumethods/createanycompumethod.py +14 -160
- odxtools/compumethods/identicalcompumethod.py +31 -6
- odxtools/compumethods/linearcompumethod.py +69 -189
- odxtools/compumethods/linearsegment.py +191 -0
- odxtools/compumethods/scalelinearcompumethod.py +132 -26
- odxtools/compumethods/tabintpcompumethod.py +119 -99
- odxtools/compumethods/texttablecompumethod.py +107 -43
- odxtools/createanydiagcodedtype.py +10 -67
- odxtools/database.py +84 -72
- odxtools/dataobjectproperty.py +10 -19
- odxtools/decodestate.py +8 -2
- odxtools/description.py +47 -0
- odxtools/determinenumberofitems.py +4 -5
- odxtools/diagcodedtype.py +29 -12
- odxtools/diagcomm.py +10 -6
- odxtools/diagdatadictionaryspec.py +20 -21
- odxtools/diaglayer.py +39 -9
- odxtools/diaglayercontainer.py +17 -11
- odxtools/diaglayerraw.py +20 -21
- odxtools/diagnostictroublecode.py +8 -9
- odxtools/diagservice.py +42 -27
- odxtools/docrevision.py +5 -7
- odxtools/dopbase.py +7 -8
- odxtools/dtcdop.py +44 -22
- odxtools/dynamicendmarkerfield.py +22 -9
- odxtools/dynamiclengthfield.py +5 -11
- odxtools/element.py +4 -3
- odxtools/encodestate.py +14 -2
- odxtools/endofpdufield.py +0 -2
- odxtools/environmentdatadescription.py +137 -19
- odxtools/exceptions.py +11 -2
- odxtools/field.py +9 -9
- odxtools/functionalclass.py +3 -5
- odxtools/inputparam.py +3 -5
- odxtools/leadinglengthinfotype.py +15 -2
- odxtools/loadfile.py +64 -0
- odxtools/minmaxlengthtype.py +20 -2
- odxtools/modification.py +3 -5
- odxtools/multiplexer.py +98 -69
- odxtools/multiplexercase.py +10 -11
- odxtools/multiplexerdefaultcase.py +11 -12
- odxtools/multiplexerswitchkey.py +4 -5
- odxtools/negoutputparam.py +3 -5
- odxtools/odxlink.py +12 -26
- odxtools/odxtypes.py +1 -1
- odxtools/outputparam.py +3 -5
- odxtools/parameterinfo.py +5 -5
- odxtools/parameters/codedconstparameter.py +2 -14
- odxtools/parameters/lengthkeyparameter.py +3 -17
- odxtools/parameters/nrcconstparameter.py +29 -50
- odxtools/parameters/parameter.py +22 -22
- odxtools/parameters/parameterwithdop.py +6 -8
- odxtools/parameters/physicalconstantparameter.py +5 -8
- odxtools/parameters/reservedparameter.py +4 -3
- odxtools/parameters/systemparameter.py +1 -1
- odxtools/parameters/tablekeyparameter.py +6 -9
- odxtools/parameters/tablestructparameter.py +6 -8
- odxtools/parameters/valueparameter.py +5 -8
- odxtools/paramlengthinfotype.py +19 -6
- odxtools/parentref.py +15 -1
- odxtools/physicaldimension.py +3 -5
- odxtools/progcode.py +18 -7
- odxtools/protstack.py +3 -5
- odxtools/relateddoc.py +7 -9
- odxtools/request.py +8 -0
- odxtools/response.py +8 -0
- odxtools/scaleconstr.py +3 -3
- odxtools/singleecujob.py +12 -10
- odxtools/snrefcontext.py +29 -0
- odxtools/specialdata.py +3 -5
- odxtools/specialdatagroup.py +5 -7
- odxtools/specialdatagroupcaption.py +3 -6
- odxtools/standardlengthtype.py +27 -2
- odxtools/state.py +3 -5
- odxtools/statechart.py +9 -11
- odxtools/statetransition.py +4 -9
- odxtools/staticfield.py +4 -8
- odxtools/table.py +7 -8
- odxtools/tablerow.py +7 -6
- odxtools/teammember.py +3 -5
- odxtools/templates/comparam-spec.odx-c.xml.jinja2 +2 -5
- odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +2 -5
- odxtools/templates/macros/printCompanyData.xml.jinja2 +2 -5
- odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
- odxtools/templates/macros/printCompuMethod.xml.jinja2 +153 -0
- odxtools/templates/macros/printDOP.xml.jinja2 +10 -132
- odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
- odxtools/templates/macros/printElementId.xml.jinja2 +3 -3
- odxtools/templates/macros/printMux.xml.jinja2 +3 -2
- odxtools/templates/macros/printTable.xml.jinja2 +2 -3
- odxtools/unit.py +3 -5
- odxtools/unitgroup.py +3 -5
- odxtools/unitspec.py +9 -10
- odxtools/utils.py +1 -26
- odxtools/version.py +2 -2
- odxtools/{write_pdx_file.py → writepdxfile.py} +19 -10
- odxtools/xdoc.py +3 -5
- {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/METADATA +1 -1
- odxtools-7.3.0.dist-info/RECORD +192 -0
- {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/WHEEL +1 -1
- odxtools/createcompanydatas.py +0 -17
- odxtools/createsdgs.py +0 -19
- odxtools/load_file.py +0 -13
- odxtools/load_odx_d_file.py +0 -6
- odxtools/load_pdx_file.py +0 -8
- odxtools-7.1.1.dist-info/RECORD +0 -186
- /odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +0 -0
- {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/LICENSE +0 -0
- {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/entry_points.txt +0 -0
- {odxtools-7.1.1.dist-info → odxtools-7.3.0.dist-info}/top_level.txt +0 -0
odxtools/database.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from itertools import chain
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import List, Optional
|
4
|
+
from typing import IO, Any, Dict, List, Optional, OrderedDict
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
from zipfile import ZipFile
|
7
7
|
|
@@ -13,7 +13,7 @@ from .diaglayer import DiagLayer
|
|
13
13
|
from .diaglayercontainer import DiagLayerContainer
|
14
14
|
from .exceptions import odxraise
|
15
15
|
from .nameditemlist import NamedItemList
|
16
|
-
from .odxlink import OdxLinkDatabase
|
16
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
17
17
|
|
18
18
|
|
19
19
|
class Database:
|
@@ -26,69 +26,75 @@ class Database:
|
|
26
26
|
*,
|
27
27
|
pdx_zip: Optional[ZipFile] = None,
|
28
28
|
odx_d_file_name: Optional[str] = None) -> None:
|
29
|
-
self.model_version = None
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
29
|
+
self.model_version: Optional[Version] = None
|
30
|
+
self.auxiliary_files: OrderedDict[str, IO[bytes]] = OrderedDict()
|
31
|
+
|
32
|
+
# create an empty database object
|
33
|
+
self._diag_layer_containers = NamedItemList[DiagLayerContainer]()
|
34
|
+
self._comparam_subsets = NamedItemList[ComparamSubset]()
|
35
|
+
self._comparam_specs = NamedItemList[ComparamSpec]()
|
36
|
+
|
37
|
+
def add_pdx_file(self, pdx_file_name: str) -> None:
|
38
|
+
pdx_zip = ZipFile(pdx_file_name)
|
39
|
+
|
40
|
+
for zip_member in pdx_zip.namelist():
|
41
|
+
# The name of ODX files can end with .odx, .odx-d,
|
42
|
+
# .odx-c, .odx-cs, .odx-e, .odx-f, .odx-fd, .odx-m,
|
43
|
+
# .odx-v . We could test for all that, or just make
|
44
|
+
# sure that the file's suffix starts with .odx
|
45
|
+
p = Path(zip_member)
|
46
|
+
if p.suffix.lower().startswith(".odx"):
|
47
|
+
root = ElementTree.parse(pdx_zip.open(zip_member)).getroot()
|
48
|
+
self._process_xml_tree(root)
|
49
|
+
elif p.name.lower() != "index.xml":
|
50
|
+
self.add_auxiliary_file(zip_member, pdx_zip.open(zip_member))
|
51
|
+
|
52
|
+
def add_odx_file(self, odx_file_name: str) -> None:
|
53
|
+
self._process_xml_tree(ElementTree.parse(odx_file_name).getroot())
|
54
|
+
|
55
|
+
def add_auxiliary_file(self,
|
56
|
+
aux_file_name: str,
|
57
|
+
aux_file_obj: Optional[IO[bytes]] = None) -> None:
|
58
|
+
if aux_file_obj is None:
|
59
|
+
aux_file_obj = open(aux_file_name, "rb")
|
60
|
+
|
61
|
+
self.auxiliary_files[aux_file_name] = aux_file_obj
|
62
|
+
|
63
|
+
def _process_xml_tree(self, root: ElementTree.Element) -> None:
|
58
64
|
dlcs: List[DiagLayerContainer] = []
|
59
65
|
comparam_subsets: List[ComparamSubset] = []
|
60
66
|
comparam_specs: List[ComparamSpec] = []
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
self.
|
90
|
-
|
91
|
-
self.
|
67
|
+
|
68
|
+
# ODX spec version
|
69
|
+
model_version = Version(root.attrib.get("MODEL-VERSION", "2.0"))
|
70
|
+
if self.model_version is not None and self.model_version != model_version:
|
71
|
+
odxraise(f"Different ODX versions used for the same database (ODX {model_version} "
|
72
|
+
f"and ODX {self.model_version}")
|
73
|
+
|
74
|
+
self.model_version = model_version
|
75
|
+
|
76
|
+
dlc = root.find("DIAG-LAYER-CONTAINER")
|
77
|
+
if dlc is not None:
|
78
|
+
dlcs.append(DiagLayerContainer.from_et(dlc, []))
|
79
|
+
|
80
|
+
# In ODX 2.0 there was only COMPARAM-SPEC. In ODX 2.2 the
|
81
|
+
# content of COMPARAM-SPEC was moved to COMPARAM-SUBSET
|
82
|
+
# and COMPARAM-SPEC became a container for PROT-STACKS and
|
83
|
+
# a PROT-STACK references a list of COMPARAM-SUBSET
|
84
|
+
cp_subset = root.find("COMPARAM-SUBSET")
|
85
|
+
if cp_subset is not None:
|
86
|
+
comparam_subsets.append(ComparamSubset.from_et(cp_subset, []))
|
87
|
+
|
88
|
+
cp_spec = root.find("COMPARAM-SPEC")
|
89
|
+
if cp_spec is not None:
|
90
|
+
if model_version < Version("2.2"):
|
91
|
+
comparam_subsets.append(ComparamSubset.from_et(cp_spec, []))
|
92
|
+
else: # odx >= 2.2
|
93
|
+
comparam_specs.append(ComparamSpec.from_et(cp_spec, []))
|
94
|
+
|
95
|
+
self._diag_layer_containers.extend(dlcs)
|
96
|
+
self._comparam_subsets.extend(comparam_subsets)
|
97
|
+
self._comparam_specs.extend(comparam_specs)
|
92
98
|
|
93
99
|
def refresh(self) -> None:
|
94
100
|
# Create wrapper objects
|
@@ -102,15 +108,7 @@ class Database:
|
|
102
108
|
|
103
109
|
# Build odxlinks
|
104
110
|
self._odxlinks = OdxLinkDatabase()
|
105
|
-
|
106
|
-
for subset in self.comparam_subsets:
|
107
|
-
self._odxlinks.update(subset._build_odxlinks())
|
108
|
-
|
109
|
-
for spec in self.comparam_specs:
|
110
|
-
self._odxlinks.update(spec._build_odxlinks())
|
111
|
-
|
112
|
-
for dlc in self.diag_layer_containers:
|
113
|
-
self._odxlinks.update(dlc._build_odxlinks())
|
111
|
+
self._odxlinks.update(self._build_odxlinks())
|
114
112
|
|
115
113
|
# Resolve ODXLINK references
|
116
114
|
for subset in self.comparam_subsets:
|
@@ -125,7 +123,21 @@ class Database:
|
|
125
123
|
# let the diaglayers sort out the inherited objects and the
|
126
124
|
# short name references
|
127
125
|
for dlc in self.diag_layer_containers:
|
128
|
-
dlc._finalize_init(self._odxlinks)
|
126
|
+
dlc._finalize_init(self, self._odxlinks)
|
127
|
+
|
128
|
+
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
129
|
+
result: Dict[OdxLinkId, Any] = {}
|
130
|
+
|
131
|
+
for subset in self.comparam_subsets:
|
132
|
+
result.update(subset._build_odxlinks())
|
133
|
+
|
134
|
+
for spec in self.comparam_specs:
|
135
|
+
result.update(spec._build_odxlinks())
|
136
|
+
|
137
|
+
for dlc in self.diag_layer_containers:
|
138
|
+
result.update(dlc._build_odxlinks())
|
139
|
+
|
140
|
+
return result
|
129
141
|
|
130
142
|
@property
|
131
143
|
def odxlinks(self) -> OdxLinkDatabase:
|
odxtools/dataobjectproperty.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional, cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .compumethods.compumethod import CompuMethod
|
@@ -10,17 +10,15 @@ from .decodestate import DecodeState
|
|
10
10
|
from .diagcodedtype import DiagCodedType
|
11
11
|
from .dopbase import DopBase
|
12
12
|
from .encodestate import EncodeState
|
13
|
-
from .exceptions import DecodeError, EncodeError,
|
13
|
+
from .exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
14
14
|
from .internalconstr import InternalConstr
|
15
15
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
16
16
|
from .odxtypes import AtomicOdxType, ParameterValue
|
17
17
|
from .physicaltype import PhysicalType
|
18
|
+
from .snrefcontext import SnRefContext
|
18
19
|
from .unit import Unit
|
19
20
|
from .utils import dataclass_fields_asdict
|
20
21
|
|
21
|
-
if TYPE_CHECKING:
|
22
|
-
from .diaglayer import DiagLayer
|
23
|
-
|
24
22
|
|
25
23
|
@dataclass
|
26
24
|
class DataObjectProperty(DopBase):
|
@@ -98,10 +96,10 @@ class DataObjectProperty(DopBase):
|
|
98
96
|
if self.unit_ref:
|
99
97
|
self._unit = odxlinks.resolve(self.unit_ref, Unit)
|
100
98
|
|
101
|
-
def _resolve_snrefs(self,
|
102
|
-
super()._resolve_snrefs(
|
99
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
100
|
+
super()._resolve_snrefs(context)
|
103
101
|
|
104
|
-
self.diag_coded_type._resolve_snrefs(
|
102
|
+
self.diag_coded_type._resolve_snrefs(context)
|
105
103
|
|
106
104
|
@property
|
107
105
|
def unit(self) -> Optional[Unit]:
|
@@ -110,16 +108,6 @@ class DataObjectProperty(DopBase):
|
|
110
108
|
def get_static_bit_length(self) -> Optional[int]:
|
111
109
|
return self.diag_coded_type.get_static_bit_length()
|
112
110
|
|
113
|
-
def convert_physical_to_internal(self, physical_value: Any) -> Any:
|
114
|
-
"""
|
115
|
-
Convert a physical representation of a parameter to its internal counterpart
|
116
|
-
"""
|
117
|
-
odxassert(
|
118
|
-
self.physical_type.base_data_type.isinstance(physical_value),
|
119
|
-
f"Expected {self.physical_type.base_data_type.value}, got {type(physical_value)}")
|
120
|
-
|
121
|
-
return self.compu_method.convert_physical_to_internal(physical_value)
|
122
|
-
|
123
111
|
def encode_into_pdu(self, physical_value: ParameterValue, encode_state: EncodeState) -> None:
|
124
112
|
"""
|
125
113
|
Convert a physical representation of a parameter to a string bytes that can be send over the wire
|
@@ -129,7 +117,10 @@ class DataObjectProperty(DopBase):
|
|
129
117
|
f"The value {repr(physical_value)} of type {type(physical_value).__name__}"
|
130
118
|
f" is not a valid.")
|
131
119
|
|
132
|
-
|
120
|
+
if not isinstance(physical_value, (int, float, str, bytes, bytearray)):
|
121
|
+
odxraise(f"Invalid type '{type(physical_value).__name__}' for physical value. "
|
122
|
+
f"(Expect atomic type!)")
|
123
|
+
internal_value = self.compu_method.convert_physical_to_internal(physical_value)
|
133
124
|
self.diag_coded_type.encode_into_pdu(internal_value, encode_state)
|
134
125
|
|
135
126
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
odxtools/decodestate.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass, field
|
3
|
-
from typing import TYPE_CHECKING, Dict, cast
|
3
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, cast
|
4
4
|
|
5
5
|
import odxtools.exceptions as exceptions
|
6
6
|
|
7
7
|
from .exceptions import DecodeError
|
8
|
-
from .odxtypes import AtomicOdxType, DataType
|
8
|
+
from .odxtypes import AtomicOdxType, DataType, ParameterValue
|
9
9
|
|
10
10
|
try:
|
11
11
|
import bitstruct.c as bitstruct
|
@@ -13,6 +13,7 @@ except ImportError:
|
|
13
13
|
import bitstruct
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
16
|
+
from .parameters.parameter import Parameter
|
16
17
|
from .tablerow import TableRow
|
17
18
|
|
18
19
|
|
@@ -46,6 +47,11 @@ class DecodeState:
|
|
46
47
|
#: values of the table key parameters decoded so far
|
47
48
|
table_keys: Dict[str, "TableRow"] = field(default_factory=dict)
|
48
49
|
|
50
|
+
#: List of parameters that have been decoded so far. The journal
|
51
|
+
#: is used by some types of parameters which depend on the values of
|
52
|
+
#: other parameters; i.e., environment data description parameters
|
53
|
+
journal: List[Tuple["Parameter", Optional[ParameterValue]]] = field(default_factory=list)
|
54
|
+
|
49
55
|
def extract_atomic_value(
|
50
56
|
self,
|
51
57
|
bit_length: int,
|
odxtools/description.py
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import List, Optional
|
3
|
+
from xml.etree import ElementTree
|
4
|
+
|
5
|
+
from .exceptions import odxrequire
|
6
|
+
from .odxlink import OdxDocFragment
|
7
|
+
|
8
|
+
|
9
|
+
@dataclass
|
10
|
+
class Description:
|
11
|
+
text: str
|
12
|
+
external_docs: List[str]
|
13
|
+
text_identifier: Optional[str]
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
def from_et(et_element: Optional[ElementTree.Element],
|
17
|
+
doc_frags: List[OdxDocFragment]) -> Optional["Description"]:
|
18
|
+
if et_element is None:
|
19
|
+
return None
|
20
|
+
|
21
|
+
# Extract the contents of the tag as a XHTML string.
|
22
|
+
raw_string = et_element.text or ""
|
23
|
+
for e in et_element:
|
24
|
+
if e.tag == "EXTERNAL-DOCS":
|
25
|
+
break
|
26
|
+
raw_string += ElementTree.tostring(e, encoding="unicode")
|
27
|
+
|
28
|
+
# remove white spaces at the beginning and at the end of all
|
29
|
+
# extracted lines
|
30
|
+
stripped_lines = [x.strip() for x in raw_string.split("\n")]
|
31
|
+
|
32
|
+
text = "\n".join(stripped_lines).strip()
|
33
|
+
|
34
|
+
text_identifier = et_element.get("TI")
|
35
|
+
|
36
|
+
external_docs = \
|
37
|
+
[
|
38
|
+
odxrequire(ed.get("HREF")) for ed in et_element.iterfind("EXTERNAL-DOCS/EXTERNAL-DOC")
|
39
|
+
]
|
40
|
+
return Description(text=text, text_identifier=text_identifier, external_docs=external_docs)
|
41
|
+
|
42
|
+
@staticmethod
|
43
|
+
def from_string(text: str) -> "Description":
|
44
|
+
return Description(text=text, external_docs=[], text_identifier=None)
|
45
|
+
|
46
|
+
def __str__(self) -> str:
|
47
|
+
return self.text
|
@@ -1,13 +1,12 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
1
2
|
from dataclasses import dataclass
|
2
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional
|
3
4
|
from xml.etree import ElementTree
|
4
5
|
|
5
6
|
from .dataobjectproperty import DataObjectProperty
|
6
7
|
from .exceptions import odxrequire
|
7
8
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
8
|
-
|
9
|
-
if TYPE_CHECKING:
|
10
|
-
from .diaglayer import DiagLayer
|
9
|
+
from .snrefcontext import SnRefContext
|
11
10
|
|
12
11
|
|
13
12
|
@dataclass
|
@@ -39,7 +38,7 @@ class DetermineNumberOfItems:
|
|
39
38
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
40
39
|
self._dop = odxlinks.resolve(self.dop_ref, DataObjectProperty)
|
41
40
|
|
42
|
-
def _resolve_snrefs(self,
|
41
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
43
42
|
pass
|
44
43
|
|
45
44
|
@property
|
odxtools/diagcodedtype.py
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
import abc
|
3
2
|
from dataclasses import dataclass
|
4
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Literal, Optional, Union, cast
|
4
|
+
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .decodestate import DecodeState
|
7
7
|
from .encodestate import EncodeState
|
8
|
-
from .exceptions import odxassert, odxraise
|
9
|
-
from .odxlink import OdxLinkDatabase, OdxLinkId
|
10
|
-
from .odxtypes import AtomicOdxType, DataType
|
11
|
-
|
12
|
-
if TYPE_CHECKING:
|
13
|
-
from .diaglayer import DiagLayer
|
8
|
+
from .exceptions import odxassert, odxraise, odxrequire
|
9
|
+
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
10
|
+
from .odxtypes import AtomicOdxType, DataType, odxstr_to_bool
|
11
|
+
from .snrefcontext import SnRefContext
|
14
12
|
|
15
13
|
# Allowed diag-coded types
|
16
14
|
DctType = Literal[
|
@@ -22,12 +20,30 @@ DctType = Literal[
|
|
22
20
|
|
23
21
|
|
24
22
|
@dataclass
|
25
|
-
class DiagCodedType
|
23
|
+
class DiagCodedType:
|
26
24
|
|
27
25
|
base_data_type: DataType
|
28
26
|
base_type_encoding: Optional[str]
|
29
27
|
is_highlow_byte_order_raw: Optional[bool]
|
30
28
|
|
29
|
+
@staticmethod
|
30
|
+
def from_et(et_element: ElementTree.Element,
|
31
|
+
doc_frags: List[OdxDocFragment]) -> "DiagCodedType":
|
32
|
+
base_data_type_str = odxrequire(et_element.get("BASE-DATA-TYPE"))
|
33
|
+
try:
|
34
|
+
base_data_type = DataType(base_data_type_str)
|
35
|
+
except ValueError:
|
36
|
+
odxraise(f"Unknown base data type {base_data_type_str}")
|
37
|
+
base_data_type = cast(DataType, None)
|
38
|
+
|
39
|
+
base_type_encoding = et_element.get("BASE-TYPE-ENCODING")
|
40
|
+
is_highlow_byte_order_raw = odxstr_to_bool(et_element.get("IS-HIGHLOW-BYTE-ORDER"))
|
41
|
+
|
42
|
+
return DiagCodedType(
|
43
|
+
base_data_type=base_data_type,
|
44
|
+
base_type_encoding=base_type_encoding,
|
45
|
+
is_highlow_byte_order_raw=is_highlow_byte_order_raw)
|
46
|
+
|
31
47
|
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]: # noqa: B027
|
32
48
|
return {}
|
33
49
|
|
@@ -35,7 +51,7 @@ class DiagCodedType(abc.ABC):
|
|
35
51
|
"""Recursively resolve any odxlinks references"""
|
36
52
|
pass
|
37
53
|
|
38
|
-
def _resolve_snrefs(self,
|
54
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None: # noqa: B027
|
39
55
|
"""Recursively resolve any short-name references"""
|
40
56
|
pass
|
41
57
|
|
@@ -43,9 +59,10 @@ class DiagCodedType(abc.ABC):
|
|
43
59
|
return None
|
44
60
|
|
45
61
|
@property
|
46
|
-
@abc.abstractmethod
|
47
62
|
def dct_type(self) -> DctType:
|
48
|
-
|
63
|
+
odxraise(f"Class {type(self).__name__} does not override required method "
|
64
|
+
f"dct_type()", NotImplementedError)
|
65
|
+
return cast(DctType, None)
|
49
66
|
|
50
67
|
@property
|
51
68
|
def is_highlow_byte_order(self) -> bool:
|
odxtools/diagcomm.py
CHANGED
@@ -6,13 +6,13 @@ from xml.etree import ElementTree
|
|
6
6
|
|
7
7
|
from .admindata import AdminData
|
8
8
|
from .audience import Audience
|
9
|
-
from .createsdgs import create_sdgs_from_et
|
10
9
|
from .element import IdentifiableElement
|
11
10
|
from .exceptions import odxraise, odxrequire
|
12
11
|
from .functionalclass import FunctionalClass
|
13
12
|
from .nameditemlist import NamedItemList
|
14
13
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
15
14
|
from .odxtypes import odxstr_to_bool
|
15
|
+
from .snrefcontext import SnRefContext
|
16
16
|
from .specialdatagroup import SpecialDataGroup
|
17
17
|
from .state import State
|
18
18
|
from .statetransition import StateTransition
|
@@ -76,7 +76,9 @@ class DiagComm(IdentifiableElement):
|
|
76
76
|
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
|
77
77
|
|
78
78
|
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
|
79
|
-
sdgs =
|
79
|
+
sdgs = [
|
80
|
+
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
81
|
+
]
|
80
82
|
|
81
83
|
functional_class_refs = [
|
82
84
|
odxrequire(OdxLinkRef.from_et(el, doc_frags))
|
@@ -201,22 +203,24 @@ class DiagComm(IdentifiableElement):
|
|
201
203
|
self._state_transitions = NamedItemList(
|
202
204
|
[odxlinks.resolve(stt_ref, StateTransition) for stt_ref in self.state_transition_refs])
|
203
205
|
|
204
|
-
def _resolve_snrefs(self,
|
206
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
205
207
|
if self.admin_data:
|
206
|
-
self.admin_data._resolve_snrefs(
|
208
|
+
self.admin_data._resolve_snrefs(context)
|
207
209
|
|
208
210
|
if self.audience:
|
209
|
-
self.audience._resolve_snrefs(
|
211
|
+
self.audience._resolve_snrefs(context)
|
210
212
|
|
211
213
|
for sdg in self.sdgs:
|
212
|
-
sdg._resolve_snrefs(
|
214
|
+
sdg._resolve_snrefs(context)
|
213
215
|
|
214
216
|
if TYPE_CHECKING:
|
217
|
+
diag_layer = odxrequire(context.diag_layer)
|
215
218
|
self._protocols = NamedItemList([
|
216
219
|
resolve_snref(prot_snref, diag_layer.protocols, DiagLayer)
|
217
220
|
for prot_snref in self.protocol_snrefs
|
218
221
|
])
|
219
222
|
else:
|
223
|
+
diag_layer = odxrequire(context.diag_layer)
|
220
224
|
self._protocols = NamedItemList([
|
221
225
|
resolve_snref(prot_snref, diag_layer.protocols)
|
222
226
|
for prot_snref in self.protocol_snrefs
|
@@ -1,12 +1,11 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from itertools import chain
|
4
|
-
from typing import
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .admindata import AdminData
|
8
8
|
from .basicstructure import BasicStructure
|
9
|
-
from .createsdgs import create_sdgs_from_et
|
10
9
|
from .dataobjectproperty import DataObjectProperty
|
11
10
|
from .dopbase import DopBase
|
12
11
|
from .dtcdop import DtcDop
|
@@ -19,15 +18,13 @@ from .exceptions import odxraise
|
|
19
18
|
from .multiplexer import Multiplexer
|
20
19
|
from .nameditemlist import NamedItemList
|
21
20
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
21
|
+
from .snrefcontext import SnRefContext
|
22
22
|
from .specialdatagroup import SpecialDataGroup
|
23
23
|
from .staticfield import StaticField
|
24
24
|
from .structure import Structure
|
25
25
|
from .table import Table
|
26
26
|
from .unitspec import UnitSpec
|
27
27
|
|
28
|
-
if TYPE_CHECKING:
|
29
|
-
from .diaglayer import DiagLayer
|
30
|
-
|
31
28
|
|
32
29
|
@dataclass
|
33
30
|
class DiagDataDictionarySpec:
|
@@ -135,7 +132,9 @@ class DiagDataDictionarySpec:
|
|
135
132
|
for table_element in et_element.iterfind("TABLES/TABLE")
|
136
133
|
]
|
137
134
|
|
138
|
-
sdgs =
|
135
|
+
sdgs = [
|
136
|
+
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
137
|
+
]
|
139
138
|
|
140
139
|
return DiagDataDictionarySpec(
|
141
140
|
admin_data=admin_data,
|
@@ -219,35 +218,35 @@ class DiagDataDictionarySpec:
|
|
219
218
|
for sdg in self.sdgs:
|
220
219
|
sdg._resolve_odxlinks(odxlinks)
|
221
220
|
|
222
|
-
def _resolve_snrefs(self,
|
221
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
223
222
|
if self.admin_data is not None:
|
224
|
-
self.admin_data._resolve_snrefs(
|
223
|
+
self.admin_data._resolve_snrefs(context)
|
225
224
|
for dtc_dop in self.dtc_dops:
|
226
|
-
dtc_dop._resolve_snrefs(
|
225
|
+
dtc_dop._resolve_snrefs(context)
|
227
226
|
for env_data_desc in self.env_data_descs:
|
228
|
-
env_data_desc._resolve_snrefs(
|
227
|
+
env_data_desc._resolve_snrefs(context)
|
229
228
|
for data_object_prop in self.data_object_props:
|
230
|
-
data_object_prop._resolve_snrefs(
|
229
|
+
data_object_prop._resolve_snrefs(context)
|
231
230
|
for structure in self.structures:
|
232
|
-
structure._resolve_snrefs(
|
231
|
+
structure._resolve_snrefs(context)
|
233
232
|
for static_field in self.static_fields:
|
234
|
-
static_field._resolve_snrefs(
|
233
|
+
static_field._resolve_snrefs(context)
|
235
234
|
for dynamic_length_field in self.dynamic_length_fields:
|
236
|
-
dynamic_length_field._resolve_snrefs(
|
235
|
+
dynamic_length_field._resolve_snrefs(context)
|
237
236
|
for dynamic_endmarker_field in self.dynamic_endmarker_fields:
|
238
|
-
dynamic_endmarker_field._resolve_snrefs(
|
237
|
+
dynamic_endmarker_field._resolve_snrefs(context)
|
239
238
|
for end_of_pdu_field in self.end_of_pdu_fields:
|
240
|
-
end_of_pdu_field._resolve_snrefs(
|
239
|
+
end_of_pdu_field._resolve_snrefs(context)
|
241
240
|
for mux in self.muxs:
|
242
|
-
mux._resolve_snrefs(
|
241
|
+
mux._resolve_snrefs(context)
|
243
242
|
for env_data in self.env_datas:
|
244
|
-
env_data._resolve_snrefs(
|
243
|
+
env_data._resolve_snrefs(context)
|
245
244
|
if self.unit_spec is not None:
|
246
|
-
self.unit_spec._resolve_snrefs(
|
245
|
+
self.unit_spec._resolve_snrefs(context)
|
247
246
|
for table in self.tables:
|
248
|
-
table._resolve_snrefs(
|
247
|
+
table._resolve_snrefs(context)
|
249
248
|
for sdg in self.sdgs:
|
250
|
-
sdg._resolve_snrefs(
|
249
|
+
sdg._resolve_snrefs(context)
|
251
250
|
|
252
251
|
@property
|
253
252
|
def all_data_object_properties(self) -> NamedItemList[DopBase]:
|