odxtools 7.0.0__py3-none-any.whl → 7.1.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/basicstructure.py +1 -5
- odxtools/diagcomm.py +11 -3
- odxtools/diagdatadictionaryspec.py +14 -14
- odxtools/diaglayer.py +7 -1
- odxtools/diaglayerraw.py +13 -7
- odxtools/dynamicendmarkerfield.py +119 -0
- odxtools/dynamiclengthfield.py +9 -3
- odxtools/dynenddopref.py +38 -0
- odxtools/encodestate.py +3 -3
- odxtools/endofpdufield.py +20 -3
- odxtools/environmentdata.py +8 -1
- odxtools/environmentdatadescription.py +8 -2
- odxtools/field.py +4 -3
- odxtools/matchingparameter.py +2 -2
- odxtools/multiplexercase.py +2 -2
- odxtools/multiplexerdefaultcase.py +7 -3
- odxtools/odxlink.py +38 -4
- odxtools/odxtypes.py +3 -2
- odxtools/parameters/codedconstparameter.py +3 -2
- odxtools/parameters/lengthkeyparameter.py +4 -3
- odxtools/parameters/nrcconstparameter.py +3 -2
- odxtools/parameters/parameter.py +6 -0
- odxtools/parameters/parameterwithdop.py +10 -14
- odxtools/parameters/physicalconstantparameter.py +4 -3
- odxtools/parameters/tablekeyparameter.py +9 -9
- odxtools/parameters/tablestructparameter.py +6 -25
- odxtools/parameters/valueparameter.py +4 -3
- odxtools/py.typed +0 -0
- odxtools/statechart.py +5 -9
- odxtools/statetransition.py +3 -8
- odxtools/staticfield.py +17 -3
- odxtools/tablerow.py +5 -3
- odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +16 -0
- odxtools/templates/macros/printVariant.xml.jinja2 +8 -0
- odxtools/version.py +2 -2
- {odxtools-7.0.0.dist-info → odxtools-7.1.1.dist-info}/METADATA +1 -1
- {odxtools-7.0.0.dist-info → odxtools-7.1.1.dist-info}/RECORD +41 -37
- {odxtools-7.0.0.dist-info → odxtools-7.1.1.dist-info}/LICENSE +0 -0
- {odxtools-7.0.0.dist-info → odxtools-7.1.1.dist-info}/WHEEL +0 -0
- {odxtools-7.0.0.dist-info → odxtools-7.1.1.dist-info}/entry_points.txt +0 -0
- {odxtools-7.0.0.dist-info → odxtools-7.1.1.dist-info}/top_level.txt +0 -0
odxtools/odxlink.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
import warnings
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import Any, Dict, List, Optional, Type, TypeVar, overload
|
4
|
+
from typing import Any, Dict, Iterable, List, Optional, Type, TypeVar, overload
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
|
-
from .exceptions import OdxWarning, odxassert
|
7
|
+
from .exceptions import OdxWarning, odxassert, odxraise
|
8
|
+
from .nameditemlist import OdxNamed, TNamed
|
8
9
|
|
9
10
|
|
10
11
|
@dataclass(frozen=True)
|
@@ -210,8 +211,10 @@ class OdxLinkDatabase:
|
|
210
211
|
|
211
212
|
return obj
|
212
213
|
|
213
|
-
|
214
|
-
|
214
|
+
odxraise(
|
215
|
+
f"ODXLINK reference {ref} could not be resolved for any "
|
216
|
+
f"of the document fragments {ref.ref_docs}", KeyError)
|
217
|
+
return None
|
215
218
|
|
216
219
|
@overload
|
217
220
|
def resolve_lenient(self, ref: OdxLinkRef, expected_type: None = None) -> Any:
|
@@ -270,3 +273,34 @@ class OdxLinkDatabase:
|
|
270
273
|
self._db[doc_frag] = {}
|
271
274
|
|
272
275
|
self._db[doc_frag][odx_id] = obj
|
276
|
+
|
277
|
+
|
278
|
+
@overload
|
279
|
+
def resolve_snref(target_short_name: str,
|
280
|
+
items: Iterable[OdxNamed],
|
281
|
+
expected_type: None = None) -> Any:
|
282
|
+
"""Resolve a short name reference given a sequence of candidate objects"""
|
283
|
+
...
|
284
|
+
|
285
|
+
|
286
|
+
@overload
|
287
|
+
def resolve_snref(target_short_name: str, items: Iterable[OdxNamed],
|
288
|
+
expected_type: Type[TNamed]) -> TNamed:
|
289
|
+
...
|
290
|
+
|
291
|
+
|
292
|
+
def resolve_snref(target_short_name: str,
|
293
|
+
items: Iterable[OdxNamed],
|
294
|
+
expected_type: Any = None) -> Any:
|
295
|
+
candidates = [x for x in items if x.short_name == target_short_name]
|
296
|
+
|
297
|
+
if not candidates:
|
298
|
+
odxraise(f"Cannot resolve short name reference to '{target_short_name}'")
|
299
|
+
return None
|
300
|
+
elif len(candidates) > 1:
|
301
|
+
odxraise(f"Cannot uniquely resolve short name reference to '{target_short_name}'")
|
302
|
+
elif expected_type is not None and not isinstance(candidates[0], expected_type):
|
303
|
+
odxraise(f"Reference '{target_short_name}' points to a {type(candidates[0]).__name__}"
|
304
|
+
f"object while expecting {expected_type.__name__}")
|
305
|
+
|
306
|
+
return candidates[0]
|
odxtools/odxtypes.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from enum import Enum
|
3
|
-
from typing import TYPE_CHECKING, Any, Callable, Dict,
|
3
|
+
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Optional, Tuple, Type, Union,
|
4
|
+
overload)
|
4
5
|
from xml.etree import ElementTree
|
5
6
|
|
6
7
|
from .exceptions import odxassert, odxraise, odxrequire
|
@@ -28,7 +29,7 @@ ParameterDict = Dict[str, Union["Parameter", "ParameterDict"]]
|
|
28
29
|
# multiple items, so this can be a list of objects.
|
29
30
|
TableStructParameterValue = Tuple[str, "ParameterValue"]
|
30
31
|
ParameterValue = Union[AtomicOdxType, "ParameterValueDict", TableStructParameterValue,
|
31
|
-
|
32
|
+
Iterable["ParameterValue"], "DiagnosticTroubleCode"]
|
32
33
|
ParameterValueDict = Dict[str, ParameterValue]
|
33
34
|
|
34
35
|
|
@@ -59,8 +59,9 @@ class CodedConstParameter(Parameter):
|
|
59
59
|
super()._resolve_odxlinks(odxlinks)
|
60
60
|
|
61
61
|
@override
|
62
|
-
def
|
63
|
-
|
62
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
63
|
+
param_list: List[Parameter]) -> None:
|
64
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
64
65
|
|
65
66
|
@override
|
66
67
|
def get_static_bit_length(self) -> Optional[int]:
|
@@ -11,7 +11,7 @@ from ..exceptions import EncodeError, odxraise, odxrequire
|
|
11
11
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
12
12
|
from ..odxtypes import ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
14
|
-
from .parameter import ParameterType
|
14
|
+
from .parameter import Parameter, ParameterType
|
15
15
|
from .parameterwithdop import ParameterWithDOP
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
@@ -60,8 +60,9 @@ class LengthKeyParameter(ParameterWithDOP):
|
|
60
60
|
super()._resolve_odxlinks(odxlinks)
|
61
61
|
|
62
62
|
@override
|
63
|
-
def
|
64
|
-
|
63
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
64
|
+
param_list: List[Parameter]) -> None:
|
65
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
65
66
|
|
66
67
|
@property
|
67
68
|
@override
|
@@ -75,8 +75,9 @@ class NrcConstParameter(Parameter):
|
|
75
75
|
super()._resolve_odxlinks(odxlinks)
|
76
76
|
|
77
77
|
@override
|
78
|
-
def
|
79
|
-
|
78
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
79
|
+
param_list: List[Parameter]) -> None:
|
80
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
80
81
|
|
81
82
|
@override
|
82
83
|
def get_static_bit_length(self) -> Optional[int]:
|
odxtools/parameters/parameter.py
CHANGED
@@ -82,7 +82,13 @@ class Parameter(NamedElement):
|
|
82
82
|
for sdg in self.sdgs:
|
83
83
|
sdg._resolve_odxlinks(odxlinks)
|
84
84
|
|
85
|
+
@final
|
85
86
|
def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
|
87
|
+
raise RuntimeError("Calling _resolve_snrefs() is not allowed for parameters. "
|
88
|
+
"Use _parameter_resolve_snrefs() instead.")
|
89
|
+
|
90
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
91
|
+
param_list: List["Parameter"]) -> None:
|
86
92
|
for sdg in self.sdgs:
|
87
93
|
sdg._resolve_snrefs(diag_layer)
|
88
94
|
|
@@ -11,7 +11,7 @@ from ..dopbase import DopBase
|
|
11
11
|
from ..dtcdop import DtcDop
|
12
12
|
from ..encodestate import EncodeState
|
13
13
|
from ..exceptions import odxassert, odxrequire
|
14
|
-
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
14
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
15
15
|
from ..odxtypes import AtomicOdxType, ParameterValue
|
16
16
|
from ..physicaltype import PhysicalType
|
17
17
|
from ..utils import dataclass_fields_asdict
|
@@ -43,7 +43,7 @@ class ParameterWithDOP(Parameter):
|
|
43
43
|
def __post_init__(self) -> None:
|
44
44
|
odxassert(self.dop_snref is not None or self.dop_ref is not None,
|
45
45
|
f"Param {self.short_name} without a DOP-(SN)REF should not exist!")
|
46
|
-
self._dop:
|
46
|
+
self._dop: DopBase
|
47
47
|
|
48
48
|
@override
|
49
49
|
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
@@ -55,26 +55,22 @@ class ParameterWithDOP(Parameter):
|
|
55
55
|
|
56
56
|
if self.dop_ref is not None:
|
57
57
|
odxassert(self.dop_snref is None)
|
58
|
-
|
59
|
-
# that currently not all kinds of DOPs are internalized
|
60
|
-
# (e.g., static and dynamic fields)
|
61
|
-
self._dop = odxlinks.resolve_lenient(self.dop_ref)
|
58
|
+
self._dop = odxlinks.resolve(self.dop_ref)
|
62
59
|
|
63
60
|
@override
|
64
|
-
def
|
65
|
-
|
61
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
62
|
+
param_list: List[Parameter]) -> None:
|
63
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
66
64
|
|
67
65
|
if self.dop_snref:
|
68
|
-
|
69
|
-
self._dop =
|
66
|
+
all_dops = diag_layer.diag_data_dictionary_spec.all_data_object_properties
|
67
|
+
self._dop = resolve_snref(self.dop_snref, all_dops, DopBase)
|
70
68
|
|
71
69
|
@property
|
72
70
|
def dop(self) -> DopBase:
|
73
|
-
"""
|
71
|
+
"""This is usually a DataObjectProperty or a Structure object"""
|
74
72
|
|
75
|
-
return
|
76
|
-
self._dop, "Specifying a data object property is mandatory but it "
|
77
|
-
"could not be resolved")
|
73
|
+
return self._dop
|
78
74
|
|
79
75
|
@override
|
80
76
|
def get_static_bit_length(self) -> Optional[int]:
|
@@ -12,7 +12,7 @@ from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
|
12
12
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
13
13
|
from ..odxtypes import ParameterValue
|
14
14
|
from ..utils import dataclass_fields_asdict
|
15
|
-
from .parameter import ParameterType
|
15
|
+
from .parameter import Parameter, ParameterType
|
16
16
|
from .parameterwithdop import ParameterWithDOP
|
17
17
|
|
18
18
|
if TYPE_CHECKING:
|
@@ -50,8 +50,9 @@ class PhysicalConstantParameter(ParameterWithDOP):
|
|
50
50
|
super()._resolve_odxlinks(odxlinks)
|
51
51
|
|
52
52
|
@override
|
53
|
-
def
|
54
|
-
|
53
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
54
|
+
param_list: List[Parameter]) -> None:
|
55
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
55
56
|
|
56
57
|
dop = odxrequire(self.dop)
|
57
58
|
if not isinstance(dop, DataObjectProperty):
|
@@ -8,7 +8,7 @@ from typing_extensions import final, override
|
|
8
8
|
from ..decodestate import DecodeState
|
9
9
|
from ..encodestate import EncodeState
|
10
10
|
from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
11
|
-
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
11
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
12
12
|
from ..odxtypes import ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
14
14
|
from .parameter import Parameter, ParameterType
|
@@ -94,19 +94,19 @@ class TableKeyParameter(Parameter):
|
|
94
94
|
self._table = self._table_row.table
|
95
95
|
|
96
96
|
@override
|
97
|
-
def
|
98
|
-
|
97
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
98
|
+
param_list: List[Parameter]) -> None:
|
99
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
99
100
|
|
100
101
|
if self.table_snref is not None:
|
101
|
-
|
102
|
-
self._table =
|
102
|
+
tables = diag_layer.diag_data_dictionary_spec.tables
|
103
|
+
self._table = resolve_snref(self.table_snref, tables, Table)
|
103
104
|
if self.table_row_snref is not None:
|
104
105
|
# make sure that we know the table to which the table row
|
105
106
|
# SNREF is relative to.
|
106
|
-
table = odxrequire(
|
107
|
-
|
108
|
-
|
109
|
-
self._table_row = table.table_rows[self.table_row_snref]
|
107
|
+
table = odxrequire(self._table,
|
108
|
+
"If a table-row is referenced, a table must also be referenced.")
|
109
|
+
self._table_row = resolve_snref(self.table_row_snref, table.table_rows, TableRow)
|
110
110
|
|
111
111
|
@property
|
112
112
|
def table(self) -> "Table":
|
@@ -3,12 +3,12 @@ from dataclasses import dataclass
|
|
3
3
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
-
from typing_extensions import
|
6
|
+
from typing_extensions import override
|
7
7
|
|
8
8
|
from ..decodestate import DecodeState
|
9
9
|
from ..encodestate import EncodeState
|
10
10
|
from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
11
|
-
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
11
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
12
12
|
from ..odxtypes import ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
14
14
|
from .parameter import Parameter, ParameterType
|
@@ -60,31 +60,12 @@ class TableStructParameter(Parameter):
|
|
60
60
|
self._table_key = odxlinks.resolve(self.table_key_ref, TableKeyParameter)
|
61
61
|
|
62
62
|
@override
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
f"Use ._table_struct_resolve_snrefs() instead.")
|
67
|
-
|
68
|
-
def _table_struct_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
69
|
-
param_list: List[Parameter]) -> None:
|
70
|
-
super()._resolve_snrefs(diag_layer)
|
63
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
64
|
+
param_list: List[Parameter]) -> None:
|
65
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
71
66
|
|
72
67
|
if self.table_key_snref is not None:
|
73
|
-
|
74
|
-
if len(tk_candidates) > 1:
|
75
|
-
odxraise(f"Short name reference '{self.table_key_snref}' could "
|
76
|
-
f"not be uniquely resolved.")
|
77
|
-
elif len(tk_candidates) == 0:
|
78
|
-
odxraise(f"Short name reference '{self.table_key_snref}' could "
|
79
|
-
f"not be resolved.")
|
80
|
-
return
|
81
|
-
|
82
|
-
tk = tk_candidates[0]
|
83
|
-
if not isinstance(tk, TableKeyParameter):
|
84
|
-
odxraise(f"Table struct '{self.short_name}' references non-TableKey parameter "
|
85
|
-
f"`{self.table_key_snref}' as its table key.")
|
86
|
-
|
87
|
-
self._table_key = tk
|
68
|
+
self._table_key = resolve_snref(self.table_key_snref, param_list, TableKeyParameter)
|
88
69
|
|
89
70
|
@property
|
90
71
|
def table_key(self) -> TableKeyParameter:
|
@@ -11,7 +11,7 @@ from ..exceptions import EncodeError, odxraise, odxrequire
|
|
11
11
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
12
12
|
from ..odxtypes import AtomicOdxType, ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
14
|
-
from .parameter import ParameterType
|
14
|
+
from .parameter import Parameter, ParameterType
|
15
15
|
from .parameterwithdop import ParameterWithDOP
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
@@ -50,8 +50,9 @@ class ValueParameter(ParameterWithDOP):
|
|
50
50
|
super()._resolve_odxlinks(odxlinks)
|
51
51
|
|
52
52
|
@override
|
53
|
-
def
|
54
|
-
|
53
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
54
|
+
param_list: List[Parameter]) -> None:
|
55
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
55
56
|
|
56
57
|
if self.physical_default_value_raw is not None:
|
57
58
|
dop = odxrequire(self.dop)
|
odxtools/py.typed
ADDED
File without changes
|
odxtools/statechart.py
CHANGED
@@ -6,7 +6,7 @@ from xml.etree import ElementTree
|
|
6
6
|
from .element import IdentifiableElement
|
7
7
|
from .exceptions import odxrequire
|
8
8
|
from .nameditemlist import NamedItemList
|
9
|
-
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
9
|
+
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, resolve_snref
|
10
10
|
from .state import State
|
11
11
|
from .statetransition import StateTransition
|
12
12
|
from .utils import dataclass_fields_asdict
|
@@ -68,19 +68,15 @@ class StateChart(IdentifiableElement):
|
|
68
68
|
for st in self.states:
|
69
69
|
st._resolve_odxlinks(odxlinks)
|
70
70
|
|
71
|
-
|
72
|
-
#
|
71
|
+
def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
|
72
|
+
# For now, we assume that the start state short name reference
|
73
|
+
# points to a local state of the state chart. TODO: The XSD
|
73
74
|
# allows to define state charts without any states, yet the
|
74
75
|
# start state SNREF is mandatory. Is this a gap in the spec or
|
75
76
|
# does it allow "foreign" start states? If the latter, what
|
76
77
|
# does that mean?
|
77
|
-
self._start_state
|
78
|
-
for st in self.states:
|
79
|
-
if st.short_name == self.start_state_snref:
|
80
|
-
self._start_state = st
|
81
|
-
break
|
78
|
+
self._start_state = resolve_snref(self.start_state_snref, self.states, State)
|
82
79
|
|
83
|
-
def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
|
84
80
|
for st in self.states:
|
85
81
|
st._resolve_snrefs(diag_layer)
|
86
82
|
|
odxtools/statetransition.py
CHANGED
@@ -5,7 +5,7 @@ from xml.etree import ElementTree
|
|
5
5
|
|
6
6
|
from .element import IdentifiableElement
|
7
7
|
from .exceptions import odxrequire
|
8
|
-
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
8
|
+
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, resolve_snref
|
9
9
|
from .state import State
|
10
10
|
from .utils import dataclass_fields_asdict
|
11
11
|
|
@@ -55,10 +55,5 @@ class StateTransition(IdentifiableElement):
|
|
55
55
|
# chart. To mitigate this a bit, the non-standard parameters are
|
56
56
|
# keyword-only...
|
57
57
|
def _resolve_snrefs(self, diag_layer: "DiagLayer", *, states: Iterable[State]) -> None:
|
58
|
-
self._source_state
|
59
|
-
self._target_state
|
60
|
-
for st in states:
|
61
|
-
if st.short_name == self.source_snref:
|
62
|
-
self._source_state = st
|
63
|
-
if st.short_name == self.target_snref:
|
64
|
-
self._target_state = st
|
58
|
+
self._source_state = resolve_snref(self.source_snref, states, State)
|
59
|
+
self._target_state = resolve_snref(self.target_snref, states, State)
|
odxtools/staticfield.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, Any, Dict, List
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Sequence
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -51,15 +51,20 @@ class StaticField(Field):
|
|
51
51
|
def encode_into_pdu(self, physical_value: ParameterValue, encode_state: EncodeState) -> None:
|
52
52
|
|
53
53
|
if not isinstance(physical_value,
|
54
|
-
|
54
|
+
Sequence) or len(physical_value) != self.fixed_number_of_items:
|
55
55
|
odxraise(f"Value for static field '{self.short_name}' "
|
56
56
|
f"must be a list of size {self.fixed_number_of_items}")
|
57
57
|
|
58
|
-
|
58
|
+
orig_is_end_of_pdu = encode_state.is_end_of_pdu
|
59
|
+
encode_state.is_end_of_pdu = False
|
60
|
+
for i, val in enumerate(physical_value):
|
59
61
|
if not isinstance(val, dict):
|
60
62
|
odxraise(f"The individual parameter values for static field '{self.short_name}' "
|
61
63
|
f"must be dictionaries for structure '{self.structure.short_name}'")
|
62
64
|
|
65
|
+
if i == len(physical_value) - 1:
|
66
|
+
encode_state.is_end_of_pdu = orig_is_end_of_pdu
|
67
|
+
|
63
68
|
pos_before = encode_state.cursor_byte_position
|
64
69
|
self.structure.encode_into_pdu(val, encode_state)
|
65
70
|
pos_after = encode_state.cursor_byte_position
|
@@ -75,12 +80,18 @@ class StaticField(Field):
|
|
75
80
|
encode_state.emplace_bytes(b'\x00' * (self.item_byte_size -
|
76
81
|
(pos_after - pos_before)))
|
77
82
|
|
83
|
+
encode_state.is_end_of_pdu = orig_is_end_of_pdu
|
84
|
+
|
78
85
|
@override
|
79
86
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
80
87
|
|
81
88
|
odxassert(decode_state.cursor_bit_position == 0,
|
82
89
|
"No bit position can be specified for static length fields!")
|
83
90
|
|
91
|
+
orig_origin = decode_state.origin_byte_position
|
92
|
+
orig_cursor = decode_state.cursor_byte_position
|
93
|
+
decode_state.origin_byte_position = decode_state.cursor_byte_position
|
94
|
+
|
84
95
|
result: List[ParameterValue] = []
|
85
96
|
for _ in range(self.fixed_number_of_items):
|
86
97
|
orig_cursor = decode_state.cursor_byte_position
|
@@ -94,4 +105,7 @@ class StaticField(Field):
|
|
94
105
|
|
95
106
|
decode_state.cursor_byte_position = orig_cursor + self.item_byte_size
|
96
107
|
|
108
|
+
decode_state.origin_byte_position = orig_origin
|
109
|
+
decode_state.cursor_byte_position = max(orig_cursor, decode_state.cursor_byte_position)
|
110
|
+
|
97
111
|
return result
|
odxtools/tablerow.py
CHANGED
@@ -9,7 +9,7 @@ from .dataobjectproperty import DataObjectProperty
|
|
9
9
|
from .dtcdop import DtcDop
|
10
10
|
from .element import IdentifiableElement
|
11
11
|
from .exceptions import odxassert, odxraise, odxrequire
|
12
|
-
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
12
|
+
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
13
13
|
from .odxtypes import AtomicOdxType
|
14
14
|
from .specialdatagroup import SpecialDataGroup
|
15
15
|
from .utils import dataclass_fields_asdict
|
@@ -128,9 +128,11 @@ class TableRow(IdentifiableElement):
|
|
128
128
|
ddd_spec = diag_layer.diag_data_dictionary_spec
|
129
129
|
|
130
130
|
if self.structure_snref is not None:
|
131
|
-
self._structure =
|
131
|
+
self._structure = resolve_snref(self.structure_snref, ddd_spec.structures,
|
132
|
+
BasicStructure)
|
132
133
|
if self.dop_snref is not None:
|
133
|
-
self._dop =
|
134
|
+
self._dop = resolve_snref(self.dop_snref, ddd_spec.data_object_props,
|
135
|
+
DataObjectProperty)
|
134
136
|
|
135
137
|
for sdg in self.sdgs:
|
136
138
|
sdg._resolve_snrefs(diag_layer)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
-#}
|
5
|
+
|
6
|
+
{%- import('macros/printElementId.xml.jinja2') as peid %}
|
7
|
+
|
8
|
+
{%- macro printStaticField(demf) -%}
|
9
|
+
<DYNAMIC-ENDMARKER-FIELD ID="{{demf.odx_id.local_id}}">
|
10
|
+
{{ peid.printElementIdSubtags(demf)|indent(1) }}
|
11
|
+
<BASIC-STRUCTURE-REF ID-REF="{{demf.structure_ref.ref_id}}" />
|
12
|
+
<DYN-END-DOP-REF ID-REF="{{demf.dyn_end_dop_ref.ref_id}}">
|
13
|
+
<TERMINATION-VALUE>{{demf.dyn_end_dop_ref.termination_value_raw}}</TERMINATION-VALUE>
|
14
|
+
</DYN-END-DOP-REF>
|
15
|
+
</DYNAMIC-ENDMARKER-FIELD>
|
16
|
+
{%- endmacro -%}
|
@@ -11,6 +11,7 @@
|
|
11
11
|
{%- import('macros/printEndOfPdu.xml.jinja2') as peopdu %}
|
12
12
|
{%- import('macros/printStaticField.xml.jinja2') as psf %}
|
13
13
|
{%- import('macros/printDynamicLengthField.xml.jinja2') as pdlf %}
|
14
|
+
{%- import('macros/printDynamicEndmarkerField.xml.jinja2') as pdemf %}
|
14
15
|
{%- import('macros/printMux.xml.jinja2') as pm %}
|
15
16
|
{%- import('macros/printEnvData.xml.jinja2') as ped %}
|
16
17
|
{%- import('macros/printEnvDataDesc.xml.jinja2') as pedd %}
|
@@ -82,6 +83,13 @@
|
|
82
83
|
{%- endfor %}
|
83
84
|
</DYNAMIC-LENGTH-FIELDS>
|
84
85
|
{%- endif %}
|
86
|
+
{%- if ddds.dynamic_endmarker_fields %}
|
87
|
+
<DYNAMIC-ENDMARKER-FIELDS>
|
88
|
+
{%- for demf in ddds.dynamic_endmarker_fields %}
|
89
|
+
{{ pdemf.printDynamicEndmarkerField(demf)|indent(3) }}
|
90
|
+
{%- endfor %}
|
91
|
+
</DYNAMIC-ENDMARKER-FIELDS>
|
92
|
+
{%- endif %}
|
85
93
|
{%- if ddds.end_of_pdu_fields %}
|
86
94
|
<END-OF-PDU-FIELDS>
|
87
95
|
{%- for eopdu in ddds.end_of_pdu_fields %}
|
odxtools/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: odxtools
|
3
|
-
Version: 7.
|
3
|
+
Version: 7.1.1
|
4
4
|
Summary: Utilities to work with the ODX standard for automotive diagnostics
|
5
5
|
Author-email: Katrin Bauer <katrin.bauer@mbition.io>, Andreas Lauser <andreas.lauser@mbition.io>, Ayoub Kaanich <kayoub5@live.com>
|
6
6
|
Maintainer-email: Andreas Lauser <andreas.lauser@mbition.io>, Ayoub Kaanich <kayoub5@live.com>
|