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
odxtools/comparamspec.py CHANGED
@@ -1,66 +1,39 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
3
+ from typing import TYPE_CHECKING, Any, Dict, List
4
4
  from xml.etree import ElementTree
5
5
 
6
- from .admindata import AdminData
7
- from .companydata import CompanyData
8
- from .createcompanydatas import create_company_datas_from_et
9
- from .createsdgs import create_sdgs_from_et
10
- from .element import IdentifiableElement
11
- from .exceptions import odxrequire
12
6
  from .nameditemlist import NamedItemList
7
+ from .odxcategory import OdxCategory
13
8
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
14
9
  from .protstack import ProtStack
15
- from .specialdatagroup import SpecialDataGroup
10
+ from .snrefcontext import SnRefContext
16
11
  from .utils import dataclass_fields_asdict
17
12
 
18
13
  if TYPE_CHECKING:
19
- from .diaglayer import DiagLayer
14
+ from .database import Database
20
15
 
21
16
 
22
17
  @dataclass
23
- class ComparamSpec(IdentifiableElement):
24
- admin_data: Optional[AdminData]
25
- company_datas: NamedItemList[CompanyData]
26
- sdgs: List[SpecialDataGroup]
18
+ class ComparamSpec(OdxCategory):
27
19
  prot_stacks: NamedItemList[ProtStack]
28
20
 
29
21
  @staticmethod
30
22
  def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "ComparamSpec":
31
23
 
32
- short_name = odxrequire(et_element.findtext("SHORT-NAME"))
33
- doc_frags = [OdxDocFragment(short_name, str(et_element.tag))]
34
- kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
24
+ cat = OdxCategory.category_from_et(et_element, doc_frags, doc_type="COMPARAM-SPEC")
25
+ doc_frags = cat.odx_id.doc_fragments
26
+ kwargs = dataclass_fields_asdict(cat)
35
27
 
36
- admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
37
- company_datas = create_company_datas_from_et(et_element.find("COMPANY-DATAS"), doc_frags)
38
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
39
28
  prot_stacks = NamedItemList([
40
29
  ProtStack.from_et(dl_element, doc_frags)
41
30
  for dl_element in et_element.iterfind("PROT-STACKS/PROT-STACK")
42
31
  ])
43
32
 
44
- return ComparamSpec(
45
- admin_data=admin_data,
46
- company_datas=company_datas,
47
- sdgs=sdgs,
48
- prot_stacks=prot_stacks,
49
- **kwargs)
33
+ return ComparamSpec(prot_stacks=prot_stacks, **kwargs)
50
34
 
51
35
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
52
- odxlinks: Dict[OdxLinkId, Any] = {}
53
- if self.odx_id is not None:
54
- odxlinks[self.odx_id] = self
55
-
56
- if self.admin_data is not None:
57
- odxlinks.update(self.admin_data._build_odxlinks())
58
-
59
- for cd in self.company_datas:
60
- odxlinks.update(cd._build_odxlinks())
61
-
62
- for sdg in self.sdgs:
63
- odxlinks.update(sdg._build_odxlinks())
36
+ odxlinks = super()._build_odxlinks()
64
37
 
65
38
  for ps in self.prot_stacks:
66
39
  odxlinks.update(ps._build_odxlinks())
@@ -68,27 +41,16 @@ class ComparamSpec(IdentifiableElement):
68
41
  return odxlinks
69
42
 
70
43
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
71
- if self.admin_data is not None:
72
- self.admin_data._resolve_odxlinks(odxlinks)
73
-
74
- for cd in self.company_datas:
75
- cd._resolve_odxlinks(odxlinks)
76
-
77
- for sdg in self.sdgs:
78
- sdg._resolve_odxlinks(odxlinks)
44
+ super()._resolve_odxlinks(odxlinks)
79
45
 
80
46
  for ps in self.prot_stacks:
81
47
  ps._resolve_odxlinks(odxlinks)
