odxtools 9.4.1__py3-none-any.whl → 9.6.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.
Files changed (113) hide show
  1. odxtools/additionalaudience.py +2 -2
  2. odxtools/admindata.py +3 -0
  3. odxtools/audience.py +9 -13
  4. odxtools/basecomparam.py +1 -2
  5. odxtools/basevariantpattern.py +38 -0
  6. odxtools/basicstructure.py +34 -35
  7. odxtools/commrelation.py +2 -1
  8. odxtools/companydata.py +1 -2
  9. odxtools/companyspecificinfo.py +3 -0
  10. odxtools/comparam.py +16 -8
  11. odxtools/comparaminstance.py +12 -12
  12. odxtools/comparamspec.py +4 -3
  13. odxtools/comparamsubset.py +26 -24
  14. odxtools/compumethods/compuconst.py +4 -4
  15. odxtools/compumethods/limit.py +9 -9
  16. odxtools/compumethods/linearsegment.py +8 -8
  17. odxtools/dataobjectproperty.py +16 -18
  18. odxtools/description.py +4 -2
  19. odxtools/determinenumberofitems.py +4 -4
  20. odxtools/diagcodedtype.py +20 -20
  21. odxtools/diagcomm.py +61 -41
  22. odxtools/diagdatadictionaryspec.py +51 -55
  23. odxtools/diaglayercontainer.py +25 -25
  24. odxtools/diaglayers/basevariant.py +5 -0
  25. odxtools/diaglayers/basevariantraw.py +7 -1
  26. odxtools/diaglayers/diaglayerraw.py +26 -27
  27. odxtools/diaglayers/ecuvariant.py +16 -0
  28. odxtools/diagnostictroublecode.py +13 -10
  29. odxtools/diagservice.py +48 -50
  30. odxtools/diagvariable.py +10 -8
  31. odxtools/docrevision.py +5 -5
  32. odxtools/dtcdop.py +17 -17
  33. odxtools/dynamicendmarkerfield.py +8 -8
  34. odxtools/dynamiclengthfield.py +2 -0
  35. odxtools/dyndefinedspec.py +21 -8
  36. odxtools/ecuvariantpattern.py +20 -9
  37. odxtools/encodestate.py +3 -3
  38. odxtools/endofpdufield.py +7 -9
  39. odxtools/environmentdatadescription.py +9 -20
  40. odxtools/field.py +21 -21
  41. odxtools/inputparam.py +15 -14
  42. odxtools/leadinglengthinfotype.py +4 -4
  43. odxtools/matchingbasevariantparameter.py +38 -0
  44. odxtools/matchingparameter.py +108 -28
  45. odxtools/minmaxlengthtype.py +6 -6
  46. odxtools/multiplexer.py +38 -39
  47. odxtools/multiplexercase.py +3 -6
  48. odxtools/multiplexerdefaultcase.py +3 -6
  49. odxtools/multiplexerswitchkey.py +4 -4
  50. odxtools/negoutputparam.py +6 -9
  51. odxtools/odxlink.py +21 -5
  52. odxtools/odxtypes.py +7 -6
  53. odxtools/outputparam.py +9 -8
  54. odxtools/parameterinfo.py +1 -1
  55. odxtools/parameters/codedconstparameter.py +28 -27
  56. odxtools/parameters/dynamicparameter.py +9 -9
  57. odxtools/parameters/lengthkeyparameter.py +18 -18
  58. odxtools/parameters/matchingrequestparameter.py +15 -15
  59. odxtools/parameters/nrcconstparameter.py +32 -24
  60. odxtools/parameters/parameter.py +35 -37
  61. odxtools/parameters/parameterwithdop.py +6 -6
  62. odxtools/parameters/physicalconstantparameter.py +19 -20
  63. odxtools/parameters/reservedparameter.py +10 -11
  64. odxtools/parameters/systemparameter.py +10 -11
  65. odxtools/parameters/tableentryparameter.py +19 -20
  66. odxtools/parameters/tablekeyparameter.py +0 -2
  67. odxtools/parameters/tablestructparameter.py +27 -21
  68. odxtools/parameters/valueparameter.py +20 -20
  69. odxtools/parentref.py +6 -7
  70. odxtools/physicaldimension.py +11 -11
  71. odxtools/physicaltype.py +9 -14
  72. odxtools/preconditionstateref.py +85 -0
  73. odxtools/progcode.py +1 -2
  74. odxtools/protstack.py +4 -4
  75. odxtools/relateddoc.py +3 -4
  76. odxtools/scaleconstr.py +0 -1
  77. odxtools/singleecujob.py +8 -4
  78. odxtools/specialdata.py +10 -9
  79. odxtools/specialdatagroup.py +1 -0
  80. odxtools/standardlengthtype.py +18 -18
  81. odxtools/statechart.py +10 -6
  82. odxtools/statemachine.py +186 -0
  83. odxtools/statetransitionref.py +231 -0
  84. odxtools/structure.py +4 -4
  85. odxtools/subcomponent.py +78 -11
  86. odxtools/table.py +23 -13
  87. odxtools/tablerow.py +86 -69
  88. odxtools/teammember.py +4 -4
  89. odxtools/templates/macros/printBaseVariant.xml.jinja2 +4 -9
  90. odxtools/templates/macros/printBaseVariantPattern.xml.jinja2 +32 -0
  91. odxtools/templates/macros/printCompanyData.xml.jinja2 +2 -2
  92. odxtools/templates/macros/printComparam.xml.jinja2 +3 -5
  93. odxtools/templates/macros/printDOP.xml.jinja2 +4 -1
  94. odxtools/templates/macros/printDiagComm.xml.jinja2 +6 -5
  95. odxtools/templates/macros/printEcuVariantPattern.xml.jinja2 +7 -6
  96. odxtools/templates/macros/printParam.xml.jinja2 +5 -5
  97. odxtools/templates/macros/printPreConditionStateRef.xml.jinja2 +18 -0
  98. odxtools/templates/macros/printStateTransitionRef.xml.jinja2 +18 -0
  99. odxtools/templates/macros/printTable.xml.jinja2 +13 -9
  100. odxtools/text.py +35 -0
  101. odxtools/unit.py +1 -3
  102. odxtools/unitgroup.py +6 -8
  103. odxtools/variantmatcher.py +209 -0
  104. odxtools/variantpattern.py +38 -0
  105. odxtools/version.py +2 -2
  106. {odxtools-9.4.1.dist-info → odxtools-9.6.0.dist-info}/METADATA +3 -2
  107. {odxtools-9.4.1.dist-info → odxtools-9.6.0.dist-info}/RECORD +111 -102
  108. {odxtools-9.4.1.dist-info → odxtools-9.6.0.dist-info}/WHEEL +1 -1
  109. odxtools/createecuvariantpatterns.py +0 -18
  110. odxtools/ecuvariantmatcher.py +0 -171
  111. {odxtools-9.4.1.dist-info → odxtools-9.6.0.dist-info}/entry_points.txt +0 -0
  112. {odxtools-9.4.1.dist-info → odxtools-9.6.0.dist-info/licenses}/LICENSE +0 -0
  113. {odxtools-9.4.1.dist-info → odxtools-9.6.0.dist-info}/top_level.txt +0 -0
