odxtools 10.0.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 +5 -5
- odxtools/admindata.py +10 -9
- odxtools/audience.py +15 -15
- odxtools/basecomparam.py +7 -6
- odxtools/basevariantpattern.py +7 -7
- odxtools/basicstructure.py +9 -9
- odxtools/cli/_print_utils.py +1 -1
- odxtools/cli/browse.py +1 -1
- odxtools/cli/list.py +1 -1
- odxtools/commrelation.py +14 -13
- odxtools/companydata.py +11 -11
- odxtools/companydocinfo.py +11 -13
- odxtools/companyrevisioninfo.py +7 -7
- odxtools/companyspecificinfo.py +9 -11
- odxtools/comparam.py +6 -5
- odxtools/comparaminstance.py +10 -10
- odxtools/comparamspec.py +8 -9
- odxtools/comparamsubset.py +14 -22
- odxtools/complexcomparam.py +10 -10
- odxtools/complexdop.py +1 -1
- odxtools/compositecodec.py +3 -3
- odxtools/compumethods/compucodecompumethod.py +4 -4
- odxtools/compumethods/compuconst.py +3 -3
- odxtools/compumethods/compudefaultvalue.py +2 -2
- odxtools/compumethods/compuinternaltophys.py +11 -10
- odxtools/compumethods/compumethod.py +8 -7
- odxtools/compumethods/compuphystointernal.py +11 -10
- odxtools/compumethods/compurationalcoeffs.py +6 -6
- odxtools/compumethods/compuscale.py +14 -14
- odxtools/compumethods/createanycompumethod.py +12 -12
- odxtools/compumethods/identicalcompumethod.py +4 -4
- odxtools/compumethods/limit.py +8 -8
- odxtools/compumethods/linearcompumethod.py +4 -4
- odxtools/compumethods/linearsegment.py +8 -8
- odxtools/compumethods/ratfunccompumethod.py +4 -4
- odxtools/compumethods/ratfuncsegment.py +8 -8
- odxtools/compumethods/scalelinearcompumethod.py +5 -5
- odxtools/compumethods/scaleratfunccompumethod.py +4 -4
- odxtools/compumethods/tabintpcompumethod.py +12 -12
- odxtools/compumethods/texttablecompumethod.py +4 -4
- odxtools/createanycomparam.py +4 -4
- odxtools/createanydiagcodedtype.py +7 -7
- odxtools/database.py +28 -26
- odxtools/dataobjectproperty.py +15 -16
- odxtools/description.py +7 -7
- odxtools/determinenumberofitems.py +6 -5
- odxtools/diagcodedtype.py +6 -6
- odxtools/diagcomm.py +26 -27
- odxtools/diagdatadictionaryspec.py +34 -34
- odxtools/diaglayercontainer.py +32 -31
- odxtools/diaglayers/basevariant.py +5 -4
- odxtools/diaglayers/basevariantraw.py +18 -19
- odxtools/diaglayers/diaglayer.py +5 -4
- odxtools/diaglayers/diaglayerraw.py +39 -48
- odxtools/diaglayers/ecushareddata.py +6 -6
- odxtools/diaglayers/ecushareddataraw.py +11 -12
- odxtools/diaglayers/ecuvariant.py +5 -4
- odxtools/diaglayers/ecuvariantraw.py +17 -18
- odxtools/diaglayers/functionalgroup.py +5 -5
- odxtools/diaglayers/functionalgroupraw.py +13 -14
- odxtools/diaglayers/hierarchyelement.py +9 -9
- odxtools/diaglayers/hierarchyelementraw.py +8 -9
- odxtools/diaglayers/protocol.py +4 -4
- odxtools/diaglayers/protocolraw.py +10 -11
- odxtools/diagnostictroublecode.py +12 -14
- odxtools/diagservice.py +19 -18
- odxtools/diagvariable.py +19 -20
- odxtools/docrevision.py +14 -13
- odxtools/dopbase.py +10 -11
- odxtools/dtcconnector.py +6 -5
- odxtools/dtcdop.py +15 -15
- odxtools/dynamicendmarkerfield.py +6 -6
- odxtools/dynamiclengthfield.py +6 -6
- odxtools/dyndefinedspec.py +7 -7
- odxtools/dynenddopref.py +7 -7
- odxtools/dyniddefmodeinfo.py +17 -17
- odxtools/ecuvariantpattern.py +6 -7
- odxtools/element.py +12 -12
- odxtools/endofpdufield.py +6 -7
- odxtools/envdataconnector.py +6 -6
- odxtools/environmentdata.py +7 -8
- odxtools/environmentdatadescription.py +13 -12
- odxtools/externalaccessmethod.py +4 -5
- odxtools/externaldoc.py +4 -4
- odxtools/field.py +12 -11
- odxtools/functionalclass.py +7 -7
- odxtools/inputparam.py +9 -8
- odxtools/internalconstr.py +10 -10
- odxtools/leadinglengthinfotype.py +5 -6
- odxtools/library.py +7 -6
- odxtools/linkeddtcdop.py +7 -6
- odxtools/matchingbasevariantparameter.py +5 -5
- odxtools/matchingparameter.py +6 -6
- odxtools/message.py +1 -1
- odxtools/minmaxlengthtype.py +6 -7
- odxtools/modification.py +5 -4
- odxtools/multiplexer.py +48 -12
- odxtools/multiplexercase.py +10 -10
- odxtools/multiplexerdefaultcase.py +8 -7
- odxtools/multiplexerswitchkey.py +6 -6
- odxtools/nameditemlist.py +1 -1
- odxtools/negoutputparam.py +6 -6
- odxtools/odxcategory.py +12 -24
- odxtools/odxdoccontext.py +16 -0
- odxtools/odxlink.py +11 -12
- odxtools/odxtypes.py +3 -3
- odxtools/outputparam.py +7 -6
- odxtools/parameters/codedconstparameter.py +6 -6
- odxtools/parameters/createanyparameter.py +15 -15
- odxtools/parameters/dynamicparameter.py +4 -5
- odxtools/parameters/lengthkeyparameter.py +6 -6
- odxtools/parameters/matchingrequestparameter.py +4 -4
- odxtools/parameters/nrcconstparameter.py +8 -8
- odxtools/parameters/parameter.py +12 -13
- odxtools/parameters/parameterwithdop.py +9 -9
- odxtools/parameters/physicalconstantparameter.py +5 -4
- odxtools/parameters/reservedparameter.py +4 -5
- odxtools/parameters/systemparameter.py +4 -5
- odxtools/parameters/tableentryparameter.py +6 -6
- odxtools/parameters/tablekeyparameter.py +12 -12
- odxtools/parameters/tablestructparameter.py +9 -9
- odxtools/parameters/valueparameter.py +6 -6
- odxtools/paramlengthinfotype.py +6 -7
- odxtools/parentref.py +12 -10
- odxtools/physicaldimension.py +12 -12
- odxtools/physicaltype.py +5 -5
- odxtools/posresponsesuppressible.py +11 -11
- odxtools/preconditionstateref.py +8 -8
- odxtools/progcode.py +9 -8
- odxtools/protstack.py +8 -7
- odxtools/relateddiagcommref.py +5 -5
- odxtools/relateddoc.py +8 -7
- odxtools/request.py +12 -13
- odxtools/response.py +12 -13
- odxtools/scaleconstr.py +8 -8
- odxtools/singleecujob.py +14 -13
- odxtools/snrefcontext.py +1 -1
- odxtools/specialdata.py +6 -5
- odxtools/specialdatagroup.py +13 -13
- odxtools/specialdatagroupcaption.py +5 -4
- odxtools/standardlengthtype.py +5 -13
- odxtools/state.py +5 -4
- odxtools/statechart.py +10 -9
- odxtools/statemachine.py +2 -2
- odxtools/statetransition.py +7 -7
- odxtools/statetransitionref.py +11 -11
- odxtools/staticfield.py +5 -4
- odxtools/structure.py +5 -5
- odxtools/subcomponent.py +18 -16
- odxtools/subcomponentparamconnector.py +8 -7
- odxtools/subcomponentpattern.py +7 -7
- odxtools/swvariable.py +6 -6
- odxtools/table.py +20 -21
- odxtools/tablediagcommconnector.py +7 -6
- odxtools/tablerow.py +57 -36
- odxtools/tablerowconnector.py +6 -6
- odxtools/teammember.py +14 -13
- odxtools/templates/macros/printParentRef.xml.jinja2 +3 -1
- odxtools/text.py +4 -4
- odxtools/unit.py +9 -8
- odxtools/unitgroup.py +9 -8
- odxtools/unitspec.py +15 -16
- odxtools/variablegroup.py +4 -5
- odxtools/variantpattern.py +3 -4
- odxtools/version.py +2 -2
- odxtools/writepdxfile.py +0 -19
- odxtools/xdoc.py +11 -10
- {odxtools-10.0.0.dist-info → odxtools-10.1.0.dist-info}/METADATA +1 -1
- odxtools-10.1.0.dist-info/RECORD +265 -0
- {odxtools-10.0.0.dist-info → odxtools-10.1.0.dist-info}/WHEEL +1 -1
- odxtools-10.0.0.dist-info/RECORD +0 -264
- {odxtools-10.0.0.dist-info → odxtools-10.1.0.dist-info}/entry_points.txt +0 -0
- {odxtools-10.0.0.dist-info → odxtools-10.1.0.dist-info}/licenses/LICENSE +0 -0
- {odxtools-10.0.0.dist-info → odxtools-10.1.0.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ from .compuscale import CompuScale
|
|
7
7
|
from .limit import Limit
|
8
8
|
|
9
9
|
|
10
|
-
@dataclass
|
10
|
+
@dataclass(kw_only=True)
|
11
11
|
class LinearSegment:
|
12
12
|
"""Helper class to represent a segment of a piecewise-linear interpolation.
|
13
13
|
|
@@ -23,8 +23,8 @@ class LinearSegment:
|
|
23
23
|
offset: float
|
24
24
|
factor: float
|
25
25
|
denominator: float
|
26
|
-
internal_lower_limit: Limit | None
|
27
|
-
internal_upper_limit: Limit | None
|
26
|
+
internal_lower_limit: Limit | None = None
|
27
|
+
internal_upper_limit: Limit | None = None
|
28
28
|
|
29
29
|
inverse_value: int | float # value used as inverse if factor is 0
|
30
30
|
|
@@ -54,7 +54,7 @@ class LinearSegment:
|
|
54
54
|
inverse_value: int | float = 0
|
55
55
|
if scale.compu_inverse_value is not None:
|
56
56
|
x = odxrequire(scale.compu_inverse_value).value
|
57
|
-
if not isinstance(x, int
|
57
|
+
if not isinstance(x, (int, float)):
|
58
58
|
odxraise(f"Non-numeric COMPU-INVERSE-VALUE specified ({x!r})")
|
59
59
|
inverse_value = x
|
60
60
|
|
@@ -75,7 +75,7 @@ class LinearSegment:
|
|
75
75
|
self.__compute_physical_limits()
|
76
76
|
|
77
77
|
def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> float | int:
|
78
|
-
if not isinstance(internal_value, int
|
78
|
+
if not isinstance(internal_value, (int, float)):
|
79
79
|
odxraise(f"Internal values of linear compumethods must "
|
80
80
|
f"either be int or float (is: {type(internal_value).__name__})")
|
81
81
|
|
@@ -90,7 +90,7 @@ class LinearSegment:
|
|
90
90
|
return result
|
91
91
|
|
92
92
|
def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> float | int:
|
93
|
-
if not isinstance(physical_value, int
|
93
|
+
if not isinstance(physical_value, (int, float)):
|
94
94
|
odxraise(f"Physical values of linear compumethods must "
|
95
95
|
f"either be int or float (is: {type(physical_value).__name__})")
|
96
96
|
|
@@ -151,7 +151,7 @@ class LinearSegment:
|
|
151
151
|
# Do type checks
|
152
152
|
expected_type = self.physical_type.python_type
|
153
153
|
if issubclass(expected_type, float):
|
154
|
-
if not isinstance(physical_value, int
|
154
|
+
if not isinstance(physical_value, (int, float)):
|
155
155
|
return False
|
156
156
|
else:
|
157
157
|
if not isinstance(physical_value, expected_type):
|
@@ -172,7 +172,7 @@ class LinearSegment:
|
|
172
172
|
# Do type checks
|
173
173
|
expected_type = self.internal_type.python_type
|
174
174
|
if issubclass(expected_type, float):
|
175
|
-
if not isinstance(internal_value, int
|
175
|
+
if not isinstance(internal_value, (int, float)):
|
176
176
|
return False
|
177
177
|
else:
|
178
178
|
if not isinstance(internal_value, expected_type):
|
@@ -4,7 +4,7 @@ from typing import cast
|
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
|
7
|
-
from ..
|
7
|
+
from ..odxdoccontext import OdxDocContext
|
8
8
|
from ..odxtypes import AtomicOdxType, DataType
|
9
9
|
from ..utils import dataclass_fields_asdict
|
10
10
|
from .compucategory import CompuCategory
|
@@ -12,7 +12,7 @@ from .compumethod import CompuMethod
|
|
12
12
|
from .ratfuncsegment import RatFuncSegment
|
13
13
|
|
14
14
|
|
15
|
-
@dataclass
|
15
|
+
@dataclass(kw_only=True)
|
16
16
|
class RatFuncCompuMethod(CompuMethod):
|
17
17
|
"""A compu method using a rational function
|
18
18
|
|
@@ -34,11 +34,11 @@ class RatFuncCompuMethod(CompuMethod):
|
|
34
34
|
return self._phys_to_int_segment
|
35
35
|
|
36
36
|
@staticmethod
|
37
|
-
def compu_method_from_et(et_element: ElementTree.Element,
|
37
|
+
def compu_method_from_et(et_element: ElementTree.Element, context: OdxDocContext, *,
|
38
38
|
internal_type: DataType,
|
39
39
|
physical_type: DataType) -> "RatFuncCompuMethod":
|
40
40
|
cm = CompuMethod.compu_method_from_et(
|
41
|
-
et_element,
|
41
|
+
et_element, context, internal_type=internal_type, physical_type=physical_type)
|
42
42
|
kwargs = dataclass_fields_asdict(cm)
|
43
43
|
|
44
44
|
return RatFuncCompuMethod(**kwargs)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from dataclasses import dataclass
|
2
|
+
from dataclasses import dataclass, field
|
3
3
|
|
4
4
|
from ..exceptions import odxraise, odxrequire
|
5
5
|
from ..odxtypes import AtomicOdxType, DataType
|
@@ -7,17 +7,17 @@ from .compuscale import CompuScale
|
|
7
7
|
from .limit import Limit
|
8
8
|
|
9
9
|
|
10
|
-
@dataclass
|
10
|
+
@dataclass(kw_only=True)
|
11
11
|
class RatFuncSegment:
|
12
12
|
"""Helper class to represent a segment of a piecewise rational function.
|
13
13
|
"""
|
14
14
|
value_type: DataType
|
15
15
|
|
16
|
-
numerator_coeffs: list[int | float]
|
17
|
-
denominator_coeffs: list[int | float]
|
16
|
+
numerator_coeffs: list[int | float] = field(default_factory=list)
|
17
|
+
denominator_coeffs: list[int | float] = field(default_factory=list)
|
18
18
|
|
19
|
-
lower_limit: Limit | None
|
20
|
-
upper_limit: Limit | None
|
19
|
+
lower_limit: Limit | None = None
|
20
|
+
upper_limit: Limit | None = None
|
21
21
|
|
22
22
|
@staticmethod
|
23
23
|
def from_compu_scale(scale: CompuScale, value_type: DataType) -> "RatFuncSegment":
|
@@ -39,7 +39,7 @@ class RatFuncSegment:
|
|
39
39
|
value_type=scale.range_type)
|
40
40
|
|
41
41
|
def convert(self, value: AtomicOdxType) -> float | int:
|
42
|
-
if not isinstance(value, int
|
42
|
+
if not isinstance(value, (int, float)):
|
43
43
|
odxraise(f"Internal values of linear compumethods must "
|
44
44
|
f"either be int or float (is: {type(value).__name__})")
|
45
45
|
|
@@ -69,7 +69,7 @@ class RatFuncSegment:
|
|
69
69
|
# Do type checks
|
70
70
|
expected_type = self.value_type.python_type
|
71
71
|
if issubclass(expected_type, float):
|
72
|
-
if not isinstance(value, int
|
72
|
+
if not isinstance(value, (int, float)):
|
73
73
|
return False
|
74
74
|
else:
|
75
75
|
if not isinstance(value, expected_type):
|
@@ -4,7 +4,7 @@ from typing import cast
|
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
|
7
|
-
from ..
|
7
|
+
from ..odxdoccontext import OdxDocContext
|
8
8
|
from ..odxtypes import AtomicOdxType, DataType
|
9
9
|
from ..utils import dataclass_fields_asdict
|
10
10
|
from .compucategory import CompuCategory
|
@@ -13,7 +13,7 @@ from .intervaltype import IntervalType
|
|
13
13
|
from .linearsegment import LinearSegment
|
14
14
|
|
15
15
|
|
16
|
-
@dataclass
|
16
|
+
@dataclass(kw_only=True)
|
17
17
|
class ScaleLinearCompuMethod(CompuMethod):
|
18
18
|
"""A piecewise linear compu method which may feature discontinuities.
|
19
19
|
|
@@ -25,11 +25,11 @@ class ScaleLinearCompuMethod(CompuMethod):
|
|
25
25
|
return self._segments
|
26
26
|
|
27
27
|
@staticmethod
|
28
|
-
def compu_method_from_et(et_element: ElementTree.Element,
|
28
|
+
def compu_method_from_et(et_element: ElementTree.Element, context: OdxDocContext, *,
|
29
29
|
internal_type: DataType,
|
30
30
|
physical_type: DataType) -> "ScaleLinearCompuMethod":
|
31
31
|
cm = CompuMethod.compu_method_from_et(
|
32
|
-
et_element,
|
32
|
+
et_element, context, internal_type=internal_type, physical_type=physical_type)
|
33
33
|
kwargs = dataclass_fields_asdict(cm)
|
34
34
|
|
35
35
|
return ScaleLinearCompuMethod(**kwargs)
|
@@ -100,7 +100,7 @@ class ScaleLinearCompuMethod(CompuMethod):
|
|
100
100
|
self._is_invertible = False
|
101
101
|
break
|
102
102
|
|
103
|
-
if not isinstance(x, int
|
103
|
+
if not isinstance(x, (int, float)):
|
104
104
|
odxraise("Linear segments must use int or float for all quantities")
|
105
105
|
|
106
106
|
# the respective function value at the interval's
|
@@ -4,7 +4,7 @@ from typing import cast
|
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
|
7
|
-
from ..
|
7
|
+
from ..odxdoccontext import OdxDocContext
|
8
8
|
from ..odxtypes import AtomicOdxType, DataType
|
9
9
|
from ..utils import dataclass_fields_asdict
|
10
10
|
from .compucategory import CompuCategory
|
@@ -12,7 +12,7 @@ from .compumethod import CompuMethod
|
|
12
12
|
from .ratfuncsegment import RatFuncSegment
|
13
13
|
|
14
14
|
|
15
|
-
@dataclass
|
15
|
+
@dataclass(kw_only=True)
|
16
16
|
class ScaleRatFuncCompuMethod(CompuMethod):
|
17
17
|
"""A compu method using a piecewise rational function
|
18
18
|
|
@@ -28,11 +28,11 @@ class ScaleRatFuncCompuMethod(CompuMethod):
|
|
28
28
|
return self._phys_to_int_segments
|
29
29
|
|
30
30
|
@staticmethod
|
31
|
-
def compu_method_from_et(et_element: ElementTree.Element,
|
31
|
+
def compu_method_from_et(et_element: ElementTree.Element, context: OdxDocContext, *,
|
32
32
|
internal_type: DataType,
|
33
33
|
physical_type: DataType) -> "ScaleRatFuncCompuMethod":
|
34
34
|
cm = CompuMethod.compu_method_from_et(
|
35
|
-
et_element,
|
35
|
+
et_element, context, internal_type=internal_type, physical_type=physical_type)
|
36
36
|
kwargs = dataclass_fields_asdict(cm)
|
37
37
|
|
38
38
|
return ScaleRatFuncCompuMethod(**kwargs)
|
@@ -3,7 +3,7 @@ from dataclasses import dataclass
|
|
3
3
|
from xml.etree import ElementTree
|
4
4
|
|
5
5
|
from ..exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
|
6
|
-
from ..
|
6
|
+
from ..odxdoccontext import OdxDocContext
|
7
7
|
from ..odxtypes import AtomicOdxType, DataType
|
8
8
|
from ..utils import dataclass_fields_asdict
|
9
9
|
from .compucategory import CompuCategory
|
@@ -12,7 +12,7 @@ from .intervaltype import IntervalType
|
|
12
12
|
from .limit import Limit
|
13
13
|
|
14
14
|
|
15
|
-
@dataclass
|
15
|
+
@dataclass(kw_only=True)
|
16
16
|
class TabIntpCompuMethod(CompuMethod):
|
17
17
|
"""A table-based interpolated compu method provides a continuous
|
18
18
|
transfer function based on piecewise linear interpolation.
|
@@ -60,11 +60,11 @@ class TabIntpCompuMethod(CompuMethod):
|
|
60
60
|
return self._physical_upper_limit
|
61
61
|
|
62
62
|
@staticmethod
|
63
|
-
def compu_method_from_et(et_element: ElementTree.Element,
|
63
|
+
def compu_method_from_et(et_element: ElementTree.Element, context: OdxDocContext, *,
|
64
64
|
internal_type: DataType,
|
65
65
|
physical_type: DataType) -> "TabIntpCompuMethod":
|
66
66
|
cm = CompuMethod.compu_method_from_et(
|
67
|
-
et_element,
|
67
|
+
et_element, context, internal_type=internal_type, physical_type=physical_type)
|
68
68
|
kwargs = dataclass_fields_asdict(cm)
|
69
69
|
|
70
70
|
return TabIntpCompuMethod(**kwargs)
|
@@ -79,10 +79,10 @@ class TabIntpCompuMethod(CompuMethod):
|
|
79
79
|
internal_point = odxrequire(scale.lower_limit).value
|
80
80
|
physical_point = odxrequire(scale.compu_const).value
|
81
81
|
|
82
|
-
if not isinstance(internal_point, float
|
82
|
+
if not isinstance(internal_point, (float, int)):
|
83
83
|
odxraise("The type of values of tab-intp compumethods must "
|
84
84
|
"either int or float")
|
85
|
-
if not isinstance(physical_point, float
|
85
|
+
if not isinstance(physical_point, (float, int)):
|
86
86
|
odxraise("The type of values of tab-intp compumethods must "
|
87
87
|
"either int or float")
|
88
88
|
|
@@ -140,13 +140,13 @@ class TabIntpCompuMethod(CompuMethod):
|
|
140
140
|
return None
|
141
141
|
|
142
142
|
def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> AtomicOdxType:
|
143
|
-
if not isinstance(physical_value, int
|
143
|
+
if not isinstance(physical_value, (int, float)):
|
144
144
|
odxraise("The type of values of tab-intp compumethods must "
|
145
145
|
"either int or float", EncodeError)
|
146
146
|
return None
|
147
147
|
|
148
148
|
odxassert(
|
149
|
-
isinstance(physical_value, int
|
149
|
+
isinstance(physical_value, (int, float)),
|
150
150
|
"Only integers and floats can be piecewise linearly interpolated", EncodeError)
|
151
151
|
result = self.__piecewise_linear_interpolate(physical_value, self._physical_points,
|
152
152
|
self._internal_points)
|
@@ -161,14 +161,14 @@ class TabIntpCompuMethod(CompuMethod):
|
|
161
161
|
return res
|
162
162
|
|
163
163
|
def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> AtomicOdxType:
|
164
|
-
if not isinstance(internal_value, int
|
164
|
+
if not isinstance(internal_value, (int, float)):
|
165
165
|
odxraise(
|
166
166
|
"The internal type of values of tab-intp compumethods must "
|
167
167
|
"either int or float", EncodeError)
|
168
168
|
return None
|
169
169
|
|
170
170
|
odxassert(
|
171
|
-
isinstance(internal_value, int
|
171
|
+
isinstance(internal_value, (int, float)),
|
172
172
|
"Only integers and floats can be piecewise linearly interpolated", DecodeError)
|
173
173
|
|
174
174
|
result = self.__piecewise_linear_interpolate(internal_value, self._internal_points,
|
@@ -185,14 +185,14 @@ class TabIntpCompuMethod(CompuMethod):
|
|
185
185
|
return res
|
186
186
|
|
187
187
|
def is_valid_physical_value(self, physical_value: AtomicOdxType) -> bool:
|
188
|
-
if not isinstance(physical_value, int
|
188
|
+
if not isinstance(physical_value, (int, float)):
|
189
189
|
return False
|
190
190
|
|
191
191
|
return min(self.physical_points) <= physical_value and physical_value <= max(
|
192
192
|
self.physical_points)
|
193
193
|
|
194
194
|
def is_valid_internal_value(self, internal_value: AtomicOdxType) -> bool:
|
195
|
-
if not isinstance(internal_value, int
|
195
|
+
if not isinstance(internal_value, (int, float)):
|
196
196
|
return False
|
197
197
|
|
198
198
|
return min(self.internal_points) <= internal_value and internal_value <= max(
|
@@ -4,7 +4,7 @@ from typing import cast
|
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from ..exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
|
7
|
-
from ..
|
7
|
+
from ..odxdoccontext import OdxDocContext
|
8
8
|
from ..odxtypes import AtomicOdxType, DataType
|
9
9
|
from ..utils import dataclass_fields_asdict
|
10
10
|
from .compucategory import CompuCategory
|
@@ -12,7 +12,7 @@ from .compumethod import CompuMethod
|
|
12
12
|
from .compuscale import CompuScale
|
13
13
|
|
14
14
|
|
15
|
-
@dataclass
|
15
|
+
@dataclass(kw_only=True)
|
16
16
|
class TexttableCompuMethod(CompuMethod):
|
17
17
|
"""Text table compute methods translate numbers to human readable
|
18
18
|
textual descriptions.
|
@@ -22,11 +22,11 @@ class TexttableCompuMethod(CompuMethod):
|
|
22
22
|
"""
|
23
23
|
|
24
24
|
@staticmethod
|
25
|
-
def compu_method_from_et(et_element: ElementTree.Element,
|
25
|
+
def compu_method_from_et(et_element: ElementTree.Element, context: OdxDocContext, *,
|
26
26
|
internal_type: DataType,
|
27
27
|
physical_type: DataType) -> "TexttableCompuMethod":
|
28
28
|
cm = CompuMethod.compu_method_from_et(
|
29
|
-
et_element,
|
29
|
+
et_element, context, internal_type=internal_type, physical_type=physical_type)
|
30
30
|
kwargs = dataclass_fields_asdict(cm)
|
31
31
|
|
32
32
|
return TexttableCompuMethod(**kwargs)
|
odxtools/createanycomparam.py
CHANGED
@@ -2,14 +2,14 @@ from xml.etree import ElementTree
|
|
2
2
|
|
3
3
|
from .comparam import Comparam
|
4
4
|
from .complexcomparam import ComplexComparam
|
5
|
-
from .
|
5
|
+
from .odxdoccontext import OdxDocContext
|
6
6
|
|
7
7
|
|
8
8
|
def create_any_comparam_from_et(et_element: ElementTree.Element,
|
9
|
-
|
9
|
+
context: OdxDocContext) -> Comparam | ComplexComparam:
|
10
10
|
if et_element.tag == "COMPARAM":
|
11
|
-
return Comparam.from_et(et_element,
|
11
|
+
return Comparam.from_et(et_element, context)
|
12
12
|
elif et_element.tag == "COMPLEX-COMPARAM":
|
13
|
-
return ComplexComparam.from_et(et_element,
|
13
|
+
return ComplexComparam.from_et(et_element, context)
|
14
14
|
|
15
15
|
raise RuntimeError(f"Unhandled communication parameter type {et_element.tag}")
|
@@ -6,22 +6,22 @@ from .exceptions import odxraise
|
|
6
6
|
from .globals import xsi
|
7
7
|
from .leadinglengthinfotype import LeadingLengthInfoType
|
8
8
|
from .minmaxlengthtype import MinMaxLengthType
|
9
|
-
from .
|
9
|
+
from .odxdoccontext import OdxDocContext
|
10
10
|
from .paramlengthinfotype import ParamLengthInfoType
|
11
11
|
from .standardlengthtype import StandardLengthType
|
12
12
|
|
13
13
|
|
14
14
|
def create_any_diag_coded_type_from_et(et_element: ElementTree.Element,
|
15
|
-
|
15
|
+
context: OdxDocContext) -> DiagCodedType:
|
16
16
|
dct_type = et_element.get(f"{xsi}type")
|
17
17
|
if dct_type == "LEADING-LENGTH-INFO-TYPE":
|
18
|
-
return LeadingLengthInfoType.from_et(et_element,
|
18
|
+
return LeadingLengthInfoType.from_et(et_element, context)
|
19
19
|
elif dct_type == "MIN-MAX-LENGTH-TYPE":
|
20
|
-
return MinMaxLengthType.from_et(et_element,
|
20
|
+
return MinMaxLengthType.from_et(et_element, context)
|
21
21
|
elif dct_type == "PARAM-LENGTH-INFO-TYPE":
|
22
|
-
return ParamLengthInfoType.from_et(et_element,
|
22
|
+
return ParamLengthInfoType.from_et(et_element, context)
|
23
23
|
elif dct_type == "STANDARD-LENGTH-TYPE":
|
24
|
-
return StandardLengthType.from_et(et_element,
|
24
|
+
return StandardLengthType.from_et(et_element, context)
|
25
25
|
|
26
26
|
odxraise(f"Unknown DIAG-CODED-TYPE {dct_type}", NotImplementedError)
|
27
|
-
return DiagCodedType.from_et(et_element,
|
27
|
+
return DiagCodedType.from_et(et_element, context)
|
odxtools/database.py
CHANGED
@@ -20,7 +20,8 @@ from .diaglayers.functionalgroup import FunctionalGroup
|
|
20
20
|
from .diaglayers.protocol import Protocol
|
21
21
|
from .exceptions import odxraise, odxrequire
|
22
22
|
from .nameditemlist import NamedItemList
|
23
|
-
from .
|
23
|
+
from .odxdoccontext import OdxDocContext
|
24
|
+
from .odxlink import DocType, OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
24
25
|
from .snrefcontext import SnRefContext
|
25
26
|
|
26
27
|
|
@@ -76,10 +77,6 @@ class Database:
|
|
76
77
|
self.auxiliary_files[str(aux_file_name)] = aux_file_obj
|
77
78
|
|
78
79
|
def _process_xml_tree(self, root: ElementTree.Element) -> None:
|
79
|
-
dlcs: list[DiagLayerContainer] = []
|
80
|
-
comparam_subsets: list[ComparamSubset] = []
|
81
|
-
comparam_specs: list[ComparamSpec] = []
|
82
|
-
|
83
80
|
# ODX spec version
|
84
81
|
model_version = Version(root.attrib.get("MODEL-VERSION", "2.0"))
|
85
82
|
if self.model_version is not None and self.model_version != model_version:
|
@@ -88,28 +85,33 @@ class Database:
|
|
88
85
|
|
89
86
|
self.model_version = model_version
|
90
87
|
|
91
|
-
|
92
|
-
if
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
88
|
+
child_elements = list(root)
|
89
|
+
if len(child_elements) != 1:
|
90
|
+
odxraise("Each ODX document must contain exactly one category.")
|
91
|
+
|
92
|
+
category_et = child_elements[0]
|
93
|
+
category_sn = odxrequire(category_et.findtext("SHORT-NAME"))
|
94
|
+
category_tag = category_et.tag
|
95
|
+
|
96
|
+
if category_tag == "DIAG-LAYER-CONTAINER":
|
97
|
+
context = OdxDocContext(model_version,
|
98
|
+
(OdxDocFragment(category_sn, DocType.CONTAINER),))
|
99
|
+
self._diag_layer_containers.append(DiagLayerContainer.from_et(category_et, context))
|
100
|
+
elif category_tag == "COMPARAM-SUBSET":
|
101
|
+
context = OdxDocContext(model_version,
|
102
|
+
(OdxDocFragment(category_sn, DocType.COMPARAM_SUBSET),))
|
103
|
+
self._comparam_subsets.append(ComparamSubset.from_et(category_et, context))
|
104
|
+
elif category_tag == "COMPARAM-SPEC":
|
105
|
+
# In ODX 2.0 there was only COMPARAM-SPEC. In ODX 2.2 the
|
106
|
+
# content of COMPARAM-SPEC was moved to COMPARAM-SUBSET
|
107
|
+
# and COMPARAM-SPEC became a container for PROT-STACKS and
|
108
|
+
# a PROT-STACK references a list of COMPARAM-SUBSET
|
109
|
+
context = OdxDocContext(model_version,
|
110
|
+
(OdxDocFragment(category_sn, DocType.COMPARAM_SPEC),))
|
105
111
|
if model_version < Version("2.2"):
|
106
|
-
|
107
|
-
else:
|
108
|
-
|
109
|
-
|
110
|
-
self._diag_layer_containers.extend(dlcs)
|
111
|
-
self._comparam_subsets.extend(comparam_subsets)
|
112
|
-
self._comparam_specs.extend(comparam_specs)
|
112
|
+
self._comparam_subsets.append(ComparamSubset.from_et(category_et, context))
|
113
|
+
else:
|
114
|
+
self._comparam_specs.append(ComparamSpec.from_et(category_et, context))
|
113
115
|
|
114
116
|
def refresh(self) -> None:
|
115
117
|
# Create wrapper objects
|
odxtools/dataobjectproperty.py
CHANGED
@@ -12,7 +12,8 @@ from .dopbase import DopBase
|
|
12
12
|
from .encodestate import EncodeState
|
13
13
|
from .exceptions import EncodeError, odxraise, odxrequire
|
14
14
|
from .internalconstr import InternalConstr
|
15
|
-
from .
|
15
|
+
from .odxdoccontext import OdxDocContext
|
16
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
16
17
|
from .odxtypes import AtomicOdxType, BytesTypes, ParameterValue
|
17
18
|
from .physicaltype import PhysicalType
|
18
19
|
from .snrefcontext import SnRefContext
|
@@ -20,7 +21,7 @@ from .unit import Unit
|
|
20
21
|
from .utils import dataclass_fields_asdict
|
21
22
|
|
22
23
|
|
23
|
-
@dataclass
|
24
|
+
@dataclass(kw_only=True)
|
24
25
|
class DataObjectProperty(DopBase):
|
25
26
|
"""This class represents a DATA-OBJECT-PROP.
|
26
27
|
|
@@ -37,42 +38,40 @@ class DataObjectProperty(DopBase):
|
|
37
38
|
#: The type of the value in the physical world
|
38
39
|
physical_type: PhysicalType
|
39
40
|
|
40
|
-
internal_constr: InternalConstr | None
|
41
|
+
internal_constr: InternalConstr | None = None
|
41
42
|
|
42
43
|
#: The unit associated with physical values (e.g. 'm/s^2')
|
43
|
-
unit_ref: OdxLinkRef | None
|
44
|
+
unit_ref: OdxLinkRef | None = None
|
44
45
|
|
45
|
-
physical_constr: InternalConstr | None
|
46
|
+
physical_constr: InternalConstr | None = None
|
46
47
|
|
47
48
|
@property
|
48
49
|
def unit(self) -> Unit | None:
|
49
50
|
return self._unit
|
50
51
|
|
51
52
|
@staticmethod
|
52
|
-
def from_et(et_element: ElementTree.Element,
|
53
|
-
doc_frags: list[OdxDocFragment]) -> "DataObjectProperty":
|
53
|
+
def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "DataObjectProperty":
|
54
54
|
"""Reads a DATA-OBJECT-PROP."""
|
55
|
-
kwargs = dataclass_fields_asdict(DopBase.from_et(et_element,
|
55
|
+
kwargs = dataclass_fields_asdict(DopBase.from_et(et_element, context))
|
56
56
|
|
57
57
|
diag_coded_type = create_any_diag_coded_type_from_et(
|
58
|
-
odxrequire(et_element.find("DIAG-CODED-TYPE")),
|
59
|
-
physical_type = PhysicalType.from_et(
|
60
|
-
odxrequire(et_element.find("PHYSICAL-TYPE")), doc_frags)
|
58
|
+
odxrequire(et_element.find("DIAG-CODED-TYPE")), context)
|
59
|
+
physical_type = PhysicalType.from_et(odxrequire(et_element.find("PHYSICAL-TYPE")), context)
|
61
60
|
compu_method = create_any_compu_method_from_et(
|
62
61
|
odxrequire(et_element.find("COMPU-METHOD")),
|
63
|
-
|
62
|
+
context,
|
64
63
|
internal_type=diag_coded_type.base_data_type,
|
65
64
|
physical_type=physical_type.base_data_type,
|
66
65
|
)
|
67
66
|
internal_constr = None
|
68
67
|
if (internal_constr_elem := et_element.find("INTERNAL-CONSTR")) is not None:
|
69
68
|
internal_constr = InternalConstr.constr_from_et(
|
70
|
-
internal_constr_elem,
|
71
|
-
unit_ref = OdxLinkRef.from_et(et_element.find("UNIT-REF"),
|
69
|
+
internal_constr_elem, context, value_type=diag_coded_type.base_data_type)
|
70
|
+
unit_ref = OdxLinkRef.from_et(et_element.find("UNIT-REF"), context)
|
72
71
|
physical_constr = None
|
73
72
|
if (physical_constr_elem := et_element.find("PHYS-CONSTR")) is not None:
|
74
73
|
physical_constr = InternalConstr.constr_from_et(
|
75
|
-
physical_constr_elem,
|
74
|
+
physical_constr_elem, context, value_type=physical_type.base_data_type)
|
76
75
|
|
77
76
|
return DataObjectProperty(
|
78
77
|
compu_method=compu_method,
|
@@ -118,7 +117,7 @@ class DataObjectProperty(DopBase):
|
|
118
117
|
f"The value {repr(physical_value)} of type {type(physical_value).__name__}"
|
119
118
|
f" is not a valid.")
|
120
119
|
|
121
|
-
if not isinstance(physical_value, int
|
120
|
+
if not isinstance(physical_value, (int, float, str, BytesTypes)):
|
122
121
|
odxraise(f"Invalid type '{type(physical_value).__name__}' for physical value. "
|
123
122
|
f"(Expect atomic type!)")
|
124
123
|
internal_value = self.compu_method.convert_physical_to_internal(physical_value)
|
odxtools/description.py
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
from dataclasses import dataclass
|
1
|
+
from dataclasses import dataclass, field
|
2
2
|
from typing import Optional
|
3
3
|
from xml.etree import ElementTree
|
4
4
|
|
5
5
|
from .exceptions import odxrequire
|
6
6
|
from .externaldoc import ExternalDoc
|
7
|
-
from .
|
7
|
+
from .odxdoccontext import OdxDocContext
|
8
8
|
|
9
9
|
|
10
|
-
@dataclass
|
10
|
+
@dataclass(kw_only=True)
|
11
11
|
class Description:
|
12
12
|
text: str
|
13
|
-
external_docs: list[ExternalDoc]
|
13
|
+
external_docs: list[ExternalDoc] = field(default_factory=list)
|
14
14
|
|
15
|
-
text_identifier: str | None
|
15
|
+
text_identifier: str | None = None
|
16
16
|
|
17
17
|
@staticmethod
|
18
18
|
def from_et(et_element: ElementTree.Element | None,
|
19
|
-
|
19
|
+
context: OdxDocContext) -> Optional["Description"]:
|
20
20
|
if et_element is None:
|
21
21
|
return None
|
22
22
|
|
@@ -35,7 +35,7 @@ class Description:
|
|
35
35
|
|
36
36
|
external_docs = \
|
37
37
|
[
|
38
|
-
odxrequire(ExternalDoc.from_et(ed,
|
38
|
+
odxrequire(ExternalDoc.from_et(ed, context)) for ed in et_element.iterfind("EXTERNAL-DOCS/EXTERNAL-DOC")
|
39
39
|
]
|
40
40
|
|
41
41
|
text_identifier = et_element.attrib.get("TI")
|
@@ -5,17 +5,18 @@ from xml.etree import ElementTree
|
|
5
5
|
|
6
6
|
from .dataobjectproperty import DataObjectProperty
|
7
7
|
from .exceptions import odxrequire
|
8
|
-
from .
|
8
|
+
from .odxdoccontext import OdxDocContext
|
9
|
+
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
9
10
|
from .snrefcontext import SnRefContext
|
10
11
|
|
11
12
|
|
12
|
-
@dataclass
|
13
|
+
@dataclass(kw_only=True)
|
13
14
|
class DetermineNumberOfItems:
|
14
15
|
"""
|
15
16
|
The object that determines the number of items of dynamic fields
|
16
17
|
"""
|
17
18
|
byte_position: int
|
18
|
-
bit_position: int | None
|
19
|
+
bit_position: int | None = None
|
19
20
|
dop_ref: OdxLinkRef
|
20
21
|
|
21
22
|
@property
|
@@ -24,11 +25,11 @@ class DetermineNumberOfItems:
|
|
24
25
|
|
25
26
|
@staticmethod
|
26
27
|
def from_et(et_element: ElementTree.Element,
|
27
|
-
|
28
|
+
context: OdxDocContext) -> "DetermineNumberOfItems":
|
28
29
|
byte_position = int(odxrequire(et_element.findtext("BYTE-POSITION")))
|
29
30
|
bit_position_str = et_element.findtext("BIT-POSITION")
|
30
31
|
bit_position = int(bit_position_str) if bit_position_str is not None else None
|
31
|
-
dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DATA-OBJECT-PROP-REF"),
|
32
|
+
dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DATA-OBJECT-PROP-REF"), context))
|
32
33
|
|
33
34
|
return DetermineNumberOfItems(
|
34
35
|
byte_position=byte_position,
|