82
48
 
83
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
84
- if self.admin_data is not None:
85
- self.admin_data._resolve_snrefs(diag_layer)
86
-
87
- for cd in self.company_datas:
88
- cd._resolve_snrefs(diag_layer)
49
+ def _finalize_init(self, database: "Database", odxlinks: OdxLinkDatabase) -> None:
50
+ super()._finalize_init(database, odxlinks)
89
51
 
90
- for sdg in self.sdgs:
91
- sdg._resolve_snrefs(diag_layer)
52
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
53
+ super()._resolve_snrefs(context)
92
54
 
93
55
  for ps in self.prot_stacks:
94
- ps._resolve_snrefs(diag_layer)
56
+ ps._resolve_snrefs(context)
@@ -3,49 +3,39 @@ from dataclasses import dataclass
3
3
  from typing import TYPE_CHECKING, Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
- from .admindata import AdminData
7
- from .companydata import CompanyData
8
6
  from .comparam import Comparam
9
7
  from .complexcomparam import ComplexComparam
10
- from .createcompanydatas import create_company_datas_from_et
11
- from .createsdgs import create_sdgs_from_et
12
8
  from .dataobjectproperty import DataObjectProperty
13
- from .element import IdentifiableElement
14
- from .exceptions import odxrequire
15
9
  from .nameditemlist import NamedItemList
10
+ from .odxcategory import OdxCategory
16
11
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
17
- from .specialdatagroup import SpecialDataGroup
12
+ from .snrefcontext import SnRefContext
18
13
  from .unitspec import UnitSpec
19
14
  from .utils import dataclass_fields_asdict
20
15
 
21
16
  if TYPE_CHECKING:
22
- from .diaglayer import DiagLayer
17
+ from .database import Database
23
18
 
24
19
 
25
20
  @dataclass
26
- class ComparamSubset(IdentifiableElement):
27
- # mandatory in ODX 2.2, but non existent in ODX 2.0
21
+ class ComparamSubset(OdxCategory):
22
+ # mandatory in ODX 2.2, but non-existent in ODX 2.0
28
23
  category: Optional[str]
29
- data_object_props: NamedItemList[DataObjectProperty]
24
+
30
25
  comparams: NamedItemList[Comparam]
31
26
  complex_comparams: NamedItemList[ComplexComparam]
27
+ data_object_props: NamedItemList[DataObjectProperty]
32
28
  unit_spec: Optional[UnitSpec]
33
- admin_data: Optional[AdminData]
34
- company_datas: NamedItemList[CompanyData]
35
- sdgs: List[SpecialDataGroup]
36
29
 
37
30
  @staticmethod
38
31
  def from_et(et_element: ElementTree.Element,
39
32
  doc_frags: List[OdxDocFragment]) -> "ComparamSubset":
40
33
 
41
- category = et_element.get("CATEGORY")
42
-
43
- short_name = odxrequire(et_element.findtext("SHORT-NAME"))
44
- doc_frags = [OdxDocFragment(short_name, str(et_element.tag))]
45
- kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
34
+ cat = OdxCategory.category_from_et(et_element, doc_frags, doc_type="COMPARAM-SUBSET")
35
+ doc_frags = cat.odx_id.doc_fragments
36
+ kwargs = dataclass_fields_asdict(cat)
46
37
 
47
- admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
48
- company_datas = create_company_datas_from_et(et_element.find("COMPANY-DATAS"), doc_frags)
38
+ category = et_element.get("CATEGORY")
49
39
 