@@ -34,8 +34,31 @@ class NrcConstParameter(Parameter):
34
34
 
35
35
  """
36
36
 
37
+ coded_values_raw: List[str]
37
38
  diag_coded_type: DiagCodedType
38
- coded_values: List[AtomicOdxType]
39
+
40
+ @property
41
+ @override
42
+ def parameter_type(self) -> ParameterType:
43
+ return "NRC-CONST"
44
+
45
+ @property
46
+ @override
47
+ def is_required(self) -> bool:
48
+ return False
49
+
50
+ @property
51
+ @override
52
+ def is_settable(self) -> bool:
53
+ return False
54
+
55
+ @property
56
+ def internal_data_type(self) -> DataType:
57
+ return self.diag_coded_type.base_data_type
58
+
59
+ @property
60
+ def coded_values(self) -> List[AtomicOdxType]:
61
+ return self._coded_values
39
62
 
40
63
  @staticmethod
41
64
  @override
@@ -44,20 +67,19 @@ class NrcConstParameter(Parameter):
44
67
 
45
68
  kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
46
69
 
70
+ coded_values_raw = [
71
+ odxrequire(x.text) for x in et_element.iterfind("CODED-VALUES/CODED-VALUE")
72
+ ]
47
73
  dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
48
74
  diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
49
- coded_values = [
50
- diag_coded_type.base_data_type.from_string(odxrequire(val.text))
51
- for val in et_element.iterfind("CODED-VALUES/CODED-VALUE")
52
- ]
53
75
 
54
76
  return NrcConstParameter(
55
- diag_coded_type=diag_coded_type, coded_values=coded_values, **kwargs)
77
+ coded_values_raw=coded_values_raw, diag_coded_type=diag_coded_type, **kwargs)
56
78
 
57
- @property
58
- @override
59
- def parameter_type(self) -> ParameterType:
60
- return "NRC-CONST"
79
+ def __post_init__(self) -> None:
80
+ self._coded_values = [
81
+ self.diag_coded_type.base_data_type.from_string(val) for val in self.coded_values_raw
82
+ ]
61
83
 
62
84
  @override
63
85
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
@@ -71,20 +93,6 @@ class NrcConstParameter(Parameter):
71
93
  def get_static_bit_length(self) -> Optional[int]:
72
94
  return self.diag_coded_type.get_static_bit_length()
73
95
 
74
- @property
75
- def internal_data_type(self) -> DataType:
76
- return self.diag_coded_type.base_data_type
77
-
78
- @property
79
- @override
80
- def is_required(self) -> bool:
81
- return False
82
-
83
- @property
84
- @override
85
- def is_settable(self) -> bool:
86
- return False
87
-
88
96
  @override
89
97
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
90
98
  encode_state: EncodeState) -> None:
@@ -42,11 +42,39 @@ class Parameter(NamedElement):
42
42
  non-positionable parameter types.
43
43
 
44
44
  """
