odxtools 6.6.1__py3-none-any.whl → 9.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 +7 -5
- odxtools/additionalaudience.py +3 -5
- odxtools/admindata.py +5 -7
- odxtools/audience.py +10 -13
- odxtools/basecomparam.py +3 -5
- odxtools/basicstructure.py +55 -241
- odxtools/cli/_parser_utils.py +16 -1
- odxtools/cli/_print_utils.py +169 -134
- odxtools/cli/browse.py +127 -103
- odxtools/cli/compare.py +114 -87
- odxtools/cli/decode.py +2 -1
- odxtools/cli/dummy_sub_parser.py +3 -1
- odxtools/cli/find.py +2 -1
- odxtools/cli/list.py +26 -16
- odxtools/cli/main.py +1 -0
- odxtools/cli/snoop.py +32 -6
- odxtools/codec.py +211 -0
- odxtools/commrelation.py +122 -0
- 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 +14 -14
- odxtools/comparamspec.py +16 -54
- odxtools/comparamsubset.py +22 -62
- odxtools/complexcomparam.py +5 -7
- odxtools/compumethods/compucodecompumethod.py +63 -0
- odxtools/compumethods/compuconst.py +31 -0
- odxtools/compumethods/compudefaultvalue.py +27 -0
- odxtools/compumethods/compuinternaltophys.py +56 -0
- odxtools/compumethods/compuinversevalue.py +7 -0
- odxtools/compumethods/compumethod.py +94 -15
- odxtools/compumethods/compuphystointernal.py +56 -0
- odxtools/compumethods/compurationalcoeffs.py +20 -9
- odxtools/compumethods/compuscale.py +67 -32
- odxtools/compumethods/createanycompumethod.py +31 -172
- odxtools/compumethods/identicalcompumethod.py +31 -6
- odxtools/compumethods/limit.py +70 -36
- odxtools/compumethods/linearcompumethod.py +70 -181
- odxtools/compumethods/linearsegment.py +190 -0
- odxtools/compumethods/ratfunccompumethod.py +106 -0
- odxtools/compumethods/ratfuncsegment.py +87 -0
- odxtools/compumethods/scalelinearcompumethod.py +132 -26
- odxtools/compumethods/scaleratfunccompumethod.py +113 -0
- odxtools/compumethods/tabintpcompumethod.py +123 -92
- odxtools/compumethods/texttablecompumethod.py +117 -57
- odxtools/createanydiagcodedtype.py +10 -67
- odxtools/database.py +167 -87
- odxtools/dataobjectproperty.py +25 -32
- odxtools/decodestate.py +14 -17
- odxtools/description.py +47 -0
- odxtools/determinenumberofitems.py +4 -5
- odxtools/diagcodedtype.py +37 -106
- odxtools/diagcomm.py +24 -12
- odxtools/diagdatadictionaryspec.py +120 -96
- odxtools/diaglayercontainer.py +46 -54
- odxtools/diaglayers/basevariant.py +128 -0
- odxtools/diaglayers/basevariantraw.py +123 -0
- odxtools/diaglayers/diaglayer.py +432 -0
- odxtools/{diaglayerraw.py → diaglayers/diaglayerraw.py} +105 -120
- odxtools/diaglayers/diaglayertype.py +42 -0
- odxtools/diaglayers/ecushareddata.py +96 -0
- odxtools/diaglayers/ecushareddataraw.py +87 -0
- odxtools/diaglayers/ecuvariant.py +124 -0
- odxtools/diaglayers/ecuvariantraw.py +129 -0
- odxtools/diaglayers/functionalgroup.py +110 -0
- odxtools/diaglayers/functionalgroupraw.py +106 -0
- odxtools/{diaglayer.py → diaglayers/hierarchyelement.py} +273 -472
- odxtools/diaglayers/hierarchyelementraw.py +58 -0
- odxtools/diaglayers/protocol.py +64 -0
- odxtools/diaglayers/protocolraw.py +91 -0
- odxtools/diagnostictroublecode.py +8 -9
- odxtools/diagservice.py +57 -44
- odxtools/diagvariable.py +113 -0
- odxtools/docrevision.py +5 -7
- odxtools/dopbase.py +15 -15
- odxtools/dtcdop.py +170 -50
- odxtools/dynamicendmarkerfield.py +134 -0
- odxtools/dynamiclengthfield.py +47 -42
- odxtools/dyndefinedspec.py +177 -0
- odxtools/dynenddopref.py +38 -0
- odxtools/ecuvariantmatcher.py +6 -7
- odxtools/element.py +13 -15
- odxtools/encodestate.py +199 -22
- odxtools/endofpdufield.py +31 -18
- odxtools/environmentdata.py +8 -1
- odxtools/environmentdatadescription.py +198 -36
- odxtools/exceptions.py +11 -2
- odxtools/field.py +10 -10
- odxtools/functionalclass.py +3 -5
- odxtools/inputparam.py +3 -12
- odxtools/internalconstr.py +14 -5
- odxtools/isotp_state_machine.py +14 -6
- odxtools/leadinglengthinfotype.py +37 -18
- odxtools/library.py +66 -0
- odxtools/loadfile.py +64 -0
- odxtools/matchingparameter.py +3 -3
- odxtools/message.py +0 -7
- odxtools/minmaxlengthtype.py +61 -33
- odxtools/modification.py +3 -5
- odxtools/multiplexer.py +135 -75
- odxtools/multiplexercase.py +39 -18
- odxtools/multiplexerdefaultcase.py +15 -12
- odxtools/multiplexerswitchkey.py +4 -5
- odxtools/nameditemlist.py +33 -8
- odxtools/negoutputparam.py +3 -5
- odxtools/odxcategory.py +83 -0
- odxtools/odxlink.py +62 -53
- odxtools/odxtypes.py +93 -8
- odxtools/outputparam.py +5 -16
- odxtools/parameterinfo.py +219 -61
- odxtools/parameters/codedconstparameter.py +45 -32
- odxtools/parameters/createanyparameter.py +19 -193
- odxtools/parameters/dynamicparameter.py +25 -4
- odxtools/parameters/lengthkeyparameter.py +83 -25
- odxtools/parameters/matchingrequestparameter.py +48 -18
- odxtools/parameters/nrcconstparameter.py +76 -54
- odxtools/parameters/parameter.py +97 -73
- odxtools/parameters/parameterwithdop.py +41 -38
- odxtools/parameters/physicalconstantparameter.py +41 -20
- odxtools/parameters/reservedparameter.py +36 -18
- odxtools/parameters/systemparameter.py +74 -7
- odxtools/parameters/tableentryparameter.py +47 -7
- odxtools/parameters/tablekeyparameter.py +142 -55
- odxtools/parameters/tablestructparameter.py +79 -58
- odxtools/parameters/valueparameter.py +39 -21
- odxtools/paramlengthinfotype.py +56 -33
- odxtools/parentref.py +20 -3
- odxtools/physicaldimension.py +3 -8
- odxtools/progcode.py +26 -11
- odxtools/protstack.py +3 -5
- odxtools/py.typed +0 -0
- odxtools/relateddoc.py +7 -9
- odxtools/request.py +120 -10
- odxtools/response.py +123 -23
- odxtools/scaleconstr.py +14 -8
- odxtools/servicebinner.py +1 -1
- odxtools/singleecujob.py +12 -10
- odxtools/snrefcontext.py +29 -0
- odxtools/specialdata.py +3 -5
- odxtools/specialdatagroup.py +7 -9
- odxtools/specialdatagroupcaption.py +3 -6
- odxtools/standardlengthtype.py +80 -14
- odxtools/state.py +3 -5
- odxtools/statechart.py +13 -19
- odxtools/statetransition.py +8 -18
- odxtools/staticfield.py +107 -0
- odxtools/subcomponent.py +288 -0
- odxtools/swvariable.py +21 -0
- odxtools/table.py +9 -9
- odxtools/tablerow.py +30 -15
- odxtools/teammember.py +3 -5
- odxtools/templates/comparam-spec.odx-c.xml.jinja2 +4 -24
- odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +5 -26
- odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +15 -31
- odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +1 -1
- odxtools/templates/macros/printAudience.xml.jinja2 +1 -1
- odxtools/templates/macros/printBaseVariant.xml.jinja2 +53 -0
- odxtools/templates/macros/printCompanyData.xml.jinja2 +4 -7
- odxtools/templates/macros/printComparam.xml.jinja2 +6 -4
- odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
- odxtools/templates/macros/printCompuMethod.xml.jinja2 +147 -0
- odxtools/templates/macros/printDOP.xml.jinja2 +27 -137
- odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
- odxtools/templates/macros/printDiagComm.xml.jinja2 +1 -1
- odxtools/templates/macros/printDiagLayer.xml.jinja2 +222 -0
- odxtools/templates/macros/printDiagVariable.xml.jinja2 +66 -0
- odxtools/templates/macros/printDynDefinedSpec.xml.jinja2 +48 -0
- odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +16 -0
- odxtools/templates/macros/printDynamicLengthField.xml.jinja2 +1 -1
- odxtools/templates/macros/printEcuSharedData.xml.jinja2 +30 -0
- odxtools/templates/macros/printEcuVariant.xml.jinja2 +53 -0
- odxtools/templates/macros/printEcuVariantPattern.xml.jinja2 +1 -1
- odxtools/templates/macros/printElementId.xml.jinja2 +8 -3
- odxtools/templates/macros/printEndOfPdu.xml.jinja2 +1 -1
- odxtools/templates/macros/printEnvDataDesc.xml.jinja2 +1 -1
- odxtools/templates/macros/printFunctionalClass.xml.jinja2 +1 -1
- odxtools/templates/macros/printFunctionalGroup.xml.jinja2 +40 -0
- odxtools/templates/macros/printHierarchyElement.xml.jinja2 +24 -0
- odxtools/templates/macros/printLibrary.xml.jinja2 +21 -0
- odxtools/templates/macros/printMux.xml.jinja2 +5 -3
- odxtools/templates/macros/printOdxCategory.xml.jinja2 +28 -0
- odxtools/templates/macros/printParam.xml.jinja2 +18 -19
- odxtools/templates/macros/printProtStack.xml.jinja2 +1 -1
- odxtools/templates/macros/printProtocol.xml.jinja2 +30 -0
- odxtools/templates/macros/printRequest.xml.jinja2 +1 -1
- odxtools/templates/macros/printResponse.xml.jinja2 +1 -1
- odxtools/templates/macros/printService.xml.jinja2 +3 -2
- odxtools/templates/macros/printSingleEcuJob.xml.jinja2 +5 -26
- odxtools/templates/macros/printSpecialData.xml.jinja2 +1 -1
- odxtools/templates/macros/printState.xml.jinja2 +1 -1
- odxtools/templates/macros/printStateChart.xml.jinja2 +1 -1
- odxtools/templates/macros/printStateTransition.xml.jinja2 +1 -1
- odxtools/templates/macros/printStaticField.xml.jinja2 +15 -0
- odxtools/templates/macros/printStructure.xml.jinja2 +1 -1
- odxtools/templates/macros/printSubComponent.xml.jinja2 +104 -0
- odxtools/templates/macros/printTable.xml.jinja2 +4 -5
- odxtools/templates/macros/printUnitSpec.xml.jinja2 +3 -5
- odxtools/uds.py +2 -10
- odxtools/unit.py +4 -8
- odxtools/unitgroup.py +3 -5
- odxtools/unitspec.py +17 -17
- odxtools/utils.py +38 -20
- odxtools/variablegroup.py +32 -0
- odxtools/version.py +2 -2
- odxtools/{write_pdx_file.py → writepdxfile.py} +22 -12
- odxtools/xdoc.py +3 -5
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/METADATA +44 -33
- odxtools-9.3.0.dist-info/RECORD +228 -0
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/WHEEL +1 -1
- odxtools/createcompanydatas.py +0 -17
- odxtools/createsdgs.py +0 -19
- odxtools/diaglayertype.py +0 -30
- odxtools/load_file.py +0 -13
- odxtools/load_odx_d_file.py +0 -6
- odxtools/load_pdx_file.py +0 -8
- odxtools/templates/macros/printVariant.xml.jinja2 +0 -208
- odxtools-6.6.1.dist-info/RECORD +0 -180
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/LICENSE +0 -0
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/entry_points.txt +0 -0
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/top_level.txt +0 -0
@@ -1,19 +1,20 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
import warnings
|
3
2
|
from dataclasses import dataclass
|
4
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional, cast
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from typing_extensions import override
|
5
7
|
|
6
8
|
from ..decodestate import DecodeState
|
7
9
|
from ..encodestate import EncodeState
|
8
|
-
from ..exceptions import EncodeError,
|
9
|
-
from ..odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
10
|
+
from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
11
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
10
12
|
from ..odxtypes import ParameterValue
|
13
|
+
from ..snrefcontext import SnRefContext
|
14
|
+
from ..utils import dataclass_fields_asdict
|
11
15
|
from .parameter import Parameter, ParameterType
|
12
16
|
from .tablekeyparameter import TableKeyParameter
|
13
17
|
|
14
|
-
if TYPE_CHECKING:
|
15
|
-
from ..diaglayer import DiagLayer
|
16
|
-
|
17
18
|
|
18
19
|
@dataclass
|
19
20
|
class TableStructParameter(Parameter):
|
@@ -21,123 +22,146 @@ class TableStructParameter(Parameter):
|
|
21
22
|
table_key_ref: Optional[OdxLinkRef]
|
22
23
|
table_key_snref: Optional[str]
|
23
24
|
|
25
|
+
@staticmethod
|
26
|
+
@override
|
27
|
+
def from_et(et_element: ElementTree.Element,
|
28
|
+
doc_frags: List[OdxDocFragment]) -> "TableStructParameter":
|
29
|
+
|
30
|
+
kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
|
31
|
+
|
32
|
+
table_key_ref = OdxLinkRef.from_et(et_element.find("TABLE-KEY-REF"), doc_frags)
|
33
|
+
table_key_snref = None
|
34
|
+
if (table_key_snref_elem := et_element.find("TABLE-KEY-SNREF")) is not None:
|
35
|
+
table_key_snref = odxrequire(table_key_snref_elem.get("SHORT-NAME"))
|
36
|
+
|
37
|
+
return TableStructParameter(
|
38
|
+
table_key_ref=table_key_ref, table_key_snref=table_key_snref, **kwargs)
|
39
|
+
|
24
40
|
def __post_init__(self) -> None:
|
25
41
|
if self.table_key_ref is None and self.table_key_snref is None:
|
26
42
|
odxraise("Either table_key_ref or table_key_snref must be defined.")
|
27
43
|
|
28
44
|
@property
|
45
|
+
@override
|
29
46
|
def parameter_type(self) -> ParameterType:
|
30
47
|
return "TABLE-STRUCT"
|
31
48
|
|
49
|
+
@override
|
32
50
|
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
33
51
|
return super()._build_odxlinks()
|
34
52
|
|
53
|
+
@override
|
35
54
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
36
55
|
super()._resolve_odxlinks(odxlinks)
|
37
56
|
|
38
57
|
if self.table_key_ref is not None:
|
39
|
-
self._table_key = odxlinks.resolve(self.table_key_ref)
|
58
|
+
self._table_key = odxlinks.resolve(self.table_key_ref, TableKeyParameter)
|
40
59
|
|
41
|
-
|
42
|
-
|
60
|
+
@override
|
61
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
62
|
+
super()._resolve_snrefs(context)
|
43
63
|
|
44
64
|
if self.table_key_snref is not None:
|
45
|
-
|
46
|
-
|
47
|
-
" in TableStructParameters.",
|
48
|
-
OdxWarning,
|
49
|
-
stacklevel=1)
|
65
|
+
self._table_key = resolve_snref(self.table_key_snref, odxrequire(context.parameters),
|
66
|
+
TableKeyParameter)
|
50
67
|
|
51
68
|
@property
|
52
69
|
def table_key(self) -> TableKeyParameter:
|
53
70
|
return self._table_key
|
54
71
|
|
55
72
|
@property
|
73
|
+
@override
|
56
74
|
def is_required(self) -> bool:
|
57
75
|
return True
|
58
76
|
|
59
77
|
@property
|
78
|
+
@override
|
60
79
|
def is_settable(self) -> bool:
|
61
80
|
return True
|
62
81
|
|
63
|
-
|
64
|
-
|
82
|
+
@override
|
83
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
84
|
+
encode_state: EncodeState) -> None:
|
65
85
|
|
66
|
-
if not isinstance(physical_value, tuple) or \
|
86
|
+
if not isinstance(physical_value, (tuple, list)) or \
|
67
87
|
len(physical_value) != 2 or \
|
68
88
|
not isinstance(physical_value[0], str):
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
89
|
+
odxraise(
|
90
|
+
f"The physical value of TableStructParameter 'self.short_name' "
|
91
|
+
f"must be a tuple containing the short name of the selected table "
|
92
|
+
f"row as the first element and the physical value for the "
|
93
|
+
f"row's structure or DOP as the second.", EncodeError)
|
73
94
|
|
74
95
|
tr_short_name = physical_value[0]
|
75
96
|
|
76
97
|
# make sure that the same table row is selected for all
|
77
98
|
# TABLE-STRUCT parameters that are using the same key
|
78
99
|
tk_short_name = self.table_key.short_name
|
79
|
-
tk_value = encode_state.
|
100
|
+
tk_value = encode_state.table_keys.get(tk_short_name)
|
80
101
|
if tk_value is None:
|
81
102
|
# no value for the key has been set yet. Set it to the
|
82
103
|
# value which we are using right now
|
83
|
-
encode_state.
|
104
|
+
encode_state.table_keys[tk_short_name] = tr_short_name
|
84
105
|
elif tk_value != tr_short_name:
|
85
|
-
|
86
|
-
|
106
|
+
odxraise(
|
107
|
+
f"Cannot determine a unique value for table key '{tk_short_name}': "
|
108
|
+
f"Requested are '{tk_value}' and '{tr_short_name}'", EncodeError)
|
109
|
+
return
|
87
110
|
|
88
111
|
# deal with the static case (i.e., the table row is selected
|
89
112
|
# by the table key object itself)
|
90
|
-
if self.table_key.table_row is not None
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
113
|
+
if self.table_key.table_row is not None:
|
114
|
+
if tr_short_name is not None and self.table_key.table_row.short_name != tr_short_name:
|
115
|
+
odxraise(
|
116
|
+
f"The selected table row for the {self.short_name} "
|
117
|
+
f"parameter must be '{self.table_key.table_row.short_name}' "
|
118
|
+
f"instead of '{tr_short_name}'", EncodeError)
|
119
|
+
return
|
120
|
+
|
121
|
+
tr_short_name = self.table_key.table_row.short_name
|
95
122
|
|
96
123
|
# encode the user specified value using the structure (or DOP)
|
97
124
|
# of the selected table row
|
98
125
|
table = self.table_key.table
|
99
126
|
candidate_trs = [tr for tr in table.table_rows if tr.short_name == tr_short_name]
|
100
|
-
if len(candidate_trs)
|
101
|
-
|
102
|
-
|
127
|
+
if len(candidate_trs) == 0:
|
128
|
+
odxraise(
|
129
|
+
f"Could not find a table row named "
|
130
|
+
f"'{tr_short_name}' in table '{table.short_name}'", EncodeError)
|
131
|
+
return
|
132
|
+
elif len(candidate_trs) > 1:
|
133
|
+
odxraise(
|
134
|
+
f"Found multiple table rows named "
|
135
|
+
f"'{tr_short_name}' in table '{table.short_name}'", EncodeError)
|
136
|
+
|
103
137
|
tr = candidate_trs[0]
|
104
138
|
tr_value = physical_value[1]
|
105
139
|
|
106
|
-
bit_position = self.bit_position or 0
|
107
140
|
if tr.structure is not None:
|
108
141
|
# the selected table row references a structure
|
109
|
-
|
110
|
-
|
111
|
-
parameter_values=tr_value,
|
112
|
-
triggering_request=encode_state.triggering_request)
|
113
|
-
|
114
|
-
return tr.structure.convert_physical_to_bytes(
|
115
|
-
tr_value, inner_encode_state, bit_position=bit_position)
|
142
|
+
tr.structure.encode_into_pdu(tr_value, encode_state)
|
143
|
+
return
|
116
144
|
|
117
145
|
# if the table row does not reference a structure, it must
|
118
146
|
# point to a DOP!
|
119
147
|
if tr.dop is None:
|
120
|
-
odxraise(
|
121
|
-
|
122
|
-
|
123
|
-
tr_value, encode_state=encode_state, bit_position=bit_position)
|
124
|
-
|
125
|
-
def encode_into_pdu(self, encode_state: EncodeState) -> bytes:
|
126
|
-
return super().encode_into_pdu(encode_state)
|
148
|
+
odxraise(f"Neither a structure nor a DOP has been defined for table row"
|
149
|
+
f"'{tr.short_name}'")
|
150
|
+
return
|
127
151
|
|
128
|
-
|
129
|
-
orig_cursor = decode_state.cursor_byte_position
|
130
|
-
if self.byte_position is not None:
|
131
|
-
decode_state.cursor_byte_position = decode_state.origin_byte_position + self.byte_position
|
152
|
+
tr.dop.encode_into_pdu(tr_value, encode_state)
|
132
153
|
|
154
|
+
@override
|
155
|
+
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
133
156
|
# find the selected table row
|
134
157
|
key_name = self.table_key.short_name
|
135
158
|
|
136
159
|
decode_state.table_keys[key_name]
|
137
160
|
table_row = decode_state.table_keys.get(key_name)
|
138
161
|
if table_row is None:
|
139
|
-
|
140
|
-
|
162
|
+
odxraise(
|
163
|
+
f"No table key '{key_name}' found when decoding "
|
164
|
+
f"table struct parameter '{str(self.short_name)}'", DecodeError)
|
141
165
|
dummy_val = cast(str, None), cast(int, None)
|
142
166
|
return dummy_val
|
143
167
|
|
@@ -145,14 +169,11 @@ class TableStructParameter(Parameter):
|
|
145
169
|
if table_row.dop is not None:
|
146
170
|
dop = table_row.dop
|
147
171
|
val = dop.decode_from_pdu(decode_state)
|
148
|
-
decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
|
149
172
|
return (table_row.short_name, val)
|
150
173
|
elif table_row.structure is not None:
|
151
174
|
val = table_row.structure.decode_from_pdu(decode_state)
|
152
|
-
decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
|
153
175
|
return (table_row.short_name, val)
|
154
176
|
else:
|
155
177
|
# the table row associated with the key neither defines a
|
156
178
|
# DOP nor a structure -> ignore it
|
157
|
-
decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
|
158
179
|
return (table_row.short_name, cast(int, None))
|
@@ -1,18 +1,20 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from typing_extensions import override
|
4
7
|
|
5
8
|
from ..dataobjectproperty import DataObjectProperty
|
6
9
|
from ..encodestate import EncodeState
|
7
|
-
from ..exceptions import odxraise, odxrequire
|
8
|
-
from ..odxlink import OdxLinkDatabase, OdxLinkId
|
9
|
-
from ..odxtypes import AtomicOdxType
|
10
|
+
from ..exceptions import EncodeError, odxraise, odxrequire
|
11
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
12
|
+
from ..odxtypes import AtomicOdxType, ParameterValue
|
13
|
+
from ..snrefcontext import SnRefContext
|
14
|
+
from ..utils import dataclass_fields_asdict
|
10
15
|
from .parameter import ParameterType
|
11
16
|
from .parameterwithdop import ParameterWithDOP
|
12
17
|
|
13
|
-
if TYPE_CHECKING:
|
14
|
-
from ..diaglayer import DiagLayer
|
15
|
-
|
16
18
|
|
17
19
|
@dataclass
|
18
20
|
class ValueParameter(ParameterWithDOP):
|
@@ -21,18 +23,33 @@ class ValueParameter(ParameterWithDOP):
|
|
21
23
|
def __post_init__(self) -> None:
|
22
24
|
self._physical_default_value: Optional[AtomicOdxType] = None
|
23
25
|
|
26
|
+
@staticmethod
|
27
|
+
@override
|
28
|
+
def from_et(et_element: ElementTree.Element,
|
29
|
+
doc_frags: List[OdxDocFragment]) -> "ValueParameter":
|
30
|
+
|
31
|
+
kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
|
32
|
+
|
33
|
+
physical_default_value_raw = et_element.findtext("PHYSICAL-DEFAULT-VALUE")
|
34
|
+
|
35
|
+
return ValueParameter(physical_default_value_raw=physical_default_value_raw, **kwargs)
|
36
|
+
|
24
37
|
@property
|
38
|
+
@override
|
25
39
|
def parameter_type(self) -> ParameterType:
|
26
40
|
return "VALUE"
|
27
41
|
|
42
|
+
@override
|
28
43
|
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
29
44
|
return super()._build_odxlinks()
|
30
45
|
|
46
|
+
@override
|
31
47
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
32
48
|
super()._resolve_odxlinks(odxlinks)
|
33
49
|
|
34
|
-
|
35
|
-
|
50
|
+
@override
|
51
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
52
|
+
super()._resolve_snrefs(context)
|
36
53
|
|
37
54
|
if self.physical_default_value_raw is not None:
|
38
55
|
dop = odxrequire(self.dop)
|
@@ -48,23 +65,24 @@ class ValueParameter(ParameterWithDOP):
|
|
48
65
|
return self._physical_default_value
|
49
66
|
|
50
67
|
@property
|
68
|
+
@override
|
51
69
|
def is_required(self) -> bool:
|
52
70
|
return self._physical_default_value is None
|
53
71
|
|
54
72
|
@property
|
73
|
+
@override
|
55
74
|
def is_settable(self) -> bool:
|
56
75
|
return True
|
57
76
|
|
58
|
-
|
59
|
-
|
60
|
-
|
77
|
+
@override
|
78
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
79
|
+
encode_state: EncodeState) -> None:
|
80
|
+
|
61
81
|
if physical_value is None:
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
return dop.convert_physical_to_bytes(
|
70
|
-
physical_value, encode_state=encode_state, bit_position=bit_position_int)
|
82
|
+
physical_value = self._physical_default_value
|
83
|
+
if physical_value is None:
|
84
|
+
odxraise(
|
85
|
+
f"A value for parameter '{self.short_name}' must be specified"
|
86
|
+
f" because the parameter does not exhibit a default.", EncodeError)
|
87
|
+
|
88
|
+
self.dop.encode_into_pdu(physical_value, encode_state=encode_state)
|
odxtools/paramlengthinfotype.py
CHANGED
@@ -1,28 +1,46 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, Any, Dict, cast
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, cast
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from typing_extensions import override
|
4
7
|
|
5
8
|
from .decodestate import DecodeState
|
6
9
|
from .diagcodedtype import DctType, DiagCodedType
|
7
10
|
from .encodestate import EncodeState
|
8
|
-
from .exceptions import odxraise
|
9
|
-
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
11
|
+
from .exceptions import EncodeError, odxraise, odxrequire
|
12
|
+
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
10
13
|
from .odxtypes import AtomicOdxType, DataType
|
14
|
+
from .snrefcontext import SnRefContext
|
15
|
+
from .utils import dataclass_fields_asdict
|
11
16
|
|
12
17
|
if TYPE_CHECKING:
|
13
|
-
from .diaglayer import DiagLayer
|
14
18
|
from .parameters.lengthkeyparameter import LengthKeyParameter
|
15
19
|
|
16
20
|
|
17
21
|
@dataclass
|
18
22
|
class ParamLengthInfoType(DiagCodedType):
|
19
|
-
|
20
23
|
length_key_ref: OdxLinkRef
|
21
24
|
|
22
25
|
@property
|
23
26
|
def dct_type(self) -> DctType:
|
24
27
|
return "PARAM-LENGTH-INFO-TYPE"
|
25
28
|
|
29
|
+
@property
|
30
|
+
def length_key(self) -> "LengthKeyParameter":
|
31
|
+
return self._length_key
|
32
|
+
|
33
|
+
@staticmethod
|
34
|
+
@override
|
35
|
+
def from_et(et_element: ElementTree.Element,
|
36
|
+
doc_frags: List[OdxDocFragment]) -> "ParamLengthInfoType":
|
37
|
+
kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, doc_frags))
|
38
|
+
|
39
|
+
length_key_ref = odxrequire(
|
40
|
+
OdxLinkRef.from_et(et_element.find("LENGTH-KEY-REF"), doc_frags))
|
41
|
+
|
42
|
+
return ParamLengthInfoType(length_key_ref=length_key_ref, **kwargs)
|
43
|
+
|
26
44
|
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
27
45
|
return super()._build_odxlinks()
|
28
46
|
|
@@ -30,45 +48,52 @@ class ParamLengthInfoType(DiagCodedType):
|
|
30
48
|
"""Recursively resolve any odxlinks references"""
|
31
49
|
super()._resolve_odxlinks(odxlinks)
|
32
50
|
|
33
|
-
|
51
|
+
if TYPE_CHECKING:
|
52
|
+
self._length_key = odxlinks.resolve(self.length_key_ref, LengthKeyParameter)
|
53
|
+
else:
|
54
|
+
self._length_key = odxlinks.resolve(self.length_key_ref)
|
34
55
|
|
35
|
-
def _resolve_snrefs(self,
|
56
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
36
57
|
"""Recursively resolve any short-name references"""
|
37
|
-
super()._resolve_snrefs(
|
58
|
+
super()._resolve_snrefs(context)
|
38
59
|
|
39
|
-
@
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
def convert_internal_to_bytes(self, internal_value: AtomicOdxType, encode_state: EncodeState,
|
44
|
-
bit_position: int) -> bytes:
|
45
|
-
bit_length = encode_state.parameter_values.get(self.length_key.short_name, None)
|
60
|
+
@override
|
61
|
+
def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
|
62
|
+
bit_length = encode_state.length_keys.get(self.length_key.short_name)
|
46
63
|
|
47
64
|
if bit_length is None:
|
65
|
+
# the length key is implicit, i.e., we need to set the
|
66
|
+
# value for the length key in the encode_state based on
|
67
|
+
# the value passed here.
|
48
68
|
if self.base_data_type in [
|
49
69
|
DataType.A_BYTEFIELD,
|
50
70
|
DataType.A_ASCIISTRING,
|
51
71
|
DataType.A_UTF8STRING,
|
52
72
|
]:
|
53
|
-
bit_length = 8 * len(internal_value)
|
54
|
-
|
55
|
-
bit_length = 16 * len(internal_value)
|
56
|
-
|
57
|
-
if self.base_data_type in [DataType.A_INT32, DataType.A_UINT32]:
|
73
|
+
bit_length = 8 * len(cast(str, internal_value))
|
74
|
+
elif self.base_data_type in [DataType.A_UNICODE2STRING]:
|
75
|
+
bit_length = 16 * len(cast(str, internal_value))
|
76
|
+
elif self.base_data_type in [DataType.A_INT32, DataType.A_UINT32]:
|
58
77
|
bit_length = int(internal_value).bit_length()
|
59
78
|
if self.base_data_type == DataType.A_INT32:
|
60
79
|
bit_length += 1
|
61
80
|
# Round up
|
62
81
|
bit_length = ((bit_length + 7) // 8) * 8
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
82
|
+
elif self.base_data_type == DataType.A_FLOAT32:
|
83
|
+
bit_length = 32
|
84
|
+
elif self.base_data_type == DataType.A_FLOAT64:
|
85
|
+
bit_length = 64
|
86
|
+
else:
|
87
|
+
odxraise(
|
88
|
+
f"Cannot determine size of an object of type "
|
89
|
+
f"{self.base_data_type.value}", EncodeError)
|
90
|
+
return
|
91
|
+
|
92
|
+
encode_state.length_keys[self.length_key.short_name] = bit_length
|
93
|
+
|
94
|
+
encode_state.emplace_atomic_value(
|
95
|
+
internal_value=internal_value,
|
96
|
+
used_mask=None,
|
72
97
|
bit_length=bit_length,
|
73
98
|
base_data_type=self.base_data_type,
|
74
99
|
is_highlow_byte_order=self.is_highlow_byte_order,
|
@@ -79,7 +104,7 @@ class ParamLengthInfoType(DiagCodedType):
|
|
79
104
|
if self.length_key.short_name not in decode_state.length_keys:
|
80
105
|
odxraise(f"Unspecified mandatory length key parameter "
|
81
106
|
f"{self.length_key.short_name}")
|
82
|
-
decode_state.cursor_bit_position =
|
107
|
+
decode_state.cursor_bit_position = 0
|
83
108
|
return cast(None, AtomicOdxType)
|
84
109
|
|
85
110
|
bit_length = decode_state.length_keys[self.length_key.short_name]
|
@@ -88,10 +113,8 @@ class ParamLengthInfoType(DiagCodedType):
|
|
88
113
|
bit_length = 0
|
89
114
|
|
90
115
|
# Extract the internal value and return.
|
91
|
-
|
116
|
+
return decode_state.extract_atomic_value(
|
92
117
|
bit_length,
|
93
118
|
self.base_data_type,
|
94
119
|
self.is_highlow_byte_order,
|
95
120
|
)
|
96
|
-
|
97
|
-
return value
|
odxtools/parentref.py
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
+
from copy import deepcopy
|
2
3
|
from dataclasses import dataclass
|
3
4
|
from typing import TYPE_CHECKING, Any, Dict, List
|
4
5
|
from xml.etree import ElementTree
|
5
6
|
|
6
7
|
from .exceptions import odxrequire
|
7
8
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
9
|
+
from .snrefcontext import SnRefContext
|
10
|
+
from .utils import dataclass_fields_asdict
|
8
11
|
|
9
12
|
if TYPE_CHECKING:
|
10
|
-
from .diaglayer import DiagLayer
|
13
|
+
from .diaglayers.diaglayer import DiagLayer
|
11
14
|
|
12
15
|
|
13
16
|
@dataclass
|
@@ -71,7 +74,21 @@ class ParentRef:
|
|
71
74
|
return {}
|
72
75
|
|
73
76
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
74
|
-
|
77
|
+
if TYPE_CHECKING:
|
78
|
+
self._layer = odxlinks.resolve(self.layer_ref, DiagLayer)
|
79
|
+
else:
|
80
|
+
self._layer = odxlinks.resolve(self.layer_ref)
|
75
81
|
|
76
|
-
def _resolve_snrefs(self,
|
82
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
77
83
|
pass
|
84
|
+
|
85
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
|
86
|
+
cls = self.__class__
|
87
|
+
result = cls.__new__(cls)
|
88
|
+
memo[id(self)] = result
|
89
|
+
|
90
|
+
fields = dataclass_fields_asdict(self)
|
91
|
+
for name, value in fields.items():
|
92
|
+
setattr(result, name, deepcopy(value))
|
93
|
+
|
94
|
+
return result
|
odxtools/physicaldimension.py
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Dict, List
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .element import IdentifiableElement
|
7
7
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
8
|
+
from .snrefcontext import SnRefContext
|
8
9
|
from .utils import dataclass_fields_asdict
|
9
10
|
|
10
|
-
if TYPE_CHECKING:
|
11
|
-
from .diaglayer import DiagLayer
|
12
|
-
|
13
11
|
|
14
12
|
@dataclass
|
15
13
|
class PhysicalDimension(IdentifiableElement):
|
@@ -43,7 +41,6 @@ class PhysicalDimension(IdentifiableElement):
|
|
43
41
|
)
|
44
42
|
```
|
45
43
|
"""
|
46
|
-
oid: Optional[str]
|
47
44
|
length_exp: int
|
48
45
|
mass_exp: int
|
49
46
|
time_exp: int
|
@@ -56,7 +53,6 @@ class PhysicalDimension(IdentifiableElement):
|
|
56
53
|
def from_et(et_element: ElementTree.Element,
|
57
54
|
doc_frags: List[OdxDocFragment]) -> "PhysicalDimension":
|
58
55
|
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
|
59
|
-
oid = et_element.get("OID")
|
60
56
|
|
61
57
|
def read_optional_int(element: ElementTree.Element, name: str) -> int:
|
62
58
|
if val_str := element.findtext(name):
|
@@ -73,7 +69,6 @@ class PhysicalDimension(IdentifiableElement):
|
|
73
69
|
luminous_intensity_exp = read_optional_int(et_element, "LUMINOUS-INTENSITY-EXP")
|
74
70
|
|
75
71
|
return PhysicalDimension(
|
76
|
-
oid=oid,
|
77
72
|
length_exp=length_exp,
|
78
73
|
mass_exp=mass_exp,
|
79
74
|
time_exp=time_exp,
|
@@ -89,5 +84,5 @@ class PhysicalDimension(IdentifiableElement):
|
|
89
84
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
90
85
|
pass
|
91
86
|
|
92
|
-
def _resolve_snrefs(self,
|
87
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
93
88
|
pass
|
odxtools/progcode.py
CHANGED
@@ -1,25 +1,33 @@
|
|
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
|
-
from .exceptions import odxrequire
|
6
|
+
from .exceptions import odxraise, odxrequire
|
7
|
+
from .library import Library
|
8
|
+
from .nameditemlist import NamedItemList
|
7
9
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
8
|
-
|
9
|
-
if TYPE_CHECKING:
|
10
|
-
from .diaglayer import DiagLayer
|
10
|
+
from .snrefcontext import SnRefContext
|
11
11
|
|
12
12
|
|
13
13
|
@dataclass
|
14
14
|
class ProgCode:
|
15
15
|
"""A reference to code that is executed by a single ECU job"""
|
16
16
|
code_file: str
|
17
|
+
encryption: Optional[str]
|
17
18
|
syntax: str
|
18
19
|
revision: str
|
19
|
-
encryption: Optional[str]
|
20
20
|
entrypoint: Optional[str]
|
21
21
|
library_refs: List[OdxLinkRef]
|
22
22
|
|
23
|
+
@property
|
24
|
+
def code(self) -> bytes:
|
25
|
+
return self._code
|
26
|
+
|
27
|
+
@property
|
28
|
+
def libraries(self) -> NamedItemList[Library]:
|
29
|
+
return self._libraries
|
30
|
+
|
23
31
|
@staticmethod
|
24
32
|
def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "ProgCode":
|
25
33
|
code_file = odxrequire(et_element.findtext("CODE-FILE"))
|
@@ -47,9 +55,16 @@ class ProgCode:
|
|
47
55
|
return {}
|
48
56
|
|
49
57
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
self._libraries = NamedItemList([odxlinks.resolve(x, Library) for x in self.library_refs])
|
59
|
+
|
60
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
61
|
+
aux_file = odxrequire(context.database).auxiliary_files.get(self.code_file)
|
62
|
+
|
63
|
+
if aux_file is None:
|
64
|
+
odxraise(f"Reference to auxiliary file '{self.code_file}' "
|
65
|
+
f"could not be resolved")
|
66
|
+
self._code: bytes = cast(bytes, None)
|
67
|
+
return
|
53
68
|
|
54
|
-
|
55
|
-
|
69
|
+
self._code = aux_file.read()
|
70
|
+
aux_file.seek(0)
|
odxtools/protstack.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
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .comparamsubset import ComparamSubset
|
@@ -8,11 +8,9 @@ from .element import IdentifiableElement
|
|
8
8
|
from .exceptions import odxrequire
|
9
9
|
from .nameditemlist import NamedItemList
|
10
10
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
11
|
+
from .snrefcontext import SnRefContext
|
11
12
|
from .utils import dataclass_fields_asdict
|
12
13
|
|
13
|
-
if TYPE_CHECKING:
|
14
|
-
from .diaglayer import DiagLayer
|
15
|
-
|
16
14
|
|
17
15
|
@dataclass
|
18
16
|
class ProtStack(IdentifiableElement):
|
@@ -47,7 +45,7 @@ class ProtStack(IdentifiableElement):
|
|
47
45
|
self._comparam_subsets = NamedItemList[ComparamSubset](
|
48
46
|
[odxlinks.resolve(x, ComparamSubset) for x in self.comparam_subset_refs])
|
49
47
|
|
50
|
-
def _resolve_snrefs(self,
|
48
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
51
49
|
pass
|
52
50
|
|
53
51
|
@property
|
odxtools/py.typed
ADDED
File without changes
|