odxtools 9.7.0__py3-none-any.whl → 10.1.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/additionalaudience.py +7 -7
- odxtools/admindata.py +14 -13
- odxtools/audience.py +17 -17
- odxtools/basecomparam.py +9 -8
- odxtools/basevariantpattern.py +9 -10
- odxtools/basicstructure.py +15 -15
- odxtools/cli/_print_utils.py +34 -22
- odxtools/cli/browse.py +8 -8
- odxtools/cli/compare.py +24 -24
- odxtools/cli/decode.py +3 -4
- odxtools/cli/find.py +4 -5
- odxtools/cli/list.py +6 -6
- odxtools/cli/main.py +2 -2
- odxtools/cli/snoop.py +3 -3
- odxtools/codec.py +3 -3
- odxtools/commrelation.py +18 -17
- odxtools/companydata.py +13 -13
- odxtools/companydocinfo.py +15 -17
- odxtools/companyrevisioninfo.py +9 -9
- odxtools/companyspecificinfo.py +11 -13
- odxtools/comparam.py +8 -7
- odxtools/comparaminstance.py +14 -14
- odxtools/comparamspec.py +10 -11
- odxtools/comparamsubset.py +17 -25
- odxtools/complexcomparam.py +14 -14
- odxtools/complexdop.py +1 -1
- odxtools/compositecodec.py +8 -8
- odxtools/compumethods/compucodecompumethod.py +7 -7
- odxtools/compumethods/compuconst.py +5 -6
- odxtools/compumethods/compudefaultvalue.py +2 -3
- odxtools/compumethods/compuinternaltophys.py +13 -12
- odxtools/compumethods/compumethod.py +10 -9
- odxtools/compumethods/compuphystointernal.py +13 -12
- odxtools/compumethods/compurationalcoeffs.py +7 -7
- odxtools/compumethods/compuscale.py +15 -16
- odxtools/compumethods/createanycompumethod.py +12 -13
- odxtools/compumethods/identicalcompumethod.py +4 -5
- odxtools/compumethods/limit.py +14 -14
- odxtools/compumethods/linearcompumethod.py +5 -5
- odxtools/compumethods/linearsegment.py +10 -11
- odxtools/compumethods/ratfunccompumethod.py +6 -6
- odxtools/compumethods/ratfuncsegment.py +7 -8
- odxtools/compumethods/scalelinearcompumethod.py +9 -9
- odxtools/compumethods/scaleratfunccompumethod.py +7 -7
- odxtools/compumethods/tabintpcompumethod.py +10 -13
- odxtools/compumethods/texttablecompumethod.py +6 -6
- odxtools/createanycomparam.py +5 -7
- odxtools/createanydiagcodedtype.py +7 -8
- odxtools/database.py +34 -31
- odxtools/dataobjectproperty.py +19 -20
- odxtools/decodestate.py +5 -5
- odxtools/description.py +9 -9
- odxtools/determinenumberofitems.py +8 -7
- odxtools/diagcodedtype.py +10 -10
- odxtools/diagcomm.py +29 -30
- odxtools/diagdatadictionaryspec.py +36 -36
- odxtools/diaglayercontainer.py +35 -34
- odxtools/diaglayers/basevariant.py +14 -12
- odxtools/diaglayers/basevariantraw.py +22 -23
- odxtools/diaglayers/diaglayer.py +24 -22
- odxtools/diaglayers/diaglayerraw.py +43 -52
- odxtools/diaglayers/diaglayertype.py +1 -2
- odxtools/diaglayers/ecushareddata.py +9 -9
- odxtools/diaglayers/ecushareddataraw.py +15 -16
- odxtools/diaglayers/ecuvariant.py +15 -13
- odxtools/diaglayers/ecuvariantraw.py +21 -22
- odxtools/diaglayers/functionalgroup.py +12 -11
- odxtools/diaglayers/functionalgroupraw.py +17 -18
- odxtools/diaglayers/hierarchyelement.py +48 -54
- odxtools/diaglayers/hierarchyelementraw.py +10 -11
- odxtools/diaglayers/protocol.py +7 -7
- odxtools/diaglayers/protocolraw.py +13 -14
- odxtools/diagnostictroublecode.py +15 -17
- odxtools/diagservice.py +28 -27
- odxtools/diagvariable.py +24 -25
- odxtools/docrevision.py +18 -17
- odxtools/dopbase.py +13 -14
- odxtools/dtcconnector.py +8 -7
- odxtools/dtcdop.py +24 -20
- odxtools/dynamicendmarkerfield.py +10 -9
- odxtools/dynamiclengthfield.py +10 -9
- odxtools/dyndefinedspec.py +10 -10
- odxtools/dynenddopref.py +9 -9
- odxtools/dyniddefmodeinfo.py +21 -21
- odxtools/ecuvariantpattern.py +8 -10
- odxtools/element.py +12 -13
- odxtools/encodestate.py +11 -11
- odxtools/encoding.py +2 -3
- odxtools/endofpdufield.py +9 -10
- odxtools/envdataconnector.py +8 -8
- odxtools/environmentdata.py +7 -9
- odxtools/environmentdatadescription.py +18 -17
- odxtools/exceptions.py +5 -5
- odxtools/externalaccessmethod.py +4 -6
- odxtools/externaldoc.py +6 -6
- odxtools/field.py +15 -15
- odxtools/functionalclass.py +9 -9
- odxtools/inputparam.py +11 -10
- odxtools/internalconstr.py +10 -11
- odxtools/isotp_state_machine.py +12 -11
- odxtools/leadinglengthinfotype.py +4 -6
- odxtools/library.py +9 -8
- odxtools/linkeddtcdop.py +9 -8
- odxtools/loadfile.py +5 -6
- odxtools/matchingbasevariantparameter.py +5 -6
- odxtools/matchingparameter.py +10 -10
- odxtools/message.py +1 -1
- odxtools/minmaxlengthtype.py +6 -7
- odxtools/modification.py +7 -6
- odxtools/multiplexer.py +54 -18
- odxtools/multiplexercase.py +13 -13
- odxtools/multiplexerdefaultcase.py +11 -10
- odxtools/multiplexerswitchkey.py +8 -8
- odxtools/nameditemlist.py +13 -13
- odxtools/negoutputparam.py +8 -8
- odxtools/obd.py +1 -2
- odxtools/odxcategory.py +14 -26
- odxtools/odxdoccontext.py +16 -0
- odxtools/odxlink.py +23 -25
- odxtools/odxtypes.py +18 -15
- odxtools/outputparam.py +9 -8
- odxtools/parameterinfo.py +1 -1
- odxtools/parameters/codedconstparameter.py +10 -10
- odxtools/parameters/createanyparameter.py +15 -16
- odxtools/parameters/dynamicparameter.py +5 -7
- odxtools/parameters/lengthkeyparameter.py +10 -10
- odxtools/parameters/matchingrequestparameter.py +6 -7
- odxtools/parameters/nrcconstparameter.py +13 -13
- odxtools/parameters/parameter.py +17 -18
- odxtools/parameters/parameterwithdop.py +13 -13
- odxtools/parameters/physicalconstantparameter.py +8 -7
- odxtools/parameters/reservedparameter.py +6 -8
- odxtools/parameters/systemparameter.py +5 -7
- odxtools/parameters/tableentryparameter.py +8 -8
- odxtools/parameters/tablekeyparameter.py +17 -17
- odxtools/parameters/tablestructparameter.py +11 -11
- odxtools/parameters/valueparameter.py +11 -11
- odxtools/paramlengthinfotype.py +10 -9
- odxtools/parentref.py +15 -13
- odxtools/physicaldimension.py +15 -15
- odxtools/physicaltype.py +5 -6
- odxtools/posresponsesuppressible.py +11 -12
- odxtools/preconditionstateref.py +11 -11
- odxtools/progcode.py +11 -10
- odxtools/protstack.py +10 -9
- odxtools/relateddiagcommref.py +5 -6
- odxtools/relateddoc.py +11 -10
- odxtools/request.py +18 -19
- odxtools/response.py +19 -20
- odxtools/scaleconstr.py +8 -9
- odxtools/servicebinner.py +5 -5
- odxtools/singleecujob.py +16 -15
- odxtools/snrefcontext.py +3 -3
- odxtools/specialdata.py +8 -7
- odxtools/specialdatagroup.py +17 -17
- odxtools/specialdatagroupcaption.py +7 -6
- odxtools/standardlengthtype.py +14 -22
- odxtools/state.py +7 -6
- odxtools/statechart.py +12 -11
- odxtools/statemachine.py +4 -3
- odxtools/statetransition.py +9 -9
- odxtools/statetransitionref.py +19 -19
- odxtools/staticfield.py +9 -7
- odxtools/structure.py +5 -6
- odxtools/subcomponent.py +20 -18
- odxtools/subcomponentparamconnector.py +10 -9
- odxtools/subcomponentpattern.py +9 -9
- odxtools/swvariable.py +6 -7
- odxtools/table.py +25 -26
- odxtools/tablediagcommconnector.py +9 -8
- odxtools/tablerow.py +64 -43
- odxtools/tablerowconnector.py +8 -8
- odxtools/teammember.py +16 -15
- odxtools/templates/macros/printParentRef.xml.jinja2 +3 -1
- odxtools/text.py +4 -5
- odxtools/uds.py +2 -3
- odxtools/unit.py +14 -13
- odxtools/unitgroup.py +11 -10
- odxtools/unitspec.py +18 -19
- odxtools/utils.py +3 -3
- odxtools/variablegroup.py +5 -6
- odxtools/variantmatcher.py +10 -10
- odxtools/variantpattern.py +5 -6
- odxtools/version.py +2 -2
- odxtools/writepdxfile.py +5 -24
- odxtools/xdoc.py +13 -12
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/METADATA +4 -5
- odxtools-10.1.0.dist-info/RECORD +265 -0
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/WHEEL +1 -1
- odxtools-9.7.0.dist-info/RECORD +0 -264
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/entry_points.txt +0 -0
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/licenses/LICENSE +0 -0
- {odxtools-9.7.0.dist-info → odxtools-10.1.0.dist-info}/top_level.txt +0 -0
odxtools/request.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
3
|
-
from typing import Any,
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any, cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .admindata import AdminData
|
@@ -14,7 +14,8 @@ from .element import IdentifiableElement
|
|
14
14
|
from .encodestate import EncodeState
|
15
15
|
from .exceptions import odxraise
|
16
16
|
from .nameditemlist import NamedItemList
|
17
|
-
from .
|
17
|
+
from .odxdoccontext import OdxDocContext
|
18
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
18
19
|
from .odxtypes import ParameterValue, ParameterValueDict
|
19
20
|
from .parameters.createanyparameter import create_any_parameter_from_et
|
20
21
|
from .parameters.parameter import Parameter
|
@@ -23,40 +24,38 @@ from .specialdatagroup import SpecialDataGroup
|
|
23
24
|
from .utils import dataclass_fields_asdict
|
24
25
|
|
25
26
|
|
26
|
-
@dataclass
|
27
|
+
@dataclass(kw_only=True)
|
27
28
|
class Request(IdentifiableElement):
|
28
29
|
"""Represents all information related to an UDS request
|
29
30
|
|
30
31
|
This class implements the `CompositeCodec` interface.
|
31
32
|
"""
|
32
|
-
admin_data:
|
33
|
-
parameters: NamedItemList[Parameter]
|
34
|
-
sdgs:
|
33
|
+
admin_data: AdminData | None = None
|
34
|
+
parameters: NamedItemList[Parameter] = field(default_factory=NamedItemList)
|
35
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
35
36
|
|
36
37
|
@property
|
37
|
-
def required_parameters(self) ->
|
38
|
+
def required_parameters(self) -> list[Parameter]:
|
38
39
|
return composite_codec_get_required_parameters(self)
|
39
40
|
|
40
41
|
@property
|
41
|
-
def free_parameters(self) ->
|
42
|
+
def free_parameters(self) -> list[Parameter]:
|
42
43
|
return composite_codec_get_free_parameters(self)
|
43
44
|
|
44
45
|
@staticmethod
|
45
|
-
def from_et(et_element: ElementTree.Element,
|
46
|
-
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element,
|
46
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Request":
|
47
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
47
48
|
|
48
|
-
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"),
|
49
|
+
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), context)
|
49
50
|
parameters = NamedItemList([
|
50
|
-
create_any_parameter_from_et(et_parameter,
|
51
|
+
create_any_parameter_from_et(et_parameter, context)
|
51
52
|
for et_parameter in et_element.iterfind("PARAMS/PARAM")
|
52
53
|
])
|
53
|
-
sdgs = [
|
54
|
-
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
55
|
-
]
|
54
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
56
55
|
|
57
56
|
return Request(admin_data=admin_data, parameters=parameters, sdgs=sdgs, **kwargs)
|
58
57
|
|
59
|
-
def _build_odxlinks(self) ->
|
58
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
60
59
|
result = {self.odx_id: self}
|
61
60
|
|
62
61
|
if self.admin_data is not None:
|
@@ -96,7 +95,7 @@ class Request(IdentifiableElement):
|
|
96
95
|
context.request = None
|
97
96
|
context.parameters = None
|
98
97
|
|
99
|
-
def get_static_bit_length(self) ->
|
98
|
+
def get_static_bit_length(self) -> int | None:
|
100
99
|
return composite_codec_get_static_bit_length(self)
|
101
100
|
|
102
101
|
def print_free_parameters_info(self) -> None:
|
@@ -123,7 +122,7 @@ class Request(IdentifiableElement):
|
|
123
122
|
|
124
123
|
return cast(ParameterValueDict, param_values)
|
125
124
|
|
126
|
-
def encode_into_pdu(self, physical_value:
|
125
|
+
def encode_into_pdu(self, physical_value: ParameterValue | None,
|
127
126
|
encode_state: EncodeState) -> None:
|
128
127
|
composite_codec_encode_into_pdu(self, physical_value, encode_state)
|
129
128
|
|
odxtools/response.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
2
|
+
from dataclasses import dataclass, field
|
3
3
|
from enum import Enum
|
4
|
-
from typing import Any,
|
4
|
+
from typing import Any, cast
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .admindata import AdminData
|
@@ -15,7 +15,8 @@ from .element import IdentifiableElement
|
|
15
15
|
from .encodestate import EncodeState
|
16
16
|
from .exceptions import odxraise
|
17
17
|
from .nameditemlist import NamedItemList
|
18
|
-
from .
|
18
|
+
from .odxdoccontext import OdxDocContext
|
19
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
19
20
|
from .odxtypes import ParameterValue, ParameterValueDict
|
20
21
|
from .parameters.createanyparameter import create_any_parameter_from_et
|
21
22
|
from .parameters.parameter import Parameter
|
@@ -30,7 +31,7 @@ class ResponseType(Enum):
|
|
30
31
|
GLOBAL_NEGATIVE = "GLOBAL-NEG-RESPONSE"
|
31
32
|
|
32
33
|
|
33
|
-
@dataclass
|
34
|
+
@dataclass(kw_only=True)
|
34
35
|
class Response(IdentifiableElement):
|
35
36
|
"""Represents all information related to an UDS response
|
36
37
|
|
@@ -39,14 +40,14 @@ class Response(IdentifiableElement):
|
|
39
40
|
|
40
41
|
response_type: ResponseType
|
41
42
|
|
42
|
-
admin_data:
|
43
|
-
parameters: NamedItemList[Parameter]
|
44
|
-
sdgs:
|
43
|
+
admin_data: AdminData | None = None
|
44
|
+
parameters: NamedItemList[Parameter] = field(default_factory=NamedItemList)
|
45
|
+
sdgs: list[SpecialDataGroup] = field(default_factory=list)
|
45
46
|
|
46
47
|
@staticmethod
|
47
|
-
def from_et(et_element: ElementTree.Element,
|
48
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "Response":
|
48
49
|
"""Reads a response."""
|
49
|
-
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element,
|
50
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
50
51
|
|
51
52
|
try:
|
52
53
|
response_type = ResponseType(et_element.tag)
|
@@ -54,14 +55,12 @@ class Response(IdentifiableElement):
|
|
54
55
|
response_type = cast(ResponseType, None)
|
55
56
|
odxraise(f"Encountered unknown response type '{et_element.tag}'")
|
56
57
|
|
57
|
-
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"),
|
58
|
+
admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), context)
|
58
59
|
parameters = NamedItemList([
|
59
|
-
create_any_parameter_from_et(et_parameter,
|
60
|
+
create_any_parameter_from_et(et_parameter, context)
|
60
61
|
for et_parameter in et_element.iterfind("PARAMS/PARAM")
|
61
62
|
])
|
62
|
-
sdgs = [
|
63
|
-
SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
|
64
|
-
]
|
63
|
+
sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
|
65
64
|
|
66
65
|
return Response(
|
67
66
|
response_type=response_type,
|
@@ -70,7 +69,7 @@ class Response(IdentifiableElement):
|
|
70
69
|
sdgs=sdgs,
|
71
70
|
**kwargs)
|
72
71
|
|
73
|
-
def _build_odxlinks(self) ->
|
72
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
74
73
|
result = {self.odx_id: self}
|
75
74
|
|
76
75
|
if self.admin_data is not None:
|
@@ -110,7 +109,7 @@ class Response(IdentifiableElement):
|
|
110
109
|
context.response = None
|
111
110
|
context.parameters = None
|
112
111
|
|
113
|
-
def encode(self, coded_request:
|
112
|
+
def encode(self, coded_request: bytes | None = None, **kwargs: ParameterValue) -> bytearray:
|
114
113
|
encode_state = EncodeState(triggering_request=coded_request, is_end_of_pdu=True)
|
115
114
|
|
116
115
|
self.encode_into_pdu(physical_value=kwargs, encode_state=encode_state)
|
@@ -126,22 +125,22 @@ class Response(IdentifiableElement):
|
|
126
125
|
|
127
126
|
return cast(ParameterValueDict, param_values)
|
128
127
|
|
129
|
-
def encode_into_pdu(self, physical_value:
|
128
|
+
def encode_into_pdu(self, physical_value: ParameterValue | None,
|
130
129
|
encode_state: EncodeState) -> None:
|
131
130
|
composite_codec_encode_into_pdu(self, physical_value, encode_state)
|
132
131
|
|
133
132
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
134
133
|
return composite_codec_decode_from_pdu(self, decode_state)
|
135
134
|
|
136
|
-
def get_static_bit_length(self) ->
|
135
|
+
def get_static_bit_length(self) -> int | None:
|
137
136
|
return composite_codec_get_static_bit_length(self)
|
138
137
|
|
139
138
|
@property
|
140
|
-
def required_parameters(self) ->
|
139
|
+
def required_parameters(self) -> list[Parameter]:
|
141
140
|
return composite_codec_get_required_parameters(self)
|
142
141
|
|
143
142
|
@property
|
144
|
-
def free_parameters(self) ->
|
143
|
+
def free_parameters(self) -> list[Parameter]:
|
145
144
|
return composite_codec_get_free_parameters(self)
|
146
145
|
|
147
146
|
def print_free_parameters_info(self) -> None:
|
odxtools/scaleconstr.py
CHANGED
@@ -1,37 +1,36 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import List, Optional
|
4
3
|
from xml.etree import ElementTree
|
5
4
|
|
6
5
|
from .compumethods.limit import Limit
|
7
6
|
from .description import Description
|
8
7
|
from .exceptions import odxraise, odxrequire
|
9
|
-
from .
|
8
|
+
from .odxdoccontext import OdxDocContext
|
10
9
|
from .odxtypes import DataType
|
11
10
|
from .validtype import ValidType
|
12
11
|
|
13
12
|
|
14
|
-
@dataclass
|
13
|
+
@dataclass(kw_only=True)
|
15
14
|
class ScaleConstr:
|
16
15
|
"""This class represents a SCALE-CONSTR.
|
17
16
|
"""
|
18
17
|
|
19
|
-
short_label:
|
20
|
-
description:
|
18
|
+
short_label: str | None = None
|
19
|
+
description: Description | None = None
|
21
20
|
lower_limit: Limit
|
22
21
|
upper_limit: Limit
|
23
22
|
validity: ValidType
|
24
23
|
value_type: DataType
|
25
24
|
|
26
25
|
@staticmethod
|
27
|
-
def scale_constr_from_et(et_element: ElementTree.Element,
|
26
|
+
def scale_constr_from_et(et_element: ElementTree.Element, context: OdxDocContext, *,
|
28
27
|
value_type: DataType) -> "ScaleConstr":
|
29
28
|
short_label = et_element.findtext("SHORT-LABEL")
|
30
|
-
description = Description.from_et(et_element.find("DESC"),
|
29
|
+
description = Description.from_et(et_element.find("DESC"), context)
|
31
30
|
lower_limit = Limit.limit_from_et(
|
32
|
-
odxrequire(et_element.find("LOWER-LIMIT")),
|
31
|
+
odxrequire(et_element.find("LOWER-LIMIT")), context, value_type=value_type)
|
33
32
|
upper_limit = Limit.limit_from_et(
|
34
|
-
odxrequire(et_element.find("UPPER-LIMIT")),
|
33
|
+
odxrequire(et_element.find("UPPER-LIMIT")), context, value_type=value_type)
|
35
34
|
|
36
35
|
validity_str = odxrequire(et_element.get("VALIDITY"))
|
37
36
|
try:
|
odxtools/servicebinner.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
+
from collections.abc import Iterable, Iterator
|
2
3
|
from io import StringIO
|
3
|
-
from typing import Dict, Iterable, Iterator, Optional
|
4
4
|
|
5
5
|
from . import obd, uds
|
6
6
|
from .diagservice import DiagService
|
@@ -21,7 +21,7 @@ class ServiceBinner:
|
|
21
21
|
"""
|
22
22
|
|
23
23
|
def __init__(self, services: Iterable[DiagService]):
|
24
|
-
service_groups:
|
24
|
+
service_groups: dict[int | None, NamedItemList[DiagService]] = {}
|
25
25
|
for service in services:
|
26
26
|
SID = self.__extract_sid(service)
|
27
27
|
|
@@ -32,7 +32,7 @@ class ServiceBinner:
|
|
32
32
|
|
33
33
|
self._service_groups = service_groups
|
34
34
|
|
35
|
-
def __extract_sid(self, service: DiagService) ->
|
35
|
+
def __extract_sid(self, service: DiagService) -> int | None:
|
36
36
|
# diagnostic services without requests are possible; just like
|
37
37
|
# aircraft without wings...
|
38
38
|
if service.request is None:
|
@@ -96,10 +96,10 @@ class ServiceBinner:
|
|
96
96
|
|
97
97
|
return result.getvalue()
|
98
98
|
|
99
|
-
def __iter__(self) -> Iterator[
|
99
|
+
def __iter__(self) -> Iterator[int | None]:
|
100
100
|
return iter(self._service_groups)
|
101
101
|
|
102
|
-
def __getitem__(self, sid:
|
102
|
+
def __getitem__(self, sid: int | None) -> NamedItemList[DiagService]:
|
103
103
|
if sid is None:
|
104
104
|
return self._service_groups.get(sid, NamedItemList())
|
105
105
|
|
odxtools/singleecujob.py
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .diagcomm import DiagComm
|
7
7
|
from .inputparam import InputParam
|
8
8
|
from .nameditemlist import NamedItemList
|
9
9
|
from .negoutputparam import NegOutputParam
|
10
|
-
from .
|
10
|
+
from .odxdoccontext import OdxDocContext
|
11
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
11
12
|
from .outputparam import OutputParam
|
12
13
|
from .progcode import ProgCode
|
13
14
|
from .snrefcontext import SnRefContext
|
14
15
|
from .utils import dataclass_fields_asdict
|
15
16
|
|
16
17
|
|
17
|
-
@dataclass
|
18
|
+
@dataclass(kw_only=True)
|
18
19
|
class SingleEcuJob(DiagComm):
|
19
20
|
"""A single ECU job is a diagnostic communication primitive.
|
20
21
|
|
@@ -30,30 +31,30 @@ class SingleEcuJob(DiagComm):
|
|
30
31
|
standard.
|
31
32
|
"""
|
32
33
|
|
33
|
-
prog_codes:
|
34
|
-
input_params: NamedItemList[InputParam]
|
35
|
-
output_params: NamedItemList[OutputParam]
|
36
|
-
neg_output_params: NamedItemList[NegOutputParam]
|
34
|
+
prog_codes: list[ProgCode] = field(default_factory=list)
|
35
|
+
input_params: NamedItemList[InputParam] = field(default_factory=NamedItemList)
|
36
|
+
output_params: NamedItemList[OutputParam] = field(default_factory=NamedItemList)
|
37
|
+
neg_output_params: NamedItemList[NegOutputParam] = field(default_factory=NamedItemList)
|
37
38
|
|
38
39
|
@staticmethod
|
39
|
-
def from_et(et_element: ElementTree.Element,
|
40
|
-
kwargs = dataclass_fields_asdict(DiagComm.from_et(et_element,
|
40
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SingleEcuJob":
|
41
|
+
kwargs = dataclass_fields_asdict(DiagComm.from_et(et_element, context))
|
41
42
|
|
42
43
|
prog_codes = [
|
43
|
-
ProgCode.from_et(pc_elem,
|
44
|
+
ProgCode.from_et(pc_elem, context)
|
44
45
|
for pc_elem in et_element.iterfind("PROG-CODES/PROG-CODE")
|
45
46
|
]
|
46
47
|
|
47
48
|
input_params = NamedItemList([
|
48
|
-
InputParam.from_et(el,
|
49
|
+
InputParam.from_et(el, context)
|
49
50
|
for el in et_element.iterfind("INPUT-PARAMS/INPUT-PARAM")
|
50
51
|
])
|
51
52
|
output_params = NamedItemList([
|
52
|
-
OutputParam.from_et(el,
|
53
|
+
OutputParam.from_et(el, context)
|
53
54
|
for el in et_element.iterfind("OUTPUT-PARAMS/OUTPUT-PARAM")
|
54
55
|
])
|
55
56
|
neg_output_params = NamedItemList([
|
56
|
-
NegOutputParam.from_et(el,
|
57
|
+
NegOutputParam.from_et(el, context)
|
57
58
|
for el in et_element.iterfind("NEG-OUTPUT-PARAMS/NEG-OUTPUT-PARAM")
|
58
59
|
])
|
59
60
|
|
@@ -64,7 +65,7 @@ class SingleEcuJob(DiagComm):
|
|
64
65
|
neg_output_params=neg_output_params,
|
65
66
|
**kwargs)
|
66
67
|
|
67
|
-
def _build_odxlinks(self) ->
|
68
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
68
69
|
result = super()._build_odxlinks()
|
69
70
|
|
70
71
|
for prog_code in self.prog_codes:
|
odxtools/snrefcontext.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING,
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
4
4
|
|
5
5
|
if TYPE_CHECKING:
|
6
6
|
from .database import Database
|
@@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
|
13
13
|
from .statechart import StateChart
|
14
14
|
|
15
15
|
|
16
|
-
@dataclass
|
16
|
+
@dataclass(kw_only=True)
|
17
17
|
class SnRefContext:
|
18
18
|
"""Represents the context for which a short name reference ought
|
19
19
|
to be resolved
|
@@ -25,5 +25,5 @@ class SnRefContext:
|
|
25
25
|
single_ecu_job: Optional["SingleEcuJob"] = None
|
26
26
|
request: Optional["Request"] = None
|
27
27
|
response: Optional["Response"] = None
|
28
|
-
parameters:
|
28
|
+
parameters: list["Parameter"] | None = None
|
29
29
|
state_chart: Optional["StateChart"] = None
|
odxtools/specialdata.py
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
-
from .
|
6
|
+
from .odxdoccontext import OdxDocContext
|
7
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
7
8
|
from .snrefcontext import SnRefContext
|
8
9
|
|
9
10
|
|
10
|
-
@dataclass
|
11
|
+
@dataclass(kw_only=True)
|
11
12
|
class SpecialData:
|
12
13
|
"""This corresponds to the SD XML tag"""
|
13
|
-
semantic_info:
|
14
|
-
text_identifier:
|
14
|
+
semantic_info: str | None = None # the "SI" attribute
|
15
|
+
text_identifier: str | None = None # the "TI" attribute, specifies the language used
|
15
16
|
value: str
|
16
17
|
|
17
18
|
@staticmethod
|
18
|
-
def from_et(et_element: ElementTree.Element,
|
19
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SpecialData":
|
19
20
|
semantic_info = et_element.get("SI")
|
20
21
|
text_identifier = et_element.get("TI")
|
21
22
|
value = et_element.text or ""
|
@@ -23,7 +24,7 @@ class SpecialData:
|
|
23
24
|
return SpecialData(
|
24
25
|
semantic_info=semantic_info, text_identifier=text_identifier, value=value)
|
25
26
|
|
26
|
-
def _build_odxlinks(self) ->
|
27
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
27
28
|
return {}
|
28
29
|
|
29
30
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
odxtools/specialdatagroup.py
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
3
|
-
from typing import Any,
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any, Union
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
-
from .
|
6
|
+
from .odxdoccontext import OdxDocContext
|
7
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
7
8
|
from .snrefcontext import SnRefContext
|
8
9
|
from .specialdata import SpecialData
|
9
10
|
from .specialdatagroupcaption import SpecialDataGroupCaption
|
10
11
|
|
11
12
|
|
12
|
-
@dataclass
|
13
|
+
@dataclass(kw_only=True)
|
13
14
|
class SpecialDataGroup:
|
14
15
|
"""This corresponds to the SDG XML tag"""
|
15
|
-
sdg_caption:
|
16
|
-
sdg_caption_ref:
|
17
|
-
values:
|
18
|
-
semantic_info:
|
16
|
+
sdg_caption: SpecialDataGroupCaption | None = None
|
17
|
+
sdg_caption_ref: OdxLinkRef | None = None
|
18
|
+
values: list[Union["SpecialDataGroup", SpecialData]] = field(default_factory=list)
|
19
|
+
semantic_info: str | None = None # the "SI" attribute
|
19
20
|
|
20
21
|
@staticmethod
|
21
|
-
def from_et(et_element: ElementTree.Element,
|
22
|
-
doc_frags: List[OdxDocFragment]) -> "SpecialDataGroup":
|
22
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "SpecialDataGroup":
|
23
23
|
|
24
24
|
sdg_caption = None
|
25
25
|
if caption_elem := et_element.find("SDG-CAPTION"):
|
26
|
-
sdg_caption = SpecialDataGroupCaption.from_et(caption_elem,
|
26
|
+
sdg_caption = SpecialDataGroupCaption.from_et(caption_elem, context)
|
27
27
|
|
28
28
|
sdg_caption_ref = None
|
29
29
|
if (caption_ref_elem := et_element.find("SDG-CAPTION-REF")) is not None:
|
30
|
-
sdg_caption_ref = OdxLinkRef.from_et(caption_ref_elem,
|
30
|
+
sdg_caption_ref = OdxLinkRef.from_et(caption_ref_elem, context)
|
31
31
|
|
32
32
|
semantic_info = et_element.get("SI")
|
33
33
|
|
34
|
-
values:
|
34
|
+
values: list[SpecialData | SpecialDataGroup] = []
|
35
35
|
for value_elem in et_element:
|
36
|
-
next_entry:
|
36
|
+
next_entry: SpecialData | SpecialDataGroup | None = None
|
37
37
|
if value_elem.tag == "SDG":
|
38
|
-
next_entry = SpecialDataGroup.from_et(value_elem,
|
38
|
+
next_entry = SpecialDataGroup.from_et(value_elem, context)
|
39
39
|
elif value_elem.tag == "SD":
|
40
|
-
next_entry = SpecialData.from_et(value_elem,
|
40
|
+
next_entry = SpecialData.from_et(value_elem, context)
|
41
41
|
|
42
42
|
if next_entry is not None:
|
43
43
|
values.append(next_entry)
|
@@ -49,7 +49,7 @@ class SpecialDataGroup:
|
|
49
49
|
values=values,
|
50
50
|
)
|
51
51
|
|
52
|
-
def _build_odxlinks(self) ->
|
52
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
53
53
|
result = {}
|
54
54
|
|
55
55
|
if self.sdg_caption_ref is None and self.sdg_caption is not None:
|
@@ -1,25 +1,26 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .element import IdentifiableElement
|
7
|
-
from .
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
8
9
|
from .snrefcontext import SnRefContext
|
9
10
|
from .utils import dataclass_fields_asdict
|
10
11
|
|
11
12
|
|
12
|
-
@dataclass
|
13
|
+
@dataclass(kw_only=True)
|
13
14
|
class SpecialDataGroupCaption(IdentifiableElement):
|
14
15
|
|
15
16
|
@staticmethod
|
16
17
|
def from_et(et_element: ElementTree.Element,
|
17
|
-
|
18
|
-
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element,
|
18
|
+
context: OdxDocContext) -> "SpecialDataGroupCaption":
|
19
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
19
20
|
|
20
21
|
return SpecialDataGroupCaption(**kwargs)
|
21
22
|
|
22
|
-
def _build_odxlinks(self) ->
|
23
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
23
24
|
result = {self.odx_id: self}
|
24
25
|
|
25
26
|
result[self.odx_id] = self
|
odxtools/standardlengthtype.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 Literal
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -9,17 +9,17 @@ from .decodestate import DecodeState
|
|
9
9
|
from .diagcodedtype import DctType, DiagCodedType
|
10
10
|
from .encodestate import EncodeState
|
11
11
|
from .exceptions import odxassert, odxraise, odxrequire
|
12
|
-
from .
|
12
|
+
from .odxdoccontext import OdxDocContext
|
13
13
|
from .odxtypes import AtomicOdxType, BytesTypes, DataType, odxstr_to_bool
|
14
14
|
from .utils import dataclass_fields_asdict, read_hex_binary
|
15
15
|
|
16
16
|
|
17
|
-
@dataclass
|
17
|
+
@dataclass(kw_only=True)
|
18
18
|
class StandardLengthType(DiagCodedType):
|
19
19
|
|
20
20
|
bit_length: int
|
21
|
-
bit_mask:
|
22
|
-
is_condensed_raw:
|
21
|
+
bit_mask: int | None = None
|
22
|
+
is_condensed_raw: bool | None = None
|
23
23
|
|
24
24
|
@property
|
25
25
|
def dct_type(self) -> DctType:
|
@@ -31,9 +31,8 @@ class StandardLengthType(DiagCodedType):
|
|
31
31
|
|
32
32
|
@staticmethod
|
33
33
|
@override
|
34
|
-
def from_et(et_element: ElementTree.Element,
|
35
|
-
|
36
|
-
kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, doc_frags))
|
34
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "StandardLengthType":
|
35
|
+
kwargs = dataclass_fields_asdict(DiagCodedType.from_et(et_element, context))
|
37
36
|
|
38
37
|
bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
|
39
38
|
bit_mask = read_hex_binary(et_element.find("BIT-MASK"))
|
@@ -50,7 +49,7 @@ class StandardLengthType(DiagCodedType):
|
|
50
49
|
'Can not apply a bit_mask on a value of type {self.base_data_type}',
|
51
50
|
)
|
52
51
|
|
53
|
-
def __get_used_mask(self, internal_value: AtomicOdxType) ->
|
52
|
+
def __get_used_mask(self, internal_value: AtomicOdxType) -> bytes | None:
|
54
53
|
"""Returns a byte field where all bits that are used by the
|
55
54
|
DiagCoded type are set and all unused ones are not set.
|
56
55
|
|
@@ -72,11 +71,7 @@ class StandardLengthType(DiagCodedType):
|
|
72
71
|
if self.is_condensed:
|
73
72
|
# if a condensed bitmask is specified, the number of bits
|
74
73
|
# set to one in the bit mask are used in the PDU
|
75
|
-
|
76
|
-
# TODO: this is pretty slow. replace it by
|
77
|
-
# `self.bit_mask.bit_count()` once we require python >=
|
78
|
-
# 3.10.
|
79
|
-
bit_sz = bin(self.bit_mask).count("1")
|
74
|
+
bit_sz = self.bit_mask.bit_count()
|
80
75
|
used_mask = (1 << bit_sz) - 1
|
81
76
|
|
82
77
|
return used_mask.to_bytes((bit_sz + 7) // 8, endianness)
|
@@ -118,7 +113,7 @@ class StandardLengthType(DiagCodedType):
|
|
118
113
|
mask_bit += 1
|
119
114
|
|
120
115
|
if isinstance(internal_value, BytesTypes):
|
121
|
-
return result.to_bytes(len(internal_value), 'big')
|
116
|
+
return result.to_bytes(len(bytes(internal_value)), 'big')
|
122
117
|
|
123
118
|
return result
|
124
119
|
|
@@ -156,7 +151,7 @@ class StandardLengthType(DiagCodedType):
|
|
156
151
|
mask_bit += 1
|
157
152
|
|
158
153
|
if isinstance(raw_value, BytesTypes):
|
159
|
-
return result.to_bytes(len(raw_value), 'big')
|
154
|
+
return result.to_bytes(len(bytes(raw_value)), 'big')
|
160
155
|
|
161
156
|
return result
|
162
157
|
if isinstance(raw_value, int):
|
@@ -164,17 +159,14 @@ class StandardLengthType(DiagCodedType):
|
|
164
159
|
if isinstance(raw_value, BytesTypes):
|
165
160
|
int_value = int.from_bytes(raw_value, 'big')
|
166
161
|
int_value &= self.bit_mask
|
167
|
-
return int_value.to_bytes(len(raw_value), 'big')
|
162
|
+
return int_value.to_bytes(len(bytes(raw_value)), 'big')
|
168
163
|
|
169
164
|
odxraise(f'Can not apply a bit_mask on a value of type {type(raw_value)}')
|
170
165
|
return raw_value
|
171
166
|
|
172
|
-
def get_static_bit_length(self) ->
|
167
|
+
def get_static_bit_length(self) -> int | None:
|
173
168
|
if self.bit_mask is not None and self.is_condensed:
|
174
|
-
|
175
|
-
# `self.bit_mask.bit_count()` once we require python >=
|
176
|
-
# 3.10.
|
177
|
-
return bin(self.bit_mask).count("1")
|
169
|
+
return self.bit_mask.bit_count()
|
178
170
|
|
179
171
|
return self.bit_length
|
180
172
|
|
odxtools/state.py
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .element import IdentifiableElement
|
7
|
-
from .
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId
|
8
9
|
from .snrefcontext import SnRefContext
|
9
10
|
from .utils import dataclass_fields_asdict
|
10
11
|
|
11
12
|
|
12
|
-
@dataclass
|
13
|
+
@dataclass(kw_only=True)
|
13
14
|
class State(IdentifiableElement):
|
14
15
|
"""
|
15
16
|
Corresponds to STATE.
|
16
17
|
"""
|
17
18
|
|
18
19
|
@staticmethod
|
19
|
-
def from_et(et_element: ElementTree.Element,
|
20
|
-
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element,
|
20
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "State":
|
21
|
+
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
|
21
22
|
|
22
23
|
return State(**kwargs)
|
23
24
|
|
24
|
-
def _build_odxlinks(self) ->
|
25
|
+
def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
|
25
26
|
return {self.odx_id: self}
|
26
27
|
|
27
28
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|