45
+ sdgs: List[SpecialDataGroup]
46
+ semantic: Optional[str]
45
47
  oid: Optional[str]
46
48
  byte_position: Optional[int]
47
49
  bit_position: Optional[int]
48
- semantic: Optional[str]
49
- sdgs: List[SpecialDataGroup]
50
+
51
+ @property
52
+ def parameter_type(self) -> ParameterType:
53
+ raise NotImplementedError(
54
+ ".parameter_type is not implemented by the concrete parameter class")
55
+
56
+ @property
57
+ def is_required(self) -> bool:
58
+ """True if the parameter must be explicitly specified when
59
+ encoding a message.
60
+
61
+ Required parameters are always settable, and parameters which
62
+ have a default value are settable but not required to be
63
+ specified.
64
+
65
+ """
66
+ raise NotImplementedError(".is_required is not implemented by the concrete parameter class")
67
+
68
+ @property
69
+ def is_settable(self) -> bool:
70
+ """True if the parameter can be specified when encoding a
71
+ message.
72
+
73
+ Required parameters are always settable, and parameters which
74
+ have a default value are settable but not required to be
75
+ specified.
76
+ """
77
+ raise NotImplementedError(".is_settable is not implemented by the concrete parameter class")
50
78
 
51
79
  @staticmethod
52
80
  @override
@@ -54,24 +82,22 @@ class Parameter(NamedElement):
54
82
 
55
83
  kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
56
84
 
57
- oid = et_element.get("OID")
58
- semantic = et_element.get("SEMANTIC")
59
85
  sdgs = [
60
86
  SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
61
87
  ]
62
-
88
+ semantic = et_element.attrib.get("SEMANTIC")
89
+ oid = et_element.attrib.get("OID")
63
90
  byte_position_str = et_element.findtext("BYTE-POSITION")
64
- bit_position_str = et_element.findtext("BIT-POSITION")
65
-
66
91
  byte_position = int(byte_position_str) if byte_position_str is not None else None
92
+ bit_position_str = et_element.findtext("BIT-POSITION")
67
93
  bit_position = int(bit_position_str) if bit_position_str is not None else None
68
94
 
69
95
  return Parameter(
96
+ sdgs=sdgs,
97
+ semantic=semantic,
70
98
  oid=oid,
71
99
  byte_position=byte_position,
72
100
  bit_position=bit_position,
73
- semantic=semantic,
74
- sdgs=sdgs,
75
101
  **kwargs)
76
102
 
77
103
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
@@ -90,37 +116,9 @@ class Parameter(NamedElement):
90
116
  for sdg in self.sdgs:
91
117
  sdg._resolve_snrefs(context)
92
118
 
93
- @property
94
- def parameter_type(self) -> ParameterType:
95
- raise NotImplementedError(
96
- ".parameter_type is not implemented by the concrete parameter class")
97
-
98
119
  def get_static_bit_length(self) -> Optional[int]:
99
120
  return None
100
121
 
101
- @property
102
- def is_required(self) -> bool:
103
- """True if the parameter must be explicitly specified when
104
- encoding a message.
105
-
106
- Required parameters are always settable, and parameters which
107
- have a default value are settable but not required to be
108
- specified.
109
-
110
- """
111
- raise NotImplementedError(".is_required is not implemented by the concrete parameter class")
112
-
113
- @property
114
- def is_settable(self) -> bool:
115
- """True if the parameter can be specified when encoding a
116
- message.
117
-
118
- Required parameters are always settable, and parameters which
119
- have a default value are settable but not required to be
120
- specified.
121
- """
122
- raise NotImplementedError(".is_settable is not implemented by the concrete parameter class")
123
-
124
122
  @final
125
123
  def encode_into_pdu(self, physical_value: Optional[ParameterValue],
126
124
  encode_state: EncodeState) -> None:
@@ -24,6 +24,12 @@ class ParameterWithDOP(Parameter):
24
24
  dop_ref: Optional[OdxLinkRef]
25
25
  dop_snref: Optional[str]
26
26
 
27
+ @property
28
+ def dop(self) -> DopBase:
29
+ """This is usually a DataObjectProperty or a Structure object"""
30
+
31
+ return self._dop
32
+
27
33
  @staticmethod
28
34
  @override