50
40
  data_object_props = NamedItemList([
51
41
  DataObjectProperty.from_et(el, doc_frags)
@@ -62,23 +52,16 @@ class ComparamSubset(IdentifiableElement):
62
52
  else:
63
53
  unit_spec = None
64
54
 
65
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
66
-
67
55
  return ComparamSubset(
68
56
  category=category,
69
- admin_data=admin_data,
70
- company_datas=company_datas,
71
57
  data_object_props=data_object_props,
72
58
  comparams=comparams,
73
59
  complex_comparams=complex_comparams,
74
60
  unit_spec=unit_spec,
75
- sdgs=sdgs,
76
61
  **kwargs)
77
62
 
78
63
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
79
- odxlinks: Dict[OdxLinkId, Any] = {}
80
- if self.odx_id is not None:
81
- odxlinks[self.odx_id] = self
64
+ odxlinks = super()._build_odxlinks()
82
65
 
83
66
  for dop in self.data_object_props:
84
67
  odxlinks[dop.odx_id] = dop
@@ -92,19 +75,11 @@ class ComparamSubset(IdentifiableElement):
92
75
  if self.unit_spec:
93
76
  odxlinks.update(self.unit_spec._build_odxlinks())
94
77
 
95
- if self.admin_data is not None:
96
- odxlinks.update(self.admin_data._build_odxlinks())
97
-
98
- if self.company_datas is not None:
99
- for cd in self.company_datas:
100
- odxlinks.update(cd._build_odxlinks())
101
-
102
- for sdg in self.sdgs:
103
- odxlinks.update(sdg._build_odxlinks())
104
-
105
78
  return odxlinks
106
79
 
107
80
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
81
+ super()._resolve_odxlinks(odxlinks)
82
+
108
83
  for dop in self.data_object_props:
109
84
  dop._resolve_odxlinks(odxlinks)
110
85
 
@@ -117,35 +92,20 @@ class ComparamSubset(IdentifiableElement):
117
92
  if self.unit_spec:
118
93
  self.unit_spec._resolve_odxlinks(odxlinks)
119
94
 
120
- if self.admin_data is not None:
121
- self.admin_data._resolve_odxlinks(odxlinks)
122
-
123
- if self.company_datas is not None:
124
- for cd in self.company_datas:
125
- cd._resolve_odxlinks(odxlinks)
95
+ def _finalize_init(self, database: "Database", odxlinks: OdxLinkDatabase) -> None:
96
+ super()._finalize_init(database, odxlinks)
126
97
 
127
- for sdg in self.sdgs:
128
- sdg._resolve_odxlinks(odxlinks)
98
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
99
+ super()._resolve_snrefs(context)
129
100
 
130
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
131
101
  for dop in self.data_object_props:
132
- dop._resolve_snrefs(diag_layer)
102
+ dop._resolve_snrefs(context)
133
103
 
134
104
  for comparam in self.comparams:
135
- comparam._resolve_snrefs(diag_layer)
105
+ comparam._resolve_snrefs(context)
136
106
 
137
107
  for ccomparam in self.complex_comparams:
138
- ccomparam._resolve_snrefs(diag_layer)
108
+ ccomparam._resolve_snrefs(context)
139
109
 
140
110
  if self.unit_spec:
141
- self.unit_spec._resolve_snrefs(diag_layer)
142
-
143
- if self.admin_data is not None:
144
- self.admin_data._resolve_snrefs(diag_layer)
145
-
146
- if self.company_datas is not None:
147
- for cd in self.company_datas:
148
- cd._resolve_snrefs(diag_layer)
149
-
150
- for sdg in self.sdgs:
151
- sdg._resolve_snrefs(diag_layer)
111
+ self.unit_spec._resolve_snrefs(context)
@@ -1,17 +1,15 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
3
+ from typing import Any, Dict, List, Optional, Union
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .basecomparam import BaseComparam
7
7
  from .nameditemlist import NamedItemList
8
8
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
9
9
  from .odxtypes import odxstr_to_bool
10
+ from .snrefcontext import SnRefContext
10
11
  from .utils import dataclass_fields_asdict
11
12
 
12
- if TYPE_CHECKING:
13
- from .diaglayer import DiagLayer
14
-
15
13
  ComplexValue = List[Union[str, "ComplexValue"]]
16
14
 
17
15
 
@@ -93,7 +91,7 @@ class ComplexComparam(BaseComparam):
93
91
  for subparam in self.subparams:
94
92
  subparam._resolve_odxlinks(odxlinks)
95
93
 
96
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
97
- super()._resolve_snrefs(diag_layer)
94
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
95
+ super()._resolve_snrefs(context)
98
96
  for subparam in self.subparams:
99
- subparam._resolve_snrefs(diag_layer)
97
+ subparam._resolve_snrefs(context)
@@ -0,0 +1,63 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import List, Optional, cast
4
+ from xml.etree import ElementTree
5
+
6
+ from ..exceptions import DecodeError, EncodeError, odxassert, odxraise
7
+ from ..odxlink import OdxDocFragment
8
+ from ..odxtypes import AtomicOdxType, DataType
9
+ from ..progcode import ProgCode
10
+ from ..utils import dataclass_fields_asdict
11
+ from .compumethod import CompuCategory, CompuMethod
12
+
13
+
14
+ @dataclass
15
+ class CompuCodeCompuMethod(CompuMethod):
16
+ """A compu method specifies the tranfer functions using Java bytecode
17
+
18
+ For details, refer to ASAM specification MCD-2 D (ODX), section 7.3.6.6.9.
19
+ """
20
+
21
+ @property
22
+ def internal_to_phys_code(self) -> Optional[ProgCode]:
23
+ if self.compu_internal_to_phys is None:
24
+ return None
25
+
26
+ return self.compu_internal_to_phys.prog_code
27
+
28
+ @property
29
+ def phys_to_internal_code(self) -> Optional[ProgCode]:
30
+ if self.compu_phys_to_internal is None:
31
+ return None
32
+
33
+ return self.compu_phys_to_internal.prog_code
34
+
35
+ @staticmethod
36
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
37
+ internal_type: DataType,
38
+ physical_type: DataType) -> "CompuCodeCompuMethod":
39
+ cm = CompuMethod.compu_method_from_et(
40
+ et_element, doc_frags, internal_type=internal_type, physical_type=physical_type)
41
+ kwargs = dataclass_fields_asdict(cm)
42
+
43
+ return CompuCodeCompuMethod(**kwargs)
44
+
45
+ def __post_init__(self) -> None:
46
+ odxassert(self.category == CompuCategory.COMPUCODE,
47
+ "CompuCodeCompuMethod must exhibit COMPUCODE category")
48
+
49
+ def convert_internal_to_physical(self, internal_value: AtomicOdxType) -> AtomicOdxType:
50
+ odxraise(r"CompuCodeCompuMethod cannot be executed by odxtools", DecodeError)
51
+ return cast(AtomicOdxType, None)
52
+
53
+ def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> AtomicOdxType:
54
+ odxraise(r"CompuCodeCompuMethod cannot be executed by odxtools", EncodeError)
55
+ return cast(AtomicOdxType, None)
56
+
57
+ def is_valid_physical_value(self, physical_value: AtomicOdxType) -> bool:
58
+ # CompuCodeCompuMethod cannot be executed by odxtools
59
+ return False
60
+
61
+ def is_valid_internal_value(self, internal_value: AtomicOdxType) -> bool:
62
+ # CompuCodeCompuMethod cannot be executed by odxtools
63
+ return False
@@ -0,0 +1,31 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from ..odxtypes import AtomicOdxType, DataType
7
+
8
+
9
+ @dataclass
10
+ class CompuConst:
11
+ v: Optional[str]
12
+ vt: Optional[str]
13
+
14
+ data_type: DataType
15
+
16
+ @staticmethod
17
+ def compuvalue_from_et(et_element: ElementTree.Element, *, data_type: DataType) -> "CompuConst":
18
+
19
+ v = et_element.findtext("V")
20
+ vt = et_element.findtext("VT")
21
+
22
+ return CompuConst(v=v, vt=vt, data_type=data_type)
23
+
24
+ def __post_init__(self) -> None:
25
+ self._value: Optional[AtomicOdxType] = self.vt
26
+ if self.v is not None:
27
+ self._value = self.data_type.from_string(self.v)
28
+
29
+ @property
30
+ def value(self) -> Optional[AtomicOdxType]:
31
+ return self._value
@@ -0,0 +1,27 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from ..odxtypes import DataType
7
+ from ..utils import dataclass_fields_asdict
8
+ from .compuconst import CompuConst
9
+ from .compuinversevalue import CompuInverseValue
10
+
11
+
12
+ @dataclass
13
+ class CompuDefaultValue(CompuConst):
14
+ compu_inverse_value: Optional[CompuInverseValue]
15
+
16
+ @staticmethod
17
+ def compuvalue_from_et(et_element: ElementTree.Element, *,
18
+ data_type: DataType) -> "CompuDefaultValue":
19
+ kwargs = dataclass_fields_asdict(
20
+ CompuConst.compuvalue_from_et(et_element, data_type=data_type))
21
+
22
+ compu_inverse_value = None
23
+ if (civ_elem := et_element.find("COMPU-INVERSE-VALUE")) is not None:
24
+ compu_inverse_value = CompuInverseValue.compuvalue_from_et(
25
+ civ_elem, data_type=data_type)
26
+
27
+ return CompuDefaultValue(**kwargs, compu_inverse_value=compu_inverse_value)
@@ -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 CompuInternalToPhys:
16
+ compu_scales: List[CompuScale]
17
+ prog_code: Optional[ProgCode]
18
+ compu_default_value: Optional[CompuDefaultValue]
19
+
20
+ @staticmethod
21
+ def compu_internal_to_phys_from_et(et_element: ElementTree.Element,
22
+ doc_frags: List[OdxDocFragment], *, internal_type: DataType,
23
+ physical_type: DataType) -> "CompuInternalToPhys":
24
+ compu_scales = [
25
+ CompuScale.compuscale_from_et(
26
+ cse, doc_frags, domain_type=internal_type, range_type=physical_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=physical_type)
38
+
39
+ return CompuInternalToPhys(
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)
@@ -0,0 +1,7 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ from .compuconst import CompuConst
4
+
5
+ # make CompuInverseValue an alias for CompuConst. The XSD defines two
6
+ # separate but identical groups for this (why?)...
7
+ CompuInverseValue = CompuConst
@@ -1,28 +1,107 @@
1
1
  # SPDX-License-Identifier: MIT
2
- import abc
3
2
  from dataclasses import dataclass
4
- from typing import Literal
3
+ from enum import Enum
4
+ from typing import Any, Dict, List, Optional
5
+ from xml.etree import ElementTree
5
6
 
7
+ from ..exceptions import odxraise
8
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
6
9
  from ..odxtypes import AtomicOdxType, DataType
10
+ from ..snrefcontext import SnRefContext
11
+ from .compuinternaltophys import CompuInternalToPhys
12
+ from .compuphystointernal import CompuPhysToInternal
7
13
 
8
- CompuMethodCategory = Literal[
9
- "IDENTICAL",
10
- "LINEAR",
11
- "SCALE-LINEAR",
12
- "TAB-INTP",
13
- "TEXTTABLE",
14
- ]
14
+
15
+ class CompuCategory(Enum):
16
+ IDENTICAL = "IDENTICAL"
17
+ LINEAR = "LINEAR"
18
+ SCALE_LINEAR = "SCALE-LINEAR"
19
+ TEXTTABLE = "TEXTTABLE"
20
+ COMPUCODE = "COMPUCODE"
21
+ TAB_INTP = "TAB-INTP"
22
+ RAT_FUNC = "RAT-FUNC"
23
+ SCALE_RAT_FUNC = "SCALE-RAT-FUNC"
15
24
 
16
25
 
17
26
  @dataclass
18
- class CompuMethod(abc.ABC):
19
- internal_type: DataType
27
+ class CompuMethod:
28
+ """A compu method translates between the internal representation
29
+ of a value and their physical representation.
30
+
31
+ There are many compu methods, but all of them are specified using
32
+ the same mechanism: The conversion from internal to physical
33
+ quantities is specified using the COMPU-INTERNAL-TO-PHYS subtag,
34
+ and the inverse is covered by
35
+ COMPU-PHYS-TO-INTERNAL. Alternatively to directly specifying the
36
+ parameters needed for conversion, it is also possible to specify a
37
+ Java program which does the conversion (doing this excludes using
38
+ ODX in non-Java contexts, though).
39
+
40
+ For details, refer to ASAM specification MCD-2 D (ODX), section 7.3.6.6.
41
+
42
+ """
43
+
44
+ category: CompuCategory
45
+ compu_internal_to_phys: Optional[CompuInternalToPhys]
46
+ compu_phys_to_internal: Optional[CompuPhysToInternal]
47
+
20
48
  physical_type: DataType
49
+ internal_type: DataType
50
+
51
+ @staticmethod
52
+ def compu_method_from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment], *,
53
+ internal_type: DataType, physical_type: DataType) -> "CompuMethod":
54
+ cat_text = et_element.findtext("CATEGORY")
55
+ if cat_text is None:
56
+ odxraise("No category specified for compu method")
57
+ cat_text = "IDENTICAL"
58
+
59
+ try:
60
+ category = CompuCategory(cat_text)
61
+ except ValueError:
62
+ odxraise(f"Encountered compu method of unknown category '{cat_text}'")
63
+ category = CompuCategory.IDENTICAL
64
+
65
+ compu_internal_to_phys = None
66
+ if (citp_elem := et_element.find("COMPU-INTERNAL-TO-PHYS")) is not None:
67
+ compu_internal_to_phys = CompuInternalToPhys.compu_internal_to_phys_from_et(
68
+ citp_elem, doc_frags, internal_type=internal_type, physical_type=physical_type)
69
+ compu_phys_to_internal = None
70
+ if (cpti_elem := et_element.find("COMPU-PHYS-TO-INTERNAL")) is not None:
71
+ compu_phys_to_internal = CompuPhysToInternal.compu_phys_to_internal_from_et(
72
+ cpti_elem, doc_frags, internal_type=internal_type, physical_type=physical_type)
73
+
74
+ return CompuMethod(
75
+ category=category,
76
+ compu_internal_to_phys=compu_internal_to_phys,
77
+ compu_phys_to_internal=compu_phys_to_internal,
78
+ physical_type=physical_type,
79
+ internal_type=internal_type)
80
+
81
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
82
+ result = {}
83
+
84
+ if self.compu_internal_to_phys is not None:
85
+ result.update(self.compu_internal_to_phys._build_odxlinks())
86
+
87
+ if self.compu_phys_to_internal is not None:
88
+ result.update(self.compu_phys_to_internal._build_odxlinks())
89
+
90
+ return result
91
+
92
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
93
+ if self.compu_internal_to_phys is not None:
94
+ self.compu_internal_to_phys._resolve_odxlinks(odxlinks)
95
+
96
+ if self.compu_phys_to_internal is not None:
97
+ self.compu_phys_to_internal._resolve_odxlinks(odxlinks)
98
+
99
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
100
+ if self.compu_internal_to_phys is not None:
101
+ self.compu_internal_to_phys._resolve_snrefs(context)
21
102
 
22
- @property
23
- @abc.abstractmethod
24
- def category(self) -> CompuMethodCategory:
25
- pass
103
+ if self.compu_phys_to_internal is not None:
104
+ self.compu_phys_to_internal._resolve_snrefs(context)
26
105
 
27
106
  def convert_physical_to_internal(self, physical_value: AtomicOdxType) -> AtomicOdxType:
28
107
  raise NotImplementedError()
@@ -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)