odxtools 6.7.0__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 +6 -4
- odxtools/additionalaudience.py +3 -5
- odxtools/admindata.py +5 -7
- odxtools/audience.py +10 -13
- odxtools/basecomparam.py +3 -5
- odxtools/basicstructure.py +55 -240
- odxtools/cli/_parser_utils.py +1 -1
- odxtools/cli/_print_utils.py +168 -134
- odxtools/cli/browse.py +111 -92
- odxtools/cli/compare.py +90 -71
- odxtools/cli/list.py +24 -15
- odxtools/cli/snoop.py +28 -5
- 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 +7 -9
- 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 +93 -12
- odxtools/compumethods/compuphystointernal.py +56 -0
- odxtools/compumethods/compurationalcoeffs.py +20 -9
- odxtools/compumethods/compuscale.py +30 -35
- odxtools/compumethods/createanycompumethod.py +28 -161
- odxtools/compumethods/identicalcompumethod.py +31 -6
- odxtools/compumethods/linearcompumethod.py +69 -189
- 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 +119 -99
- odxtools/compumethods/texttablecompumethod.py +107 -43
- odxtools/createanydiagcodedtype.py +10 -67
- odxtools/database.py +167 -87
- odxtools/dataobjectproperty.py +15 -25
- odxtools/decodestate.py +9 -15
- odxtools/description.py +47 -0
- odxtools/determinenumberofitems.py +4 -5
- odxtools/diagcodedtype.py +36 -106
- odxtools/diagcomm.py +24 -12
- odxtools/diagdatadictionaryspec.py +33 -34
- 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/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} +209 -448
- 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 +56 -43
- odxtools/diagvariable.py +113 -0
- odxtools/docrevision.py +5 -7
- odxtools/dopbase.py +15 -17
- odxtools/dtcdop.py +168 -50
- odxtools/dynamicendmarkerfield.py +134 -0
- odxtools/dynamiclengthfield.py +41 -37
- 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 -38
- odxtools/exceptions.py +11 -2
- odxtools/field.py +10 -10
- odxtools/functionalclass.py +3 -5
- odxtools/inputparam.py +3 -12
- 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 +128 -73
- odxtools/multiplexercase.py +13 -14
- odxtools/multiplexerdefaultcase.py +15 -12
- odxtools/multiplexerswitchkey.py +4 -5
- odxtools/nameditemlist.py +29 -5
- odxtools/negoutputparam.py +3 -5
- odxtools/odxcategory.py +83 -0
- odxtools/odxlink.py +60 -51
- odxtools/odxtypes.py +37 -5
- odxtools/outputparam.py +4 -15
- odxtools/parameterinfo.py +218 -67
- odxtools/parameters/codedconstparameter.py +16 -24
- odxtools/parameters/dynamicparameter.py +5 -4
- odxtools/parameters/lengthkeyparameter.py +60 -26
- odxtools/parameters/matchingrequestparameter.py +23 -11
- odxtools/parameters/nrcconstparameter.py +45 -46
- odxtools/parameters/parameter.py +54 -56
- odxtools/parameters/parameterwithdop.py +15 -25
- odxtools/parameters/physicalconstantparameter.py +15 -18
- odxtools/parameters/reservedparameter.py +6 -2
- odxtools/parameters/systemparameter.py +55 -11
- odxtools/parameters/tableentryparameter.py +3 -2
- odxtools/parameters/tablekeyparameter.py +103 -49
- odxtools/parameters/tablestructparameter.py +47 -48
- odxtools/parameters/valueparameter.py +16 -20
- odxtools/paramlengthinfotype.py +52 -32
- odxtools/parentref.py +16 -2
- 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 +3 -3
- 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 +7 -17
- odxtools/staticfield.py +31 -25
- odxtools/subcomponent.py +288 -0
- odxtools/swvariable.py +21 -0
- odxtools/table.py +7 -8
- odxtools/tablerow.py +19 -11
- 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 -133
- 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 +4 -3
- odxtools/templates/macros/printOdxCategory.xml.jinja2 +28 -0
- odxtools/templates/macros/printParam.xml.jinja2 +11 -12
- 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 +1 -1
- 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} +20 -10
- odxtools/xdoc.py +3 -5
- {odxtools-6.7.0.dist-info → odxtools-9.3.0.dist-info}/METADATA +20 -21
- odxtools-9.3.0.dist-info/RECORD +228 -0
- {odxtools-6.7.0.dist-info → odxtools-9.3.0.dist-info}/WHEEL +1 -1
- odxtools/createcompanydatas.py +0 -17
- odxtools/createsdgs.py +0 -19
- odxtools/load_file.py +0 -13
- odxtools/load_odx_d_file.py +0 -6
- odxtools/load_pdx_file.py +0 -8
- odxtools/templates/macros/printVariant.xml.jinja2 +0 -216
- odxtools-6.7.0.dist-info/RECORD +0 -182
- /odxtools/{diaglayertype.py → diaglayers/diaglayertype.py} +0 -0
- {odxtools-6.7.0.dist-info → odxtools-9.3.0.dist-info}/LICENSE +0 -0
- {odxtools-6.7.0.dist-info → odxtools-9.3.0.dist-info}/entry_points.txt +0 -0
- {odxtools-6.7.0.dist-info → odxtools-9.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
from xml.etree import ElementTree
|
5
|
+
|
6
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
7
|
+
from ..odxtypes import DataType
|
8
|
+
from ..progcode import ProgCode
|
9
|
+
from ..snrefcontext import SnRefContext
|
10
|
+
from .compudefaultvalue import CompuDefaultValue
|
11
|
+
from .compuscale import CompuScale
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass
|
15
|
+
class CompuPhysToInternal:
|
16
|
+
compu_scales: List[CompuScale]
|
17
|
+
prog_code: Optional[ProgCode]
|
18
|
+
compu_default_value: Optional[CompuDefaultValue]
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def compu_phys_to_internal_from_et(et_element: ElementTree.Element,
|
22
|
+
doc_frags: List[OdxDocFragment], *, internal_type: DataType,
|
23
|
+
physical_type: DataType) -> "CompuPhysToInternal":
|
24
|
+
compu_scales = [
|
25
|
+
CompuScale.compuscale_from_et(
|
26
|
+
cse, doc_frags, domain_type=physical_type, range_type=internal_type)
|
27
|
+
for cse in et_element.iterfind("COMPU-SCALES/COMPU-SCALE")
|
28
|
+
]
|
29
|
+
|
30
|
+
prog_code = None
|
31
|
+
if (pce := et_element.find("PROG-CODE")) is not None:
|
32
|
+
prog_code = ProgCode.from_et(pce, doc_frags)
|
33
|
+
|
34
|
+
compu_default_value = None
|
35
|
+
if (cdve := et_element.find("COMPU-DEFAULT-VALUE")) is not None:
|
36
|
+
compu_default_value = CompuDefaultValue.compuvalue_from_et(
|
37
|
+
cdve, data_type=internal_type)
|
38
|
+
|
39
|
+
return CompuPhysToInternal(
|
40
|
+
compu_scales=compu_scales, prog_code=prog_code, compu_default_value=compu_default_value)
|
41
|
+
|
42
|
+
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
43
|
+
result = {}
|
44
|
+
|
45
|
+
if self.prog_code is not None:
|
46
|
+
result.update(self.prog_code._build_odxlinks())
|
47
|
+
|
48
|
+
return result
|
49
|
+
|
50
|
+
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
51
|
+
if self.prog_code is not None:
|
52
|
+
self.prog_code._resolve_odxlinks(odxlinks)
|
53
|
+
|
54
|
+
def _resolve_snrefs(self, context: SnRefContext) -> None:
|
55
|
+
if self.prog_code is not None:
|
56
|
+
self.prog_code._resolve_snrefs(context)
|
@@ -1,25 +1,36 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import List
|
3
|
+
from typing import List, Union, cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
-
from ..exceptions import odxrequire
|
6
|
+
from ..exceptions import odxassert, odxrequire
|
7
7
|
from ..odxlink import OdxDocFragment
|
8
|
+
from ..odxtypes import DataType
|
8
9
|
|
9
10
|
|
10
11
|
@dataclass
|
11
12
|
class CompuRationalCoeffs:
|
12
|
-
|
13
|
-
|
13
|
+
value_type: DataType
|
14
|
+
|
15
|
+
numerators: List[Union[int, float]]
|
16
|
+
denominators: List[Union[int, float]]
|
14
17
|
|
15
18
|
@staticmethod
|
16
|
-
def
|
17
|
-
|
19
|
+
def coeffs_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
|
20
|
+
value_type: DataType) -> "CompuRationalCoeffs":
|
21
|
+
odxassert(
|
22
|
+
value_type
|
23
|
+
in (DataType.A_UINT32, DataType.A_INT32, DataType.A_FLOAT32, DataType.A_FLOAT64),
|
24
|
+
"Rational coefficients must be of numeric type.")
|
25
|
+
|
18
26
|
numerators = [
|
19
|
-
float(odxrequire(elem.text))
|
27
|
+
cast(float, value_type.from_string(odxrequire(elem.text)))
|
28
|
+
for elem in et_element.iterfind("COMPU-NUMERATOR/V")
|
20
29
|
]
|
21
30
|
denominators = [
|
22
|
-
float(odxrequire(elem.text))
|
31
|
+
cast(float, value_type.from_string(odxrequire(elem.text)))
|
32
|
+
for elem in et_element.iterfind("COMPU-DENOMINATOR/V")
|
23
33
|
]
|
24
34
|
|
25
|
-
return CompuRationalCoeffs(
|
35
|
+
return CompuRationalCoeffs(
|
36
|
+
value_type=value_type, numerators=numerators, denominators=denominators)
|
@@ -3,9 +3,11 @@ from dataclasses import dataclass
|
|
3
3
|
from typing import List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
+
from ..description import Description
|
6
7
|
from ..odxlink import OdxDocFragment
|
7
8
|
from ..odxtypes import AtomicOdxType, DataType
|
8
|
-
from
|
9
|
+
from .compuconst import CompuConst
|
10
|
+
from .compuinversevalue import CompuInverseValue
|
9
11
|
from .compurationalcoeffs import CompuRationalCoeffs
|
10
12
|
from .limit import Limit
|
11
13
|
|
@@ -13,58 +15,51 @@ from .limit import Limit
|
|
13
15
|
@dataclass
|
14
16
|
class CompuScale:
|
15
17
|
"""A COMPU-SCALE represents one value range of a COMPU-METHOD.
|
16
|
-
|
17
|
-
Example:
|
18
|
-
|
19
|
-
For a TEXTTABLE compu method a compu scale within COMPU-INTERNAL-TO-PHYS
|
20
|
-
can be defined with
|
21
|
-
```
|
22
|
-
scale = CompuScale(
|
23
|
-
short_label="example_label", # optional: provide a label
|
24
|
-
description="<p>fancy description</p>", # optional: provide a description
|
25
|
-
lower_limit=Limit(0), # required: lower limit
|
26
|
-
upper_limit=Limit(3), # required: upper limit
|
27
|
-
compu_inverse_value=2, # required if lower_limit != upper_limit
|
28
|
-
compu_const="true", # required: physical value to be shown to the user
|
29
|
-
)
|
30
|
-
```
|
31
|
-
|
32
|
-
Almost all attributes are optional but there are compu-method-specific restrictions.
|
33
|
-
E.g., lower_limit must always be defined unless the COMPU-METHOD is of CATEGORY LINEAR or RAT-FUNC.
|
34
|
-
Either `compu_const` or `compu_rational_coeffs` must be defined but never both.
|
35
18
|
"""
|
36
19
|
|
37
20
|
short_label: Optional[str]
|
38
|
-
description: Optional[
|
21
|
+
description: Optional[Description]
|
39
22
|
lower_limit: Optional[Limit]
|
40
23
|
upper_limit: Optional[Limit]
|
41
|
-
compu_inverse_value: Optional[
|
42
|
-
compu_const: Optional[
|
24
|
+
compu_inverse_value: Optional[CompuInverseValue]
|
25
|
+
compu_const: Optional[CompuConst]
|
43
26
|
compu_rational_coeffs: Optional[CompuRationalCoeffs]
|
44
27
|
|
45
28
|
# the following two attributes are not specified for COMPU-SCALE
|
46
29
|
# tags in the XML, but they are required to do anything useful
|
47
|
-
# with
|
48
|
-
|
49
|
-
|
30
|
+
# with compu scales: The domain type is the input set of the
|
31
|
+
# function associated with the compu scale object, whilst the
|
32
|
+
# range type represents the output set. IOW, for scales contained
|
33
|
+
# by the internal-to-physical mapping function, the domain type is
|
34
|
+
# the internal and the range type is the physical type of the
|
35
|
+
# compu method. (Vice versa for scales specified by the
|
36
|
+
# physical-to-internal mapping function.)
|
37
|
+
domain_type: DataType
|
38
|
+
range_type: DataType
|
50
39
|
|
51
40
|
@staticmethod
|
52
41
|
def compuscale_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
|
53
|
-
|
42
|
+
domain_type: DataType, range_type: DataType) -> "CompuScale":
|
54
43
|
short_label = et_element.findtext("SHORT-LABEL")
|
55
|
-
description =
|
44
|
+
description = Description.from_et(et_element.find("DESC"), doc_frags)
|
56
45
|
|
57
46
|
lower_limit = Limit.limit_from_et(
|
58
|
-
et_element.find("LOWER-LIMIT"), doc_frags, value_type=
|
47
|
+
et_element.find("LOWER-LIMIT"), doc_frags, value_type=domain_type)
|
59
48
|
upper_limit = Limit.limit_from_et(
|
60
|
-
et_element.find("UPPER-LIMIT"), doc_frags, value_type=
|
49
|
+
et_element.find("UPPER-LIMIT"), doc_frags, value_type=domain_type)
|
50
|
+
|
51
|
+
compu_inverse_value = None
|
52
|
+
if (cive := et_element.find("COMPU-INVERSE-VALUE")) is not None:
|
53
|
+
compu_inverse_value = CompuInverseValue.compuvalue_from_et(cive, data_type=domain_type)
|
61
54
|
|
62
|
-
|
63
|
-
|
55
|
+
compu_const = None
|
56
|
+
if (cce := et_element.find("COMPU-CONST")) is not None:
|
57
|
+
compu_const = CompuConst.compuvalue_from_et(cce, data_type=range_type)
|
64
58
|
|
65
59
|
compu_rational_coeffs: Optional[CompuRationalCoeffs] = None
|
66
60
|
if (crc_elem := et_element.find("COMPU-RATIONAL-COEFFS")) is not None:
|
67
|
-
compu_rational_coeffs = CompuRationalCoeffs.
|
61
|
+
compu_rational_coeffs = CompuRationalCoeffs.coeffs_from_et(
|
62
|
+
crc_elem, doc_frags, value_type=range_type)
|
68
63
|
|
69
64
|
return CompuScale(
|
70
65
|
short_label=short_label,
|
@@ -74,8 +69,8 @@ class CompuScale:
|
|
74
69
|
compu_inverse_value=compu_inverse_value,
|
75
70
|
compu_const=compu_const,
|
76
71
|
compu_rational_coeffs=compu_rational_coeffs,
|
77
|
-
|
78
|
-
|
72
|
+
domain_type=domain_type,
|
73
|
+
range_type=range_type)
|
79
74
|
|
80
75
|
def applies(self, internal_value: AtomicOdxType) -> bool:
|
81
76
|
|
@@ -1,186 +1,53 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
from typing import
|
2
|
+
from typing import List
|
3
3
|
from xml.etree import ElementTree
|
4
4
|
|
5
|
-
from ..exceptions import
|
5
|
+
from ..exceptions import odxraise, odxrequire
|
6
6
|
from ..odxlink import OdxDocFragment
|
7
7
|
from ..odxtypes import DataType
|
8
|
+
from .compucodecompumethod import CompuCodeCompuMethod
|
8
9
|
from .compumethod import CompuMethod
|
9
|
-
from .compuscale import CompuScale
|
10
10
|
from .identicalcompumethod import IdenticalCompuMethod
|
11
|
-
from .limit import Limit
|
12
11
|
from .linearcompumethod import LinearCompuMethod
|
12
|
+
from .ratfunccompumethod import RatFuncCompuMethod
|
13
13
|
from .scalelinearcompumethod import ScaleLinearCompuMethod
|
14
|
+
from .scaleratfunccompumethod import ScaleRatFuncCompuMethod
|
14
15
|
from .tabintpcompumethod import TabIntpCompuMethod
|
15
16
|
from .texttablecompumethod import TexttableCompuMethod
|
16
17
|
|
17
18
|
|
18
|
-
def _parse_compu_scale_to_linear_compu_method(
|
19
|
-
et_element: ElementTree.Element,
|
20
|
-
doc_frags: List[OdxDocFragment],
|
21
|
-
*,
|
22
|
-
internal_type: DataType,
|
23
|
-
physical_type: DataType,
|
24
|
-
is_scale_linear: bool = False,
|
25
|
-
**kwargs: Any,
|
26
|
-
) -> LinearCompuMethod:
|
27
|
-
odxassert(physical_type in [
|
28
|
-
DataType.A_FLOAT32,
|
29
|
-
DataType.A_FLOAT64,
|
30
|
-
DataType.A_INT32,
|
31
|
-
DataType.A_UINT32,
|
32
|
-
])
|
33
|
-
odxassert(internal_type in [
|
34
|
-
DataType.A_FLOAT32,
|
35
|
-
DataType.A_FLOAT64,
|
36
|
-
DataType.A_INT32,
|
37
|
-
DataType.A_UINT32,
|
38
|
-
])
|
39
|
-
|
40
|
-
if physical_type.python_type == float:
|
41
|
-
computation_python_type = physical_type.from_string
|
42
|
-
else:
|
43
|
-
computation_python_type = internal_type.from_string
|
44
|
-
|
45
|
-
kwargs = kwargs.copy()
|
46
|
-
kwargs["internal_type"] = internal_type
|
47
|
-
kwargs["physical_type"] = physical_type
|
48
|
-
|
49
|
-
coeffs = odxrequire(et_element.find("COMPU-RATIONAL-COEFFS"))
|
50
|
-
nums = coeffs.iterfind("COMPU-NUMERATOR/V")
|
51
|
-
|
52
|
-
offset = computation_python_type(odxrequire(next(nums).text))
|
53
|
-
factor_el = next(nums, None)
|
54
|
-
factor = computation_python_type(odxrequire(factor_el.text) if factor_el is not None else "0")
|
55
|
-
denominator = 1.0
|
56
|
-
if (string := coeffs.findtext("COMPU-DENOMINATOR/V")) is not None:
|
57
|
-
denominator = float(string)
|
58
|
-
if denominator == 0:
|
59
|
-
odxraise("CompuMethod: A denominator of zero will lead to divisions by zero.")
|
60
|
-
|
61
|
-
# Read lower limit
|
62
|
-
internal_lower_limit = Limit.limit_from_et(
|
63
|
-
et_element.find("LOWER-LIMIT"),
|
64
|
-
doc_frags,
|
65
|
-
value_type=internal_type,
|
66
|
-
)
|
67
|
-
|
68
|
-
kwargs["internal_lower_limit"] = internal_lower_limit
|
69
|
-
|
70
|
-
# Read upper limit
|
71
|
-
internal_upper_limit = Limit.limit_from_et(
|
72
|
-
et_element.find("UPPER-LIMIT"),
|
73
|
-
doc_frags,
|
74
|
-
value_type=internal_type,
|
75
|
-
)
|
76
|
-
|
77
|
-
kwargs["internal_upper_limit"] = internal_upper_limit
|
78
|
-
kwargs["denominator"] = denominator
|
79
|
-
kwargs["factor"] = factor
|
80
|
-
kwargs["offset"] = offset
|
81
|
-
|
82
|
-
return LinearCompuMethod(**kwargs)
|
83
|
-
|
84
|
-
|
85
|
-
def create_compu_default_value(et_element: Optional[ElementTree.Element],
|
86
|
-
doc_frags: List[OdxDocFragment], internal_type: DataType, *,
|
87
|
-
physical_type: DataType) -> Optional[CompuScale]:
|
88
|
-
if et_element is None:
|
89
|
-
return None
|
90
|
-
compu_const = physical_type.create_from_et(et_element)
|
91
|
-
scale = CompuScale.compuscale_from_et(
|
92
|
-
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
93
|
-
scale.compu_const = compu_const
|
94
|
-
return scale
|
95
|
-
|
96
|
-
|
97
19
|
def create_any_compu_method_from_et(et_element: ElementTree.Element,
|
98
20
|
doc_frags: List[OdxDocFragment], *, internal_type: DataType,
|
99
21
|
physical_type: DataType) -> CompuMethod:
|
100
|
-
compu_category = et_element.findtext("CATEGORY")
|
101
|
-
odxassert(compu_category in [
|
102
|
-
"IDENTICAL",
|
103
|
-
"LINEAR",
|
104
|
-
"SCALE-LINEAR",
|
105
|
-
"TEXTTABLE",
|
106
|
-
"COMPUCODE",
|
107
|
-
"TAB-INTP",
|
108
|
-
"RAT-FUNC",
|
109
|
-
"SCALE-RAT-FUNC",
|
110
|
-
])
|
111
|
-
|
112
|
-
if et_element.find("COMPU-PHYS-TO-INTERNAL") is not None: # TODO: Is this never used?
|
113
|
-
raise NotImplementedError(f"Found COMPU-PHYS-TO-INTERNAL for category {compu_category}")
|
114
|
-
|
115
|
-
kwargs: Dict[str, Any] = {
|
116
|
-
"physical_type": physical_type,
|
117
|
-
"internal_type": internal_type,
|
118
|
-
}
|
22
|
+
compu_category = odxrequire(et_element.findtext("CATEGORY"))
|
119
23
|
|
120
24
|
if compu_category == "IDENTICAL":
|
121
|
-
|
122
|
-
internal_type
|
123
|
-
(internal_type in [DataType.A_ASCIISTRING, DataType.A_UTF8STRING] and
|
124
|
-
physical_type == DataType.A_UNICODE2STRING),
|
125
|
-
f"Internal type '{internal_type}' and physical type '{physical_type}'"
|
126
|
-
f" must be the same for compu methods of category '{compu_category}'")
|
127
|
-
return IdenticalCompuMethod(internal_type=internal_type, physical_type=physical_type)
|
128
|
-
|
129
|
-
if compu_category == "TEXTTABLE":
|
130
|
-
odxassert(physical_type == DataType.A_UNICODE2STRING)
|
131
|
-
compu_internal_to_phys = odxrequire(et_element.find("COMPU-INTERNAL-TO-PHYS"))
|
132
|
-
|
133
|
-
internal_to_phys: List[CompuScale] = []
|
134
|
-
for scale_elem in compu_internal_to_phys.iterfind("COMPU-SCALES/COMPU-SCALE"):
|
135
|
-
internal_to_phys.append(
|
136
|
-
CompuScale.compuscale_from_et(
|
137
|
-
scale_elem, doc_frags, internal_type=internal_type,
|
138
|
-
physical_type=physical_type))
|
139
|
-
compu_default_value = create_compu_default_value(
|
140
|
-
et_element.find("COMPU-DEFAULT-VALUE"), doc_frags, **kwargs)
|
141
|
-
|
142
|
-
return TexttableCompuMethod(
|
143
|
-
internal_to_phys=internal_to_phys,
|
144
|
-
compu_default_value=compu_default_value,
|
145
|
-
**kwargs,
|
146
|
-
)
|
147
|
-
|
25
|
+
return IdenticalCompuMethod.compu_method_from_et(
|
26
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
148
27
|
elif compu_category == "LINEAR":
|
149
|
-
|
150
|
-
|
151
|
-
scale_elem = odxrequire(et_element.find("COMPU-INTERNAL-TO-PHYS/COMPU-SCALES/COMPU-SCALE"))
|
152
|
-
return _parse_compu_scale_to_linear_compu_method(scale_elem, doc_frags, **kwargs)
|
153
|
-
|
28
|
+
return LinearCompuMethod.compu_method_from_et(
|
29
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
154
30
|
elif compu_category == "SCALE-LINEAR":
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
return
|
162
|
-
|
31
|
+
return ScaleLinearCompuMethod.compu_method_from_et(
|
32
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
33
|
+
elif compu_category == "RAT-FUNC":
|
34
|
+
return RatFuncCompuMethod.compu_method_from_et(
|
35
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
36
|
+
elif compu_category == "SCALE-RAT-FUNC":
|
37
|
+
return ScaleRatFuncCompuMethod.compu_method_from_et(
|
38
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
39
|
+
elif compu_category == "TEXTTABLE":
|
40
|
+
return TexttableCompuMethod.compu_method_from_et(
|
41
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
42
|
+
elif compu_category == "COMPUCODE":
|
43
|
+
return CompuCodeCompuMethod.compu_method_from_et(
|
44
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
163
45
|
elif compu_category == "TAB-INTP":
|
164
|
-
|
165
|
-
|
166
|
-
for scale_elem in et_element.iterfind("COMPU-INTERNAL-TO-PHYS/COMPU-SCALES/COMPU-SCALE"):
|
167
|
-
internal_point = internal_type.from_string(
|
168
|
-
odxrequire(scale_elem.findtext("LOWER-LIMIT")))
|
169
|
-
physical_point = physical_type.create_from_et(
|
170
|
-
odxrequire(scale_elem.find("COMPU-CONST")))
|
171
|
-
|
172
|
-
if not isinstance(internal_point, (float, int)):
|
173
|
-
odxraise()
|
174
|
-
if not isinstance(physical_point, (float, int)):
|
175
|
-
odxraise()
|
176
|
-
|
177
|
-
internal_points.append(internal_point)
|
178
|
-
physical_points.append(physical_point)
|
179
|
-
|
180
|
-
return TabIntpCompuMethod(
|
181
|
-
internal_points=internal_points, physical_points=physical_points, **kwargs)
|
46
|
+
return TabIntpCompuMethod.compu_method_from_et(
|
47
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
182
48
|
|
183
49
|
# TODO: Implement all categories (never instantiate the CompuMethod base class!)
|
184
50
|
odxraise(f"Warning: Computation category {compu_category} is not implemented!")
|
185
51
|
|
186
|
-
return IdenticalCompuMethod(
|
52
|
+
return IdenticalCompuMethod.compu_method_from_et(
|
53
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
@@ -1,16 +1,41 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
+
from typing import List
|
4
|
+
from xml.etree import ElementTree
|
3
5
|
|
4
|
-
from ..
|
5
|
-
from
|
6
|
+
from ..exceptions import odxassert
|
7
|
+
from ..odxlink import OdxDocFragment
|
8
|
+
from ..odxtypes import AtomicOdxType, DataType
|
9
|
+
from ..utils import dataclass_fields_asdict
|
10
|
+
from .compumethod import CompuMethod
|
6
11
|
|
7
12
|
|
8
13
|
@dataclass
|
9
14
|
class IdenticalCompuMethod(CompuMethod):
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
15
|
+
"""Identical compu methods just pass through the internal value.
|
16
|
+
|
17
|
+
For details, refer to ASAM specification MCD-2 D (ODX), section 7.3.6.6.2.
|
18
|
+
"""
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
|
22
|
+
internal_type: DataType,
|
23
|
+
physical_type: DataType) -> "IdenticalCompuMethod":
|
24
|
+
cm = CompuMethod.compu_method_from_et(
|
25
|
+
et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
|
26
|
+
kwargs = dataclass_fields_asdict(cm)
|
27
|
+
|
28
|
+
odxassert(
|
29
|
+
internal_type == physical_type or
|
30
|
+
(internal_type
|
31
|
+
in [DataType.A_ASCIISTRING, DataType.A_UTF8STRING, DataType.A_UNICODE2STRING] and
|
32
|
+
physical_type
|
33
|
+
in [DataType.A_ASCIISTRING, DataType.A_UTF8STRING, DataType.A_UNICODE2STRING]),
|
34
|
+
f"Internal type and physical type must be the same for compu methods of category "
|
35
|
+
f"'{cm.category}' (internal type: '{internal_type.value}', physical type: "
|
36
|
+
f"'{physical_type.value}')")
|
37
|
+
|
38
|
+
return IdenticalCompuMethod(**kwargs)
|
14
39
|
|
15
40
|
def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> AtomicOdxType:
|
16
41
|
return physical_value
|