29
35
  def from_et(et_element: ElementTree.Element,
@@ -63,12 +69,6 @@ class ParameterWithDOP(Parameter):
63
69
  ddds = odxrequire(context.diag_layer).diag_data_dictionary_spec
64
70
  self._dop = resolve_snref(self.dop_snref, ddds.all_data_object_properties, DopBase)
65
71
 
66
- @property
67
- def dop(self) -> DopBase:
68
- """This is usually a DataObjectProperty or a Structure object"""
69
-
70
- return self._dop
71
-
72
72
  @override
73
73
  def get_static_bit_length(self) -> Optional[int]:
74
74
  if self._dop is not None:
@@ -19,9 +19,27 @@ from .parameterwithdop import ParameterWithDOP
19
19
 
20
20
  @dataclass
21
21
  class PhysicalConstantParameter(ParameterWithDOP):
22
-
23
22
  physical_constant_value_raw: str
24
23
 
24
+ @property
25
+ @override
26
+ def parameter_type(self) -> ParameterType:
27
+ return "PHYS-CONST"
28
+
29
+ @property
30
+ @override
31
+ def is_required(self) -> bool:
32
+ return False
33
+
34
+ @property
35
+ @override
36
+ def is_settable(self) -> bool:
37
+ return False
38
+
39
+ @property
40
+ def physical_constant_value(self) -> ParameterValue:
41
+ return self._physical_constant_value
42
+
25
43
  @staticmethod
26
44
  @override
27
45
  def from_et(et_element: ElementTree.Element,
@@ -34,11 +52,6 @@ class PhysicalConstantParameter(ParameterWithDOP):
34
52
  return PhysicalConstantParameter(
35
53
  physical_constant_value_raw=physical_constant_value_raw, **kwargs)
36
54
 
37
- @property
38
- @override
39
- def parameter_type(self) -> ParameterType:
40
- return "PHYS-CONST"
41
-
42
55
  @override
43
56
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
44
57
  return super()._build_odxlinks()
@@ -58,20 +71,6 @@ class PhysicalConstantParameter(ParameterWithDOP):
58
71
  base_data_type = dop.physical_type.base_data_type
59
72
  self._physical_constant_value = base_data_type.from_string(self.physical_constant_value_raw)
60
73
 
61
- @property
62
- def physical_constant_value(self) -> ParameterValue:
63
- return self._physical_constant_value
64
-
65
- @property
66
- @override
67
- def is_required(self) -> bool:
68
- return False
69
-
70
- @property
71
- @override
72
- def is_settable(self) -> bool:
73
- return False
74
-
75
74
  @override
76
75
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
77
76
  encode_state: EncodeState) -> None:
@@ -18,17 +18,6 @@ from .parameter import Parameter, ParameterType
18
18
  class ReservedParameter(Parameter):
19
19
  bit_length: int
20
20
 
21
- @staticmethod
22
- @override
23
- def from_et(et_element: ElementTree.Element,
24
- doc_frags: List[OdxDocFragment]) -> "ReservedParameter":
25
-
26
- kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
27
-
28
- bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
29
-
30
- return ReservedParameter(bit_length=bit_length, **kwargs)
31
-
32
21
  @property
33
22
  @override
34
23
  def parameter_type(self) -> ParameterType:
@@ -44,6 +33,16 @@ class ReservedParameter(Parameter):
44
33
  def is_settable(self) -> bool:
45
34
  return False
46
35
 
36
+ @staticmethod
37
+ @override
38
+ def from_et(et_element: ElementTree.Element,
39
+ doc_frags: List[OdxDocFragment]) -> "ReservedParameter":
40
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
41
+
42
+ bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
43
+
44
+ return ReservedParameter(bit_length=bit_length, **kwargs)
45
+
47
46
  @override
48
47
  def get_static_bit_length(self) -> Optional[int]:
49
48
  return self.bit_length
@@ -29,17 +29,6 @@ PREDEFINED_SYSPARAM_VALUES = [
29
29
  class SystemParameter(ParameterWithDOP):
30
30
  sysparam: str
31
31
 
32
- @staticmethod
33
- @override
34
- def from_et(et_element: ElementTree.Element,
35
- doc_frags: List[OdxDocFragment]) -> "SystemParameter":
36
-
37
- kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
38
-
39
- sysparam = odxrequire(et_element.get("SYSPARAM"))
40
-
41
- return SystemParameter(sysparam=sysparam, **kwargs)
42
-
43
32
  @property
44
33
  @override
45
34
  def parameter_type(self) -> ParameterType:
@@ -58,6 +47,16 @@ class SystemParameter(ParameterWithDOP):
58
47
  def is_settable(self) -> bool:
59
48
  return True
60
49
 
50
+ @staticmethod
51
+ @override
52
+ def from_et(et_element: ElementTree.Element,
53
+ doc_frags: List[OdxDocFragment]) -> "SystemParameter":
54
+ kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
55
+
56
+ sysparam = odxrequire(et_element.get("SYSPARAM"))
57
+
58
+ return SystemParameter(sysparam=sysparam, **kwargs)
59
+
61
60
  @override
62
61
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
63
62
  encode_state: EncodeState) -> None:
@@ -28,11 +28,29 @@ class TableEntryParameter(Parameter):
28
28
  target: RowFragment
29
29
  table_row_ref: OdxLinkRef
30
30
 
31
+ @property
32
+ @override
33
+ def parameter_type(self) -> ParameterType:
34
+ return "TABLE-ENTRY"
35
+
36
+ @property
37
+ @override
38
+ def is_required(self) -> bool:
39
+ raise NotImplementedError("TableEntryParameter.is_required is not implemented yet.")
40
+
41
+ @property
42
+ @override
43
+ def is_settable(self) -> bool:
44
+ raise NotImplementedError("TableEntryParameter.is_settable is not implemented yet.")
45
+
46
+ @property
47
+ def table_row(self) -> "TableRow":
48
+ return self._table_row
49
+
31
50
  @staticmethod
32
51
  @override
33
52
  def from_et(et_element: ElementTree.Element,
34
53
  doc_frags: List[OdxDocFragment]) -> "TableEntryParameter":
35
-
36
54
  kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
37
55
 
38
56
  target_str = odxrequire(et_element.findtext("TARGET"))
@@ -54,30 +72,11 @@ class TableEntryParameter(Parameter):
54
72
  else:
55
73
  self._table_row = odxlinks.resolve(self.table_row_ref)
56
74
 
57
- @property
58
- @override
59
- def parameter_type(self) -> ParameterType:
60
- return "TABLE-ENTRY"
61
-
62
- @property
63
- @override
64
- def is_required(self) -> bool:
65
- raise NotImplementedError("TableEntryParameter.is_required is not implemented yet.")
66
-
67
- @property
68
- @override
69
- def is_settable(self) -> bool:
70
- raise NotImplementedError("TableEntryParameter.is_settable is not implemented yet.")
71
-
72
75
  @override
73
76
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
74
77
  encode_state: EncodeState) -> None:
75
78
  raise NotImplementedError("Encoding a TableEntryParameter is not implemented yet.")
76
79
 
77
- @property
78
- def table_row(self) -> "TableRow":
79
- return self._table_row
80
-
81
80
  @override
82
81
  def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
83
82
  raise NotImplementedError("Decoding a TableEntryParameter is not implemented yet.")
@@ -38,7 +38,6 @@ class TableKeyParameter(Parameter):
38
38
  @override
39
39
  def from_et(et_element: ElementTree.Element,
40
40
  doc_frags: List[OdxDocFragment]) -> "TableKeyParameter":
41
-
42
41
  kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
43
42
 
44
43
  odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
@@ -201,7 +200,6 @@ class TableKeyParameter(Parameter):
201
200
  encode_state.cursor_bit_position = 0
202
201
 
203
202
  def encode_value_into_pdu(self, encode_state: EncodeState) -> None:
204
-
205
203
  key_dop = self.table.key_dop
206
204
  if key_dop is None:
207
205
  odxraise(
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional, cast
3
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -15,13 +15,38 @@ from ..utils import dataclass_fields_asdict
15
15
  from .parameter import Parameter, ParameterType
16
16
  from .tablekeyparameter import TableKeyParameter
17
17
 
18
+ if TYPE_CHECKING:
19
+ from ..table import Table
20
+
18
21
 
19
22
  @dataclass
20
23
  class TableStructParameter(Parameter):
21
-
22
24
  table_key_ref: Optional[OdxLinkRef]
23
25
  table_key_snref: Optional[str]
24
26
 
27
+ @property
28
+ @override
29
+ def parameter_type(self) -> ParameterType:
30
+ return "TABLE-STRUCT"
31
+
32
+ @property
33
+ def table(self) -> "Table":
34
+ return self._table_key.table
35
+
36
+ @property
37
+ def table_key(self) -> TableKeyParameter:
38
+ return self._table_key
39
+
40
+ @property
41
+ @override
42
+ def is_required(self) -> bool:
43
+ return True
44
+
45
+ @property
46
+ @override
47
+ def is_settable(self) -> bool:
48
+ return True
49
+
25
50
  @staticmethod
26
51
  @override
27
52
  def from_et(et_element: ElementTree.Element,
@@ -41,11 +66,6 @@ class TableStructParameter(Parameter):
41
66
  if self.table_key_ref is None and self.table_key_snref is None:
42
67
  odxraise("Either table_key_ref or table_key_snref must be defined.")
43
68
 
44
- @property
45
- @override
46
- def parameter_type(self) -> ParameterType:
47
- return "TABLE-STRUCT"
48
-
49
69
  @override
50
70
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
51
71
  return super()._build_odxlinks()
@@ -65,20 +85,6 @@ class TableStructParameter(Parameter):
65
85
  self._table_key = resolve_snref(self.table_key_snref, odxrequire(context.parameters),
66
86
  TableKeyParameter)
67
87
 
68
- @property
69
- def table_key(self) -> TableKeyParameter:
70
- return self._table_key
71
-
72
- @property
73
- @override
74
- def is_required(self) -> bool:
75
- return True
76
-
77
- @property
78
- @override
79
- def is_settable(self) -> bool:
80
- return True
81
-
82
88
  @override
83
89
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
84
90
  encode_state: EncodeState) -> None:
@@ -20,8 +20,24 @@ from .parameterwithdop import ParameterWithDOP
20
20
  class ValueParameter(ParameterWithDOP):
21
21
  physical_default_value_raw: Optional[str]
22
22
 
23
- def __post_init__(self) -> None:
24
- self._physical_default_value: Optional[AtomicOdxType] = None
23
+ @property
24
+ @override
25
+ def parameter_type(self) -> ParameterType:
26
+ return "VALUE"
27
+
28
+ @property
29
+ def physical_default_value(self) -> Optional[AtomicOdxType]:
30
+ return self._physical_default_value
31
+
32
+ @property
33
+ @override
34
+ def is_required(self) -> bool:
35
+ return self._physical_default_value is None
36
+
37
+ @property
38
+ @override
39
+ def is_settable(self) -> bool:
40
+ return True
25
41
 
26
42
  @staticmethod
27
43
  @override
@@ -34,10 +50,8 @@ class ValueParameter(ParameterWithDOP):
34
50
 
35
51
  return ValueParameter(physical_default_value_raw=physical_default_value_raw, **kwargs)
36
52
 
37
- @property
38
- @override
39
- def parameter_type(self) -> ParameterType:
40
- return "VALUE"
53
+ def __post_init__(self) -> None:
54
+ self._physical_default_value: Optional[AtomicOdxType] = None
41
55
 
42
56
  @override
43
57
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
@@ -60,20 +74,6 @@ class ValueParameter(ParameterWithDOP):
60
74
  self._physical_default_value = base_data_type.from_string(
61
75
  self.physical_default_value_raw)
62
76
 
63
- @property
64
- def physical_default_value(self) -> Optional[AtomicOdxType]:
65
- return self._physical_default_value
66
-
67
- @property
68
- @override
69
- def is_required(self) -> bool:
70
- return self._physical_default_value is None
71
-
72
- @property
73
- @override
74
- def is_settable(self) -> bool:
75
- return True
76
-
77
77
  @override
78
78
  def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
79
79
  encode_state: EncodeState) -> None:
