odxtools 6.6.1__py3-none-any.whl → 9.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. odxtools/__init__.py +7 -5
  2. odxtools/additionalaudience.py +3 -5
  3. odxtools/admindata.py +5 -7
  4. odxtools/audience.py +10 -13
  5. odxtools/basecomparam.py +3 -5
  6. odxtools/basicstructure.py +55 -241
  7. odxtools/cli/_parser_utils.py +16 -1
  8. odxtools/cli/_print_utils.py +169 -134
  9. odxtools/cli/browse.py +127 -103
  10. odxtools/cli/compare.py +114 -87
  11. odxtools/cli/decode.py +2 -1
  12. odxtools/cli/dummy_sub_parser.py +3 -1
  13. odxtools/cli/find.py +2 -1
  14. odxtools/cli/list.py +26 -16
  15. odxtools/cli/main.py +1 -0
  16. odxtools/cli/snoop.py +32 -6
  17. odxtools/codec.py +211 -0
  18. odxtools/commrelation.py +122 -0
  19. odxtools/companydata.py +5 -7
  20. odxtools/companydocinfo.py +7 -8
  21. odxtools/companyrevisioninfo.py +3 -5
  22. odxtools/companyspecificinfo.py +8 -9
  23. odxtools/comparam.py +4 -6
  24. odxtools/comparaminstance.py +14 -14
  25. odxtools/comparamspec.py +16 -54
  26. odxtools/comparamsubset.py +22 -62
  27. odxtools/complexcomparam.py +5 -7
  28. odxtools/compumethods/compucodecompumethod.py +63 -0
  29. odxtools/compumethods/compuconst.py +31 -0
  30. odxtools/compumethods/compudefaultvalue.py +27 -0
  31. odxtools/compumethods/compuinternaltophys.py +56 -0
  32. odxtools/compumethods/compuinversevalue.py +7 -0
  33. odxtools/compumethods/compumethod.py +94 -15
  34. odxtools/compumethods/compuphystointernal.py +56 -0
  35. odxtools/compumethods/compurationalcoeffs.py +20 -9
  36. odxtools/compumethods/compuscale.py +67 -32
  37. odxtools/compumethods/createanycompumethod.py +31 -172
  38. odxtools/compumethods/identicalcompumethod.py +31 -6
  39. odxtools/compumethods/limit.py +70 -36
  40. odxtools/compumethods/linearcompumethod.py +70 -181
  41. odxtools/compumethods/linearsegment.py +190 -0
  42. odxtools/compumethods/ratfunccompumethod.py +106 -0
  43. odxtools/compumethods/ratfuncsegment.py +87 -0
  44. odxtools/compumethods/scalelinearcompumethod.py +132 -26
  45. odxtools/compumethods/scaleratfunccompumethod.py +113 -0
  46. odxtools/compumethods/tabintpcompumethod.py +123 -92
  47. odxtools/compumethods/texttablecompumethod.py +117 -57
  48. odxtools/createanydiagcodedtype.py +10 -67
  49. odxtools/database.py +167 -87
  50. odxtools/dataobjectproperty.py +25 -32
  51. odxtools/decodestate.py +14 -17
  52. odxtools/description.py +47 -0
  53. odxtools/determinenumberofitems.py +4 -5
  54. odxtools/diagcodedtype.py +37 -106
  55. odxtools/diagcomm.py +24 -12
  56. odxtools/diagdatadictionaryspec.py +120 -96
  57. odxtools/diaglayercontainer.py +46 -54
  58. odxtools/diaglayers/basevariant.py +128 -0
  59. odxtools/diaglayers/basevariantraw.py +123 -0
  60. odxtools/diaglayers/diaglayer.py +432 -0
  61. odxtools/{diaglayerraw.py → diaglayers/diaglayerraw.py} +105 -120
  62. odxtools/diaglayers/diaglayertype.py +42 -0
  63. odxtools/diaglayers/ecushareddata.py +96 -0
  64. odxtools/diaglayers/ecushareddataraw.py +87 -0
  65. odxtools/diaglayers/ecuvariant.py +124 -0
  66. odxtools/diaglayers/ecuvariantraw.py +129 -0
  67. odxtools/diaglayers/functionalgroup.py +110 -0
  68. odxtools/diaglayers/functionalgroupraw.py +106 -0
  69. odxtools/{diaglayer.py → diaglayers/hierarchyelement.py} +273 -472
  70. odxtools/diaglayers/hierarchyelementraw.py +58 -0
  71. odxtools/diaglayers/protocol.py +64 -0
  72. odxtools/diaglayers/protocolraw.py +91 -0
  73. odxtools/diagnostictroublecode.py +8 -9
  74. odxtools/diagservice.py +57 -44
  75. odxtools/diagvariable.py +113 -0
  76. odxtools/docrevision.py +5 -7
  77. odxtools/dopbase.py +15 -15
  78. odxtools/dtcdop.py +170 -50
  79. odxtools/dynamicendmarkerfield.py +134 -0
  80. odxtools/dynamiclengthfield.py +47 -42
  81. odxtools/dyndefinedspec.py +177 -0
  82. odxtools/dynenddopref.py +38 -0
  83. odxtools/ecuvariantmatcher.py +6 -7
  84. odxtools/element.py +13 -15
  85. odxtools/encodestate.py +199 -22
  86. odxtools/endofpdufield.py +31 -18
  87. odxtools/environmentdata.py +8 -1
  88. odxtools/environmentdatadescription.py +198 -36
  89. odxtools/exceptions.py +11 -2
  90. odxtools/field.py +10 -10
  91. odxtools/functionalclass.py +3 -5
  92. odxtools/inputparam.py +3 -12
  93. odxtools/internalconstr.py +14 -5
  94. odxtools/isotp_state_machine.py +14 -6
  95. odxtools/leadinglengthinfotype.py +37 -18
  96. odxtools/library.py +66 -0
  97. odxtools/loadfile.py +64 -0
  98. odxtools/matchingparameter.py +3 -3
  99. odxtools/message.py +0 -7
  100. odxtools/minmaxlengthtype.py +61 -33
  101. odxtools/modification.py +3 -5
  102. odxtools/multiplexer.py +135 -75
  103. odxtools/multiplexercase.py +39 -18
  104. odxtools/multiplexerdefaultcase.py +15 -12
  105. odxtools/multiplexerswitchkey.py +4 -5
  106. odxtools/nameditemlist.py +33 -8
  107. odxtools/negoutputparam.py +3 -5
  108. odxtools/odxcategory.py +83 -0
  109. odxtools/odxlink.py +62 -53
  110. odxtools/odxtypes.py +93 -8
  111. odxtools/outputparam.py +5 -16
  112. odxtools/parameterinfo.py +219 -61
  113. odxtools/parameters/codedconstparameter.py +45 -32
  114. odxtools/parameters/createanyparameter.py +19 -193
  115. odxtools/parameters/dynamicparameter.py +25 -4
  116. odxtools/parameters/lengthkeyparameter.py +83 -25
  117. odxtools/parameters/matchingrequestparameter.py +48 -18
  118. odxtools/parameters/nrcconstparameter.py +76 -54
  119. odxtools/parameters/parameter.py +97 -73
  120. odxtools/parameters/parameterwithdop.py +41 -38
  121. odxtools/parameters/physicalconstantparameter.py +41 -20
  122. odxtools/parameters/reservedparameter.py +36 -18
  123. odxtools/parameters/systemparameter.py +74 -7
  124. odxtools/parameters/tableentryparameter.py +47 -7
  125. odxtools/parameters/tablekeyparameter.py +142 -55
  126. odxtools/parameters/tablestructparameter.py +79 -58
  127. odxtools/parameters/valueparameter.py +39 -21
  128. odxtools/paramlengthinfotype.py +56 -33
  129. odxtools/parentref.py +20 -3
  130. odxtools/physicaldimension.py +3 -8
  131. odxtools/progcode.py +26 -11
  132. odxtools/protstack.py +3 -5
  133. odxtools/py.typed +0 -0
  134. odxtools/relateddoc.py +7 -9
  135. odxtools/request.py +120 -10
  136. odxtools/response.py +123 -23
  137. odxtools/scaleconstr.py +14 -8
  138. odxtools/servicebinner.py +1 -1
  139. odxtools/singleecujob.py +12 -10
  140. odxtools/snrefcontext.py +29 -0
  141. odxtools/specialdata.py +3 -5
  142. odxtools/specialdatagroup.py +7 -9
  143. odxtools/specialdatagroupcaption.py +3 -6
  144. odxtools/standardlengthtype.py +80 -14
  145. odxtools/state.py +3 -5
  146. odxtools/statechart.py +13 -19
  147. odxtools/statetransition.py +8 -18
  148. odxtools/staticfield.py +107 -0
  149. odxtools/subcomponent.py +288 -0
  150. odxtools/swvariable.py +21 -0
  151. odxtools/table.py +9 -9
  152. odxtools/tablerow.py +30 -15
  153. odxtools/teammember.py +3 -5
  154. odxtools/templates/comparam-spec.odx-c.xml.jinja2 +4 -24
  155. odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +5 -26
  156. odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +15 -31
  157. odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +1 -1
  158. odxtools/templates/macros/printAudience.xml.jinja2 +1 -1
  159. odxtools/templates/macros/printBaseVariant.xml.jinja2 +53 -0
  160. odxtools/templates/macros/printCompanyData.xml.jinja2 +4 -7
  161. odxtools/templates/macros/printComparam.xml.jinja2 +6 -4
  162. odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
  163. odxtools/templates/macros/printCompuMethod.xml.jinja2 +147 -0
  164. odxtools/templates/macros/printDOP.xml.jinja2 +27 -137
  165. odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
  166. odxtools/templates/macros/printDiagComm.xml.jinja2 +1 -1
  167. odxtools/templates/macros/printDiagLayer.xml.jinja2 +222 -0
  168. odxtools/templates/macros/printDiagVariable.xml.jinja2 +66 -0
  169. odxtools/templates/macros/printDynDefinedSpec.xml.jinja2 +48 -0
  170. odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +16 -0
  171. odxtools/templates/macros/printDynamicLengthField.xml.jinja2 +1 -1
  172. odxtools/templates/macros/printEcuSharedData.xml.jinja2 +30 -0
  173. odxtools/templates/macros/printEcuVariant.xml.jinja2 +53 -0
  174. odxtools/templates/macros/printEcuVariantPattern.xml.jinja2 +1 -1
  175. odxtools/templates/macros/printElementId.xml.jinja2 +8 -3
  176. odxtools/templates/macros/printEndOfPdu.xml.jinja2 +1 -1
  177. odxtools/templates/macros/printEnvDataDesc.xml.jinja2 +1 -1
  178. odxtools/templates/macros/printFunctionalClass.xml.jinja2 +1 -1
  179. odxtools/templates/macros/printFunctionalGroup.xml.jinja2 +40 -0
  180. odxtools/templates/macros/printHierarchyElement.xml.jinja2 +24 -0
  181. odxtools/templates/macros/printLibrary.xml.jinja2 +21 -0
  182. odxtools/templates/macros/printMux.xml.jinja2 +5 -3
  183. odxtools/templates/macros/printOdxCategory.xml.jinja2 +28 -0
  184. odxtools/templates/macros/printParam.xml.jinja2 +18 -19
  185. odxtools/templates/macros/printProtStack.xml.jinja2 +1 -1
  186. odxtools/templates/macros/printProtocol.xml.jinja2 +30 -0
  187. odxtools/templates/macros/printRequest.xml.jinja2 +1 -1
  188. odxtools/templates/macros/printResponse.xml.jinja2 +1 -1
  189. odxtools/templates/macros/printService.xml.jinja2 +3 -2
  190. odxtools/templates/macros/printSingleEcuJob.xml.jinja2 +5 -26
  191. odxtools/templates/macros/printSpecialData.xml.jinja2 +1 -1
  192. odxtools/templates/macros/printState.xml.jinja2 +1 -1
  193. odxtools/templates/macros/printStateChart.xml.jinja2 +1 -1
  194. odxtools/templates/macros/printStateTransition.xml.jinja2 +1 -1
  195. odxtools/templates/macros/printStaticField.xml.jinja2 +15 -0
  196. odxtools/templates/macros/printStructure.xml.jinja2 +1 -1
  197. odxtools/templates/macros/printSubComponent.xml.jinja2 +104 -0
  198. odxtools/templates/macros/printTable.xml.jinja2 +4 -5
  199. odxtools/templates/macros/printUnitSpec.xml.jinja2 +3 -5
  200. odxtools/uds.py +2 -10
  201. odxtools/unit.py +4 -8
  202. odxtools/unitgroup.py +3 -5
  203. odxtools/unitspec.py +17 -17
  204. odxtools/utils.py +38 -20
  205. odxtools/variablegroup.py +32 -0
  206. odxtools/version.py +2 -2
  207. odxtools/{write_pdx_file.py → writepdxfile.py} +22 -12
  208. odxtools/xdoc.py +3 -5
  209. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/METADATA +44 -33
  210. odxtools-9.3.0.dist-info/RECORD +228 -0
  211. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/WHEEL +1 -1
  212. odxtools/createcompanydatas.py +0 -17
  213. odxtools/createsdgs.py +0 -19
  214. odxtools/diaglayertype.py +0 -30
  215. odxtools/load_file.py +0 -13
  216. odxtools/load_odx_d_file.py +0 -6
  217. odxtools/load_pdx_file.py +0 -8
  218. odxtools/templates/macros/printVariant.xml.jinja2 +0 -208
  219. odxtools-6.6.1.dist-info/RECORD +0 -180
  220. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/LICENSE +0 -0
  221. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/entry_points.txt +0 -0
  222. {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/top_level.txt +0 -0
@@ -2,13 +2,9 @@
2
2
  from typing import List
3
3
  from xml.etree import ElementTree
4
4
 
5
- from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
6
- from ..createsdgs import create_sdgs_from_et
7
- from ..element import NamedElement
8
- from ..exceptions import odxrequire
5
+ from ..exceptions import odxraise
9
6
  from ..globals import xsi
10
- from ..odxlink import OdxDocFragment, OdxLinkId, OdxLinkRef
11
- from ..utils import dataclass_fields_asdict
7
+ from ..odxlink import OdxDocFragment
12
8
  from .codedconstparameter import CodedConstParameter
13
9
  from .dynamicparameter import DynamicParameter
14
10
  from .lengthkeyparameter import LengthKeyParameter
@@ -27,203 +23,33 @@ from .valueparameter import ValueParameter
27
23
  def create_any_parameter_from_et(et_element: ElementTree.Element,
28
24
  doc_frags: List[OdxDocFragment]) \
29
25
  -> Parameter:
30
- kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
31
- semantic = et_element.get("SEMANTIC")
32
- byte_position_str = et_element.findtext("BYTE-POSITION")
33
- byte_position = int(byte_position_str) if byte_position_str is not None else None
34
- bit_position_str = et_element.findtext("BIT-POSITION")
35
- bit_position = None
36
- if bit_position_str is not None:
37
- bit_position = int(bit_position_str)
38
26
  parameter_type = et_element.get(f"{xsi}type")
39
27
 
40
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
41
-
42
28
  # Which attributes are set depends on the type of the parameter.
43
- if parameter_type in ["VALUE", "PHYS-CONST", "SYSTEM", "LENGTH-KEY"]:
44
- dop_ref = OdxLinkRef.from_et(et_element.find("DOP-REF"), doc_frags)
45
- dop_snref = None
46
- if (dop_snref_elem := et_element.find("DOP-SNREF")) is not None:
47
- dop_snref = odxrequire(dop_snref_elem.get("SHORT-NAME"))
48
-
49
- if dop_ref is None and dop_snref is None:
50
- raise ValueError(
51
- f"A parameter of type {parameter_type} must reference a DOP! {dop_ref}, {dop_snref}"
52
- )
53
-
54
29
  if parameter_type == "VALUE":
55
- physical_default_value_raw = (
56
- et_element.findtext("PHYSICAL-DEFAULT-VALUE")
57
- if et_element.find("PHYSICAL-DEFAULT-VALUE") is not None else None)
58
-
59
- return ValueParameter(
60
- semantic=semantic,
61
- byte_position=byte_position,
62
- bit_position=bit_position,
63
- dop_ref=dop_ref,
64
- dop_snref=dop_snref,
65
- physical_default_value_raw=physical_default_value_raw,
66
- sdgs=sdgs,
67
- **kwargs)
68
-
69
- elif parameter_type == "PHYS-CONST":
70
- physical_constant_value = odxrequire(et_element.findtext("PHYS-CONSTANT-VALUE"))
71
-
72
- return PhysicalConstantParameter(
73
- semantic=semantic,
74
- byte_position=byte_position,
75
- bit_position=bit_position,
76
- dop_ref=dop_ref,
77
- dop_snref=dop_snref,
78
- physical_constant_value_raw=physical_constant_value,
79
- sdgs=sdgs,
80
- **kwargs)
81
-
30
+ return ValueParameter.from_et(et_element, doc_frags)
82
31
  elif parameter_type == "CODED-CONST":
83
- dct_elem = odxrequire(et_element.find("DIAG-CODED-TYPE"))
84
- diag_coded_type = create_any_diag_coded_type_from_et(dct_elem, doc_frags)
85
- coded_value = diag_coded_type.base_data_type.from_string(
86
- odxrequire(et_element.findtext("CODED-VALUE")))
87
-
88
- return CodedConstParameter(
89
- semantic=semantic,
90
- diag_coded_type=diag_coded_type,
91
- coded_value=coded_value,
92
- byte_position=byte_position,
93
- bit_position=bit_position,
94
- sdgs=sdgs,
95
- **kwargs)
96
-
32
+ return CodedConstParameter.from_et(et_element, doc_frags)
33
+ elif parameter_type == "PHYS-CONST":
34
+ return PhysicalConstantParameter.from_et(et_element, doc_frags)
35
+ elif parameter_type == "SYSTEM":
36
+ return SystemParameter.from_et(et_element, doc_frags)
37
+ elif parameter_type == "LENGTH-KEY":
38
+ return LengthKeyParameter.from_et(et_element, doc_frags)
97
39
  elif parameter_type == "NRC-CONST":
98
- diag_coded_type = create_any_diag_coded_type_from_et(
99
- odxrequire(et_element.find("DIAG-CODED-TYPE")), doc_frags)
100
- coded_values = [
101
- diag_coded_type.base_data_type.from_string(odxrequire(val.text))
102
- for val in et_element.iterfind("CODED-VALUES/CODED-VALUE")
103
- ]
104
-
105
- return NrcConstParameter(
106
- semantic=semantic,
107
- diag_coded_type=diag_coded_type,
108
- coded_values=coded_values,
109
- byte_position=byte_position,
110
- bit_position=bit_position,
111
- sdgs=sdgs,
112
- **kwargs)
113
-
40
+ return NrcConstParameter.from_et(et_element, doc_frags)
114
41
  elif parameter_type == "RESERVED":
115
- bit_length = int(odxrequire(et_element.findtext("BIT-LENGTH")))
116
-
117
- return ReservedParameter(
118
- bit_length=bit_length,
119
- semantic=semantic,
120
- byte_position=byte_position,
121
- bit_position=bit_position,
122
- sdgs=sdgs,
123
- **kwargs)
124
-
42
+ return ReservedParameter.from_et(et_element, doc_frags)
125
43
  elif parameter_type == "MATCHING-REQUEST-PARAM":
126
- byte_length = int(odxrequire(et_element.findtext("BYTE-LENGTH")))
127
- request_byte_pos = int(odxrequire(et_element.findtext("REQUEST-BYTE-POS")))
128
-
129
- return MatchingRequestParameter(
130
- semantic=semantic,
131
- byte_position=byte_position,
132
- bit_position=bit_position,
133
- request_byte_position=request_byte_pos,
134
- byte_length=byte_length,
135
- sdgs=sdgs,
136
- **kwargs)
137
-
138
- elif parameter_type == "SYSTEM":
139
- sysparam = odxrequire(et_element.get("SYSPARAM"))
140
-
141
- return SystemParameter(
142
- sysparam=sysparam,
143
- semantic=semantic,
144
- byte_position=byte_position,
145
- bit_position=bit_position,
146
- dop_ref=dop_ref,
147
- dop_snref=dop_snref,
148
- sdgs=sdgs,
149
- **kwargs)
150
-
151
- elif parameter_type == "LENGTH-KEY":
152
- odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
153
-
154
- return LengthKeyParameter(
155
- odx_id=odx_id,
156
- semantic=semantic,
157
- byte_position=byte_position,
158
- bit_position=bit_position,
159
- dop_ref=dop_ref,
160
- dop_snref=dop_snref,
161
- sdgs=sdgs,
162
- **kwargs)
163
-
44
+ return MatchingRequestParameter.from_et(et_element, doc_frags)
164
45
  elif parameter_type == "DYNAMIC":
165
-
166
- return DynamicParameter(
167
- semantic=semantic,
168
- byte_position=byte_position,
169
- bit_position=bit_position,
170
- sdgs=sdgs,
171
- **kwargs)
172
-
46
+ return DynamicParameter.from_et(et_element, doc_frags)
173
47
  elif parameter_type == "TABLE-STRUCT":
174
- key_ref = OdxLinkRef.from_et(et_element.find("TABLE-KEY-REF"), doc_frags)
175
- if (key_snref_elem := et_element.find("TABLE-KEY-SNREF")) is not None:
176
- key_snref = odxrequire(key_snref_elem.get("SHORT-NAME"))
177
- else:
178
- key_snref = None
179
-
180
- return TableStructParameter(
181
- table_key_ref=key_ref,
182
- table_key_snref=key_snref,
183
- semantic=semantic,
184
- byte_position=byte_position,
185
- bit_position=bit_position,
186
- sdgs=sdgs,
187
- **kwargs)
188
-
48
+ return TableStructParameter.from_et(et_element, doc_frags)
189
49
  elif parameter_type == "TABLE-KEY":
190
-
191
- parameter_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
192
- table_ref = OdxLinkRef.from_et(et_element.find("TABLE-REF"), doc_frags)
193
- if (table_snref_elem := et_element.find("TABLE-SNREF")) is not None:
194
- table_snref = odxrequire(table_snref_elem.get("SHORT-NAME"))
195
- else:
196
- table_snref = None
197
-
198
- table_row_ref = OdxLinkRef.from_et(et_element.find("TABLE-ROW-REF"), doc_frags)
199
- if (table_row_snref_elem := et_element.find("TABLE-ROW-SNREF")) is not None:
200
- table_row_snref = odxrequire(table_row_snref_elem.get("SHORT-NAME"))
201
- else:
202
- table_row_snref = None
203
-
204
- return TableKeyParameter(
205
- table_ref=table_ref,
206
- table_snref=table_snref,
207
- table_row_snref=table_row_snref,
208
- table_row_ref=table_row_ref,
209
- odx_id=parameter_id,
210
- byte_position=byte_position,
211
- bit_position=bit_position,
212
- semantic=semantic,
213
- sdgs=sdgs,
214
- **kwargs)
215
-
50
+ return TableKeyParameter.from_et(et_element, doc_frags)
216
51
  elif parameter_type == "TABLE-ENTRY":
217
- target = odxrequire(et_element.findtext("TARGET"))
218
- table_row_ref = odxrequire(OdxLinkRef.from_et(et_element.find("TABLE-ROW-REF"), doc_frags))
219
-
220
- return TableEntryParameter(
221
- target=target,
222
- table_row_ref=table_row_ref,
223
- byte_position=byte_position,
224
- bit_position=bit_position,
225
- semantic=semantic,
226
- sdgs=sdgs,
227
- **kwargs)
52
+ return TableEntryParameter.from_et(et_element, doc_frags)
228
53
 
229
- raise NotImplementedError(f"I don't know about parameters of type {parameter_type}")
54
+ odxraise(f"I don't know about parameters of type {parameter_type}", NotImplementedError)
55
+ return Parameter.from_et(et_element, doc_frags)
@@ -1,29 +1,50 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
+ from typing import List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from typing_extensions import override
3
7
 
4
8
  from ..decodestate import DecodeState
5
9
  from ..encodestate import EncodeState
10
+ from ..odxlink import OdxDocFragment
6
11
  from ..odxtypes import ParameterValue
12
+ from ..utils import dataclass_fields_asdict
7
13
  from .parameter import Parameter, ParameterType
8
14
 
9
15
 
10
16
  @dataclass
11
17
  class DynamicParameter(Parameter):
12
18
 
19
+ @staticmethod
20
+ @override
21
+ def from_et(et_element: ElementTree.Element,
22
+ doc_frags: List[OdxDocFragment]) -> "DynamicParameter":
23
+
24
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
25
+
26
+ return DynamicParameter(**kwargs)
27
+
13
28
  @property
29
+ @override
14
30
  def parameter_type(self) -> ParameterType:
15
31
  return "DYNAMIC"
16
32
 
17
33
  @property
34
+ @override
18
35
  def is_required(self) -> bool:
19
36
  raise NotImplementedError(".is_required for a DynamicParameter")
20
37
 
21
38
  @property
39
+ @override
22
40
  def is_settable(self) -> bool:
23
41
  raise NotImplementedError(".is_settable for a DynamicParameter")
24
42
 
25
- def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
26
- raise NotImplementedError("Encoding a DynamicParameter is not implemented yet.")
43
+ @override
44
+ def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
45
+ encode_state: EncodeState) -> None:
46
+ raise NotImplementedError("Encoding DynamicParameter is not implemented yet.")
27
47
 