odxtools/parentref.py CHANGED
@@ -37,6 +37,12 @@ class ParentRef:
37
37
  "NOT-INHERITED-DIAG-COMM/"
38
38
  "DIAG-COMM-SNREF")
39
39
  ]
40
+ not_inherited_variables = [
41
+ odxrequire(el.get("SHORT-NAME"))
42
+ for el in et_element.iterfind("NOT-INHERITED-VARIABLES/"
43
+ "NOT-INHERITED-VARIABLE/"
44
+ "DIAG-VARIABLE-SNREF")
45
+ ]
40
46
  not_inherited_dops = [
41
47
  odxrequire(el.get("SHORT-NAME")) for el in et_element.iterfind("NOT-INHERITED-DOPS/"
42
48
  "NOT-INHERITED-DOP/"
@@ -47,13 +53,6 @@ class ParentRef:
47
53
  "NOT-INHERITED-TABLE/"
48
54
  "TABLE-SNREF")
49
55
  ]
50
- not_inherited_variables = [
51
- odxrequire(el.get("SHORT-NAME"))
52
- for el in et_element.iterfind("NOT-INHERITED-VARIABLES/"
53
- "NOT-INHERITED-VARIABLE/"
54
- "DIAG-VARIABLE-SNREF")
55
- ]
56
-
57
56
  not_inherited_global_neg_responses = [
58
57
  odxrequire(el.get("SHORT-NAME"))
59
58
  for el in et_element.iterfind("NOT-INHERITED-GLOBAL-NEG-RESPONSES/"
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, List
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
@@ -41,24 +41,24 @@ class PhysicalDimension(IdentifiableElement):
41
41
  )
42
42
  ```
43
43
  """
44
- length_exp: int
45
- mass_exp: int
46
- time_exp: int
47
- current_exp: int
48
- temperature_exp: int
49
- molar_amount_exp: int
50
- luminous_intensity_exp: int
44
+ length_exp: Optional[int]
45
+ mass_exp: Optional[int]
46
+ time_exp: Optional[int]
47
+ current_exp: Optional[int]
48
+ temperature_exp: Optional[int]
49
+ molar_amount_exp: Optional[int]
50
+ luminous_intensity_exp: Optional[int]
51
51
 
52
52
  @staticmethod
53
53
  def from_et(et_element: ElementTree.Element,
54
54
  doc_frags: List[OdxDocFragment]) -> "PhysicalDimension":
55
55
  kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
56
56
 
57
- def read_optional_int(element: ElementTree.Element, name: str) -> int:
58
- if val_str := element.findtext(name):
57
+ def read_optional_int(element: ElementTree.Element, name: str) -> Optional[int]:
58
+ if (val_str := element.findtext(name)) is not None:
59
59
  return int(val_str)
60
60
  else:
61
- return 0
61
+ return None
62
62
 
63
63
  length_exp = read_optional_int(et_element, "LENGTH-EXP")
64
64
  mass_exp = read_optional_int(et_element, "MASS-EXP")
odxtools/physicaltype.py CHANGED
@@ -39,6 +39,11 @@ class PhysicalType:
39
39
  PhysicalType(DataType.A_FLOAT64, precision=2)
40
40
  """
41
41
 
42
+ precision: Optional[int]
43
+ """Number of digits after the decimal point to display to the user
44
+ The precision is only applicable if the base data type is A_FLOAT32 or A_FLOAT64.
45
+ """
46
+
42
47
  base_data_type: DataType
43
48
 
44
49
  display_radix: Optional[Radix]
@@ -46,18 +51,11 @@ class PhysicalType:
46
51
  The display radix is only applicable if the base data type is A_UINT32.
47
52
  """
48
53
 
49
- precision: Optional[int]
50
- """Number of digits after the decimal point to display to the user
51
- The precision is only applicable if the base data type is A_FLOAT32 or A_FLOAT64.
52
- """
53
-
54
- def __post_init__(self) -> None:
55
- self.base_data_type = DataType(self.base_data_type)
56
- if self.display_radix is not None:
57
- self.display_radix = Radix(self.display_radix)
58
-
59
54
  @staticmethod
60
55
  def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "PhysicalType":
56
+ precision_str = et_element.findtext("PRECISION")
57
+ precision = int(precision_str) if precision_str is not None else None
58
+
61
59
  base_data_type_str = et_element.get("BASE-DATA-TYPE")
62
60
  if base_data_type_str not in DataType.__members__:
63
61
  odxraise(f"Encountered unknown base data type '{base_data_type_str}'")
@@ -71,8 +69,5 @@ class PhysicalType:
71
69
  else:
72
70
  display_radix = None
73
71
 
74
- precision_str = et_element.findtext("PRECISION")
75
- precision = int(precision_str) if precision_str is not None else None
76
-
77
72
  return PhysicalType(
78
- base_data_type=base_data_type, display_radix=display_radix, precision=precision)
73
+ precision=precision, base_data_type=base_data_type, display_radix=display_radix)