28
- def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
29
- raise NotImplementedError("Decoding a DynamicParameter is not implemented yet.")
48
+ @override
49
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
50
+ raise NotImplementedError("Decoding DynamicParameter is not implemented yet.")
@@ -1,18 +1,19 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict
3
+ from typing import Any, Dict, List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from typing_extensions import final, override
4
7
 
5
8
  from ..decodestate import DecodeState
6
9
  from ..encodestate import EncodeState
7
- from ..exceptions import odxraise, odxrequire
8
- from ..odxlink import OdxLinkDatabase, OdxLinkId
10
+ from ..exceptions import EncodeError, odxraise, odxrequire
11
+ from ..odxlink import OdxDocFragment, OdxLinkId
9
12
  from ..odxtypes import ParameterValue
13
+ from ..utils import dataclass_fields_asdict
10
14
  from .parameter import ParameterType
11
15
  from .parameterwithdop import ParameterWithDOP
12
16
 
13
- if TYPE_CHECKING:
14
- from ..diaglayer import DiagLayer
15
-
16
17
 
17
18
  @dataclass
18
19
  class LengthKeyParameter(ParameterWithDOP):
@@ -27,10 +28,23 @@ class LengthKeyParameter(ParameterWithDOP):
27
28
 
28
29
  odx_id: OdxLinkId
29
30
 
31
+ @staticmethod
32
+ @override
33
+ def from_et(et_element: ElementTree.Element,
34
+ doc_frags: List[OdxDocFragment]) -> "LengthKeyParameter":
35
+
36
+ kwargs = dataclass_fields_asdict(ParameterWithDOP.from_et(et_element, doc_frags))
37
+
38
+ odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
39
+
40
+ return LengthKeyParameter(odx_id=odx_id, **kwargs)
41
+
30
42
  @property
43
+ @override
31
44
  def parameter_type(self) -> ParameterType:
32
45
  return "LENGTH-KEY"
33
46
 
47
+ @override
34
48
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
35
49
  result = super()._build_odxlinks()
36
50
 
@@ -38,36 +52,80 @@ class LengthKeyParameter(ParameterWithDOP):
38
52
 
39
53
  return result
40
54
 
41
- def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
42
- super()._resolve_odxlinks(odxlinks)
43
-
44
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
45
- super()._resolve_snrefs(diag_layer)
46
-
47
55
  @property
56
+ @override
48
57
  def is_required(self) -> bool:
49
58
  return False
50
59
 
51
60
  @property
61
+ @override
52
62
  def is_settable(self) -> bool:
53
63
  # length keys can be explicitly set, but they do not need to
54
64
  # be because they can be implicitly determined by the length
55
65
  # of the corresponding field
56
66
  return True
57
67
 
58
- def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
59
- physical_value = encode_state.parameter_values.get(self.short_name, 0)
60
-
61
- bit_pos = self.bit_position or 0
62
- dop = odxrequire(super().dop,
63
- f"A DOP is required for length key parameter {self.short_name}")
64
- return dop.convert_physical_to_bytes(physical_value, encode_state, bit_position=bit_pos)
65
-
66
- def encode_into_pdu(self, encode_state: EncodeState) -> bytes:
67
- return super().encode_into_pdu(encode_state)
68
-
69
- def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
70
- phys_val = super().decode_from_pdu(decode_state)
68
+ @override
69
+ @final
70
+ def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
71
+ encode_state: EncodeState) -> None:
72
+ # if you get this exception, you ought to use
73
+ # `.encode_placeholder_into_pdu()` followed by (after the
74
+ # value of the length key has been determined)
75
+ # `.encode_value_into_pdu()`.
76
+ raise RuntimeError("_encode_positioned_into_pdu() cannot be called for length keys.")
77
+
78
+ def encode_placeholder_into_pdu(self, physical_value: Optional[ParameterValue],
79
+ encode_state: EncodeState) -> None:
80
+
81
+ if physical_value is not None:
82
+ if not self.dop.is_valid_physical_value(physical_value):
83
+ odxraise(f"Invalid explicitly specified physical value '{physical_value!r}' "
84
+ f"for length key '{self.short_name}'.")
85
+
86
+ lkv = encode_state.length_keys.get(self.short_name)
87
+ if lkv is not None and lkv != physical_value:
88
+ odxraise(f"Got conflicting values for length key {self.short_name}: "
89
+ f"{lkv} and {physical_value!r}")
90
+
91
+ if not isinstance(physical_value, int):
92
+ odxraise(
93
+ f"Value of length key {self.short_name} is of type {type(physical_value).__name__} "
94
+ f"instead of int")
95
+
96
+ encode_state.length_keys[self.short_name] = physical_value
97
+
98
+ pos = encode_state.cursor_byte_position
99
+ if self.byte_position is not None:
100
+ pos = encode_state.origin_byte_position + self.byte_position
101
+ encode_state.key_pos[self.short_name] = pos
102
+ encode_state.cursor_byte_position = pos
103
+ encode_state.cursor_bit_position = self.bit_position or 0
104
+
105
+ # emplace a value of zero into the encode state, but pretend the bits not to be used
106
+ n = odxrequire(self.dop.get_static_bit_length()) + encode_state.cursor_bit_position
107
+ tmp_val = b'\x00' * ((n + 7) // 8)
108
+ encode_state.cursor_bit_position = 0
109
+ encode_state.emplace_bytes(tmp_val, obj_used_mask=tmp_val)
110
+
111
+ def encode_value_into_pdu(self, encode_state: EncodeState) -> None:
112
+
113
+ if self.short_name not in encode_state.length_keys:
114
+ odxraise(
115
+ f"Length key {self.short_name} has not been defined before "
116
+ f"it is required.", EncodeError)
117
+ return
118
+ else:
119
+ physical_value = encode_state.length_keys[self.short_name]
120
+
121
+ encode_state.cursor_byte_position = encode_state.key_pos[self.short_name]
122
+ encode_state.cursor_bit_position = self.bit_position or 0
123
+
124
+ self.dop.encode_into_pdu(encode_state=encode_state, physical_value=physical_value)
125
+
126
+ @override
127
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
128
+ phys_val = super()._decode_positioned_from_pdu(decode_state)
71
129
 
72
130
  if not isinstance(phys_val, int):
73
131
  odxraise(f"The pysical type of length keys must be an integer, "
@@ -1,11 +1,16 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import Optional
3
+ from typing import List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from typing_extensions import override
4
7
 
5
8
  from ..decodestate import DecodeState
6
9
  from ..encodestate import EncodeState
7
- from ..exceptions import EncodeError
10
+ from ..exceptions import EncodeError, odxraise, odxrequire
11
+ from ..odxlink import OdxDocFragment
8
12
  from ..odxtypes import DataType, ParameterValue
13
+ from ..utils import dataclass_fields_asdict
9
14
  from .parameter import Parameter, ParameterType
10
15
 
11
16
 
@@ -14,39 +19,64 @@ class MatchingRequestParameter(Parameter):
14
19
  request_byte_position: int
15
20
  byte_length: int
16
21
 
22
+ @staticmethod
23
+ @override
24
+ def from_et(et_element: ElementTree.Element,
25
+ doc_frags: List[OdxDocFragment]) -> "MatchingRequestParameter":
26
+
27
+ kwargs = dataclass_fields_asdict(Parameter.from_et(et_element, doc_frags))
28
+
29
+ request_byte_position = int(odxrequire(et_element.findtext("REQUEST-BYTE-POS")))
30
+ byte_length = int(odxrequire(et_element.findtext("BYTE-LENGTH")))
31
+
32
+ return MatchingRequestParameter(
33
+ request_byte_position=request_byte_position, byte_length=byte_length, **kwargs)
34
+
17
35
  @property
36
+ @override
18
37
  def parameter_type(self) -> ParameterType:
19
38
  return "MATCHING-REQUEST-PARAM"
20
39
 
40
+ @override
21
41
  def get_static_bit_length(self) -> Optional[int]:
22
42
  return 8 * self.byte_length
23
43
 
24
44
  @property
45
+ @override
25
46
  def is_required(self) -> bool:
26
47
  return False
27
48
 
28
49
  @property
50
+ @override
29
51
  def is_settable(self) -> bool:
30
52
  return False
31
53
 
32
- def get_coded_value_as_bytes(self, encode_state: EncodeState) -> bytes:
33
- if not encode_state.triggering_request:
34
- raise EncodeError(f"Parameter '{self.short_name}' is of matching request type,"
35
- " but no original request has been specified.")
36
- return encode_state.triggering_request[self
37
- .request_byte_position:self.request_byte_position +
38
- self.byte_length]
54
+ @override
55
+ def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
56
+ encode_state: EncodeState) -> None:
57
+ if encode_state.triggering_request is None:
58
+ odxraise(
59
+ f"Parameter '{self.short_name}' is of matching request type,"
60
+ f" but no original request has been specified.", EncodeError)
61
+ return
39
62
 
40
- def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
41
- orig_cursor = decode_state.cursor_byte_position
42
- if self.byte_position is not None:
43
- decode_state.cursor_byte_position = decode_state.origin_byte_position + self.byte_position
63
+ rq_pos = self.request_byte_position
64
+ rq_len = self.byte_length
44
65
 
45
- result = decode_state.extract_atomic_value(
66
+ if len(encode_state.triggering_request) < rq_pos + rq_len:
67
+ odxraise(
68
+ f"Specified triggering request 0x{encode_state.triggering_request.hex()} "
69
+ f"is not long enough to encode matching request parameter "
70
+ f"'{self.short_name}': Have {len(encode_state.triggering_request)} "
71
+ f"bytes, need at least {rq_pos + rq_len} bytes", EncodeError)
72
+ return
73
+
74
+ encode_state.emplace_bytes(encode_state.triggering_request[rq_pos:rq_pos + rq_len],
75
+ self.short_name)
76
+
77
+ @override
78
+ def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
79
+ return decode_state.extract_atomic_value(
46
80
  bit_length=self.byte_length * 8,
47
81
  base_data_type=DataType.A_UINT32,
48
82
  is_highlow_byte_order=False)
49
-
50
- decode_state.cursor_byte_position = max(decode_state.cursor_byte_position, orig_cursor)
51
-
52
- return result