odxtools 7.1.0__py3-none-any.whl → 7.2.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 (131) hide show
  1. odxtools/__init__.py +6 -4
  2. odxtools/additionalaudience.py +3 -5
  3. odxtools/admindata.py +5 -7
  4. odxtools/audience.py +3 -5
  5. odxtools/basecomparam.py +3 -5
  6. odxtools/basicstructure.py +10 -17
  7. odxtools/cli/_parser_utils.py +1 -1
  8. odxtools/cli/_print_utils.py +3 -2
  9. odxtools/cli/compare.py +1 -1
  10. odxtools/companydata.py +5 -7
  11. odxtools/companydocinfo.py +7 -8
  12. odxtools/companyrevisioninfo.py +3 -5
  13. odxtools/companyspecificinfo.py +8 -9
  14. odxtools/comparam.py +4 -6
  15. odxtools/comparaminstance.py +6 -8
  16. odxtools/comparamspec.py +14 -13
  17. odxtools/comparamsubset.py +17 -16
  18. odxtools/complexcomparam.py +5 -7
  19. odxtools/compumethods/compuconst.py +31 -0
  20. odxtools/compumethods/compudefaultvalue.py +27 -0
  21. odxtools/compumethods/compuinternaltophys.py +39 -0
  22. odxtools/compumethods/compuinversevalue.py +7 -0
  23. odxtools/compumethods/compumethod.py +67 -12
  24. odxtools/compumethods/compuphystointernal.py +39 -0
  25. odxtools/compumethods/compuscale.py +15 -26
  26. odxtools/compumethods/createanycompumethod.py +14 -160
  27. odxtools/compumethods/identicalcompumethod.py +31 -6
  28. odxtools/compumethods/linearcompumethod.py +69 -189
  29. odxtools/compumethods/linearsegment.py +193 -0
  30. odxtools/compumethods/scalelinearcompumethod.py +132 -26
  31. odxtools/compumethods/tabintpcompumethod.py +119 -99
  32. odxtools/compumethods/texttablecompumethod.py +107 -43
  33. odxtools/createanydiagcodedtype.py +10 -67
  34. odxtools/database.py +68 -62
  35. odxtools/dataobjectproperty.py +10 -19
  36. odxtools/description.py +47 -0
  37. odxtools/determinenumberofitems.py +4 -5
  38. odxtools/diagcodedtype.py +29 -12
  39. odxtools/diagcomm.py +10 -6
  40. odxtools/diagdatadictionaryspec.py +20 -21
  41. odxtools/diaglayer.py +34 -5
  42. odxtools/diaglayercontainer.py +17 -11
  43. odxtools/diaglayerraw.py +20 -21
  44. odxtools/diagnostictroublecode.py +7 -8
  45. odxtools/diagservice.py +9 -7
  46. odxtools/docrevision.py +5 -7
  47. odxtools/dopbase.py +7 -8
  48. odxtools/dtcdop.py +5 -8
  49. odxtools/dynamicendmarkerfield.py +22 -9
  50. odxtools/dynamiclengthfield.py +5 -11
  51. odxtools/element.py +4 -3
  52. odxtools/endofpdufield.py +0 -2
  53. odxtools/environmentdatadescription.py +4 -6
  54. odxtools/exceptions.py +1 -1
  55. odxtools/field.py +9 -9
  56. odxtools/functionalclass.py +3 -5
  57. odxtools/inputparam.py +3 -5
  58. odxtools/leadinglengthinfotype.py +15 -2
  59. odxtools/loadfile.py +64 -0
  60. odxtools/minmaxlengthtype.py +20 -2
  61. odxtools/modification.py +3 -5
  62. odxtools/multiplexer.py +7 -14
  63. odxtools/multiplexercase.py +4 -6
  64. odxtools/multiplexerdefaultcase.py +4 -6
  65. odxtools/multiplexerswitchkey.py +4 -5
  66. odxtools/negoutputparam.py +3 -5
  67. odxtools/outputparam.py +3 -5
  68. odxtools/parameterinfo.py +3 -3
  69. odxtools/parameters/codedconstparameter.py +2 -14
  70. odxtools/parameters/lengthkeyparameter.py +3 -17
  71. odxtools/parameters/nrcconstparameter.py +2 -14
  72. odxtools/parameters/parameter.py +22 -22
  73. odxtools/parameters/parameterwithdop.py +6 -8
  74. odxtools/parameters/physicalconstantparameter.py +5 -8
  75. odxtools/parameters/reservedparameter.py +4 -3
  76. odxtools/parameters/tablekeyparameter.py +6 -9
  77. odxtools/parameters/tablestructparameter.py +6 -8
  78. odxtools/parameters/valueparameter.py +5 -8
  79. odxtools/paramlengthinfotype.py +19 -6
  80. odxtools/parentref.py +15 -1
  81. odxtools/physicaldimension.py +3 -5
  82. odxtools/progcode.py +18 -7
  83. odxtools/protstack.py +3 -5
  84. odxtools/py.typed +0 -0
  85. odxtools/relateddoc.py +7 -9
  86. odxtools/request.py +8 -0
  87. odxtools/response.py +8 -0
  88. odxtools/scaleconstr.py +3 -3
  89. odxtools/singleecujob.py +12 -10
  90. odxtools/snrefcontext.py +29 -0
  91. odxtools/specialdata.py +3 -5
  92. odxtools/specialdatagroup.py +5 -7
  93. odxtools/specialdatagroupcaption.py +3 -6
  94. odxtools/standardlengthtype.py +27 -2
  95. odxtools/state.py +3 -5
  96. odxtools/statechart.py +9 -11
  97. odxtools/statetransition.py +4 -9
  98. odxtools/staticfield.py +4 -8
  99. odxtools/table.py +7 -8
  100. odxtools/tablerow.py +7 -6
  101. odxtools/teammember.py +3 -5
  102. odxtools/templates/comparam-spec.odx-c.xml.jinja2 +2 -5
  103. odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +2 -5
  104. odxtools/templates/macros/printCompanyData.xml.jinja2 +2 -5
  105. odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
  106. odxtools/templates/macros/printCompuMethod.xml.jinja2 +153 -0
  107. odxtools/templates/macros/printDOP.xml.jinja2 +10 -132
  108. odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
  109. odxtools/templates/macros/printElementId.xml.jinja2 +3 -3
  110. odxtools/templates/macros/printMux.xml.jinja2 +3 -2
  111. odxtools/templates/macros/printTable.xml.jinja2 +2 -3
  112. odxtools/unit.py +3 -5
  113. odxtools/unitgroup.py +3 -5
  114. odxtools/unitspec.py +9 -10
  115. odxtools/utils.py +1 -26
  116. odxtools/version.py +2 -2
  117. odxtools/{write_pdx_file.py → writepdxfile.py} +19 -10
  118. odxtools/xdoc.py +3 -5
  119. {odxtools-7.1.0.dist-info → odxtools-7.2.0.dist-info}/METADATA +1 -1
  120. odxtools-7.2.0.dist-info/RECORD +192 -0
  121. {odxtools-7.1.0.dist-info → odxtools-7.2.0.dist-info}/WHEEL +1 -1
  122. odxtools/createcompanydatas.py +0 -17
  123. odxtools/createsdgs.py +0 -19
  124. odxtools/load_file.py +0 -13
  125. odxtools/load_odx_d_file.py +0 -6
  126. odxtools/load_pdx_file.py +0 -8
  127. odxtools-7.1.0.dist-info/RECORD +0 -185
  128. /odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +0 -0
  129. {odxtools-7.1.0.dist-info → odxtools-7.2.0.dist-info}/LICENSE +0 -0
  130. {odxtools-7.1.0.dist-info → odxtools-7.2.0.dist-info}/entry_points.txt +0 -0
  131. {odxtools-7.1.0.dist-info → odxtools-7.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,153 @@
1
+ {#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printElementId.xml.jinja2') as peid %}
7
+ {%- import('macros/printAdminData.xml.jinja2') as pad %}
8
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
9
+ {%- import('macros/printDescription.xml.jinja2') as pd %}
10
+
11
+
12
+ {%- macro printLimit(tag_name, limit_obj) -%}
13
+ {%- if limit_obj is not none %}
14
+ <{{tag_name}}
15
+ {%- if limit_obj.interval_type is not none %}
16
+ {{- make_xml_attrib("INTERVAL-TYPE", limit_obj.interval_type.value) }}
17
+ {%- endif %}
18
+ {%- if limit_obj.value_raw is none %}
19
+ {#- #}/>
20
+ {%- else %}
21
+ {#- #}>
22
+ {%- if hasattr(limit_obj._value, 'hex') -%}
23
+ {#- bytes or bytarray limit #}
24
+ {{- limit_obj._value.hex().upper() }}
25
+ {%- else -%}
26
+ {{- limit_obj._value }}
27
+ {%- endif -%}
28
+ </{{tag_name}}>
29
+ {%- endif -%}
30
+ {%- endif -%}
31
+ {%- endmacro -%}
32
+
33
+ {%- macro printCompuInverseValue(civ) -%}
34
+ <COMPU-INVERSE-VALUE>
35
+ {%- if civ.v is not none %}
36
+ <V>{{civ.v}}</V>
37
+ {%- endif %}
38
+ {%- if civ.vt is not none %}
39
+ <VT>{{civ.vt | e}}</VT>
40
+ {%- endif %}
41
+ </COMPU-INVERSE-VALUE>
42
+ {%- endmacro -%}
43
+
44
+ {%- macro printCompuDefaultValue(cdv) -%}
45
+ <COMPU-DEFAULT-VALUE>
46
+ {%- if cdv.v is not none %}
47
+ <V>{{cdv.v}}</V>
48
+ {%- endif %}
49
+ {%- if cdv.vt is not none %}
50
+ <VT>{{cdv.vt | e}}</VT>
51
+ {%- endif %}
52
+ {%- if cdv.compu_inverse_value is not none %}
53
+ {{printCompuInverseValue(cdv.compu_inverse_value)}}
54
+ {%- endif %}
55
+ </COMPU-DEFAULT-VALUE>
56
+ {%- endmacro -%}
57
+
58
+ {%- macro printCompuScale(cs) -%}
59
+ <COMPU-SCALE>
60
+ {%- if cs.short_label is not none %}
61
+ <SHORT-LABEL>{{cs.short_label|e}}</SHORT-LABEL>
62
+ {%- endif %}
63
+ {{- pd.printDescription(cs.description)|indent(2, first=True) }}
64
+ {{- printLimit("LOWER-LIMIT", cs.lower_limit)|indent(2, first=True) }}
65
+ {{- printLimit("UPPER-LIMIT", cs.upper_limit)|indent(2, first=True) }}
66
+ {%- if cs.compu_inverse_value is not none %}
67
+ {{printCompuInverseValue(cs.compu_inverse_value)}}
68
+ {%- endif %}
69
+ {%- if cs.compu_const is not none %}
70
+ <COMPU-CONST>
71
+ {%- if cs.compu_const.v is not none %}
72
+ <V>{{cs.compu_const.v}}</V>
73
+ {%- endif %}
74
+ {%- if cs.compu_const.vt is not none %}
75
+ <VT>{{cs.compu_const.vt | e}}</VT>
76
+ {%- endif %}
77
+ </COMPU-CONST>
78
+ {%- endif %}
79
+ {%- set crc = cs.compu_rational_coeffs %}
80
+ {%- if crc is not none %}
81
+ <COMPU-RATIONAL-COEFFS>
82
+ <COMPU-NUMERATOR>
83
+ {%- for v in crc.numerators %}
84
+ <V>{{v}}</V>
85
+ {%- endfor %}
86
+ </COMPU-NUMERATOR>
87
+ {%- if crc.denominators %}
88
+ <COMPU-DENOMINATOR>
89
+ {%- for v in crc.denominators %}
90
+ <V>{{v}}</V>
91
+ {%- endfor %}
92
+ </COMPU-DENOMINATOR>
93
+ {%- endif %}
94
+ </COMPU-RATIONAL-COEFFS>
95
+ {%- endif %}
96
+ </COMPU-SCALE>
97
+ {%- endmacro -%}
98
+
99
+ {%- macro printProgCode(pc) -%}
100
+ <PROG-CODE>
101
+ <CODE-FILE>{{pc.code_file}}</CODE-FILE>
102
+ <SYNTAX>{{pc.syntax}}</SYNTAX>
103
+ {%- if pc.encryption is not none %}
104
+ <ENCRYPTION>{{pc.encryption}}</ENCRYPTION>
105
+ {%- endif %}
106
+ {%- if pc.entry_point is not none %}
107
+ <ENTRY-POINT>{{pc.entry_point}}</ENTRY-POINT>
108
+ {%- endif %}
109
+ {%- if pc.library_refs %}
110
+ <LIBRARY-REFS>
111
+ {%- for libref in pc.library_refs %}
112
+ <LIBRARY-REF ID-REF="{{libref.ref_id}}" />
113
+ {%- endfor %}
114
+ </LIBRARY-REFS>
115
+ {%- endif %}
116
+ </PROG-CODE>
117
+ {%- endmacro -%}
118
+
119
+ {%- macro printCompuMethod(cm) -%}
120
+ <COMPU-METHOD>
121
+ <CATEGORY>{{cm.category.value}}</CATEGORY>
122
+ {%- if cm.compu_internal_to_phys is not none %}
123
+ <COMPU-INTERNAL-TO-PHYS>
124
+ <COMPU-SCALES>
125
+ {%- for cs in cm.compu_internal_to_phys.compu_scales %}
126
+ {{ printCompuScale(cs) | indent(3) }}
127
+ {%- endfor %}
128
+ </COMPU-SCALES>
129
+ {%- if cm.compu_internal_to_phys.prog_code is not none %}
130
+ {{ printProgCode(cm.compu_internal_to_phys.prog_code) | indent(3) }}
131
+ {%- endif %}
132
+ {%- if cm.compu_internal_to_phys.compu_default_value is not none %}
133
+ {{ printCompuDefaultValue(cm.compu_internal_to_phys.compu_default_value) | indent(3) }}
134
+ {%- endif %}
135
+ </COMPU-INTERNAL-TO-PHYS>
136
+ {%- endif %}
137
+ {%- if cm.compu_phys_to_internal is not none %}
138
+ <COMPU-PHYS-TO-INTERNAL>
139
+ <COMPU-SCALES>
140
+ {%- for cs in cm.compu_phys_to_internal.compu_scales %}
141
+ {{ printCompuScale(cs) | indent(3) }}
142
+ {%- endfor %}
143
+ </COMPU-SCALES>
144
+ {%- if cm.compu_phys_to_internal.prog_code is not none %}
145
+ {{ printProgCode(cm.compu_phys_to_internal.prog_code) | indent(3) }}
146
+ {%- endif %}
147
+ {%- if cm.compu_phys_to_internal.compu_default_value is not none %}
148
+ {{ printCompuDefaultValue(cm.compu_phys_to_internal.compu_default_value) | indent(3) }}
149
+ {%- endif %}
150
+ </COMPU-PHYS-TO-INTERNAL>
151
+ {%- endif %}
152
+ </COMPU-METHOD>
153
+ {%- endmacro -%}
@@ -6,6 +6,9 @@
6
6
  {%- import('macros/printElementId.xml.jinja2') as peid %}
7
7
  {%- import('macros/printAdminData.xml.jinja2') as pad %}
8
8
  {%- import('macros/printSpecialData.xml.jinja2') as psd %}
9
+ {%- import('macros/printCompuMethod.xml.jinja2') as pcm %}
10
+ {%- import('macros/printDescription.xml.jinja2') as pd %}
11
+
9
12
 
10
13
  {%- macro printDiagCodedType(dct) -%}
11
14
  <DIAG-CODED-TYPE {{-make_xml_attrib("BASE-DATA-TYPE", dct.base_data_type.value)}}
@@ -30,7 +33,6 @@
30
33
  </DIAG-CODED-TYPE>
31
34
  {%- endmacro -%}
32
35
 
33
-
34
36
  {%- macro printPhysicalType(physical_type) %}
35
37
  {%- if physical_type.display_radix is not none %}
36
38
  <PHYSICAL-TYPE BASE-DATA-TYPE="{{physical_type.base_data_type.value}}" DISPLAY-RADIX="{{physical_type.display_radix.name}}" />
@@ -43,39 +45,14 @@
43
45
  {%- endif %}
44
46
  {%- endmacro -%}
45
47
 
46
- {%- macro printLimit(tag_name, limit_obj) -%}
47
- {%- if limit_obj is not none %}
48
- <{{tag_name}}
49
- {%- if limit_obj.interval_type is not none %}
50
- {{- make_xml_attrib("INTERVAL-TYPE", limit_obj.interval_type.value) }}
51
- {%- endif %}
52
- {%- if limit_obj.value_raw is none %}
53
- {#- #}/>
54
- {%- else %}
55
- {#- #}>
56
- {%- if hasattr(limit_obj._value, 'hex') -%}
57
- {#- bytes or bytarray limit #}
58
- {{- limit_obj._value.hex().upper() }}
59
- {%- else -%}
60
- {{- limit_obj._value }}
61
- {%- endif -%}
62
- </{{tag_name}}>
63
- {%- endif -%}
64
- {%- endif -%}
65
- {%- endmacro -%}
66
-
67
48
  {%- macro printScaleConstr(sc) %}
68
49
  <SCALE-CONSTR VALIDITY="{{sc.validity.value}}">
69
50
  {%- if sc.short_label is not none %}
70
51
  <SHORT-LABEL>{{sc.short_label|e}}</SHORT-LABEL>
71
52
  {%- endif %}
72
- {%- if sc.description and sc.description.strip() %}
73
- <DESC>
74
- {{sc.description}}
75
- </DESC>
76
- {%- endif %}
77
- {{printLimit("LOWER-LIMIT", sc.lower_limit) }}
78
- {{printLimit("UPPER-LIMIT", sc.upper_limit) }}
53
+ {{pd.printDescription(sc.description)}}
54
+ {{pcm.printLimit("LOWER-LIMIT", sc.lower_limit) }}
55
+ {{pcm.printLimit("UPPER-LIMIT", sc.upper_limit) }}
79
56
  </SCALE-CONSTR>
80
57
  {%- endmacro -%}
81
58
 
@@ -85,8 +62,8 @@
85
62
  {%- else %}
86
63
  <INTERNAL-CONSTR>
87
64
  {%- endif %}
88
- {{printLimit("LOWER-LIMIT", ic.lower_limit) }}
89
- {{printLimit("UPPER-LIMIT", ic.upper_limit) }}
65
+ {{pcm.printLimit("LOWER-LIMIT", ic.lower_limit) }}
66
+ {{pcm.printLimit("UPPER-LIMIT", ic.upper_limit) }}
90
67
  {%- if ic.scale_constrs %}
91
68
  <SCALE-CONSTRS>
92
69
  {%- for sc in ic.scale_constrs %}
@@ -101,105 +78,6 @@
101
78
  {%- endif %}
102
79
  {%- endmacro -%}
103
80
 
104
- {%- macro printCompuMethod(cm) -%}
105
- <COMPU-METHOD>
106
- <CATEGORY>{{cm.category}}</CATEGORY>
107
- {%- if cm.category == "TEXTTABLE" %}
108
- <COMPU-INTERNAL-TO-PHYS>
109
- <COMPU-SCALES>
110
- {%- for cs in cm.internal_to_phys %}
111
- <COMPU-SCALE>
112
- {%- if cs.short_label and cs.short_label.strip() %}
113
- <SHORT-LABEL>{{cs.short_label|e}}</SHORT-LABEL>
114
- {%- endif %}
115
- {%- if cs.description and cs.description.strip() %}
116
- <DESC>
117
- {{cs.description}}
118
- </DESC>
119
- {%- endif %}
120
- {{printLimit("LOWER-LIMIT", cs.lower_limit) }}
121
- {{printLimit("UPPER-LIMIT", cs.upper_limit) }}
122
- {%- if cs.compu_inverse_value is not none %}
123
- <COMPU-INVERSE-VALUE>
124
- <V>{{cs.compu_inverse_value}}</V>
125
- </COMPU-INVERSE-VALUE>
126
- {%- endif %}
127
- <COMPU-CONST>
128
- <VT>{{cs.compu_const | e}}</VT>
129
- </COMPU-CONST>
130
- </COMPU-SCALE>
131
- {%- endfor %}
132
- </COMPU-SCALES>
133
- {%- if cm.compu_default_value is not none %}
134
- <COMPU-DEFAULT-VALUE>
135
- <VT>{{cm.compu_default_value.compu_const}}</VT>
136
- {%- if cm.compu_default_value.compu_inverse_value is not none %}
137
- <COMPU-INVERSE-VALUE>
138
- <V>{{cm.compu_default_value.compu_inverse_value}}</V>
139
- </COMPU-INVERSE-VALUE>
140
- {%- endif %}
141
- </COMPU-DEFAULT-VALUE>
142
- {%- endif %}
143
- </COMPU-INTERNAL-TO-PHYS>
144
- {%- elif cm.category == "LINEAR" %}
145
- <COMPU-INTERNAL-TO-PHYS>
146
- <COMPU-SCALES>
147
- <COMPU-SCALE>
148
- {{printLimit("LOWER-LIMIT", cm.internal_lower_limit) }}
149
- {{printLimit("UPPER-LIMIT", cm.internal_upper_limit) }}
150
- <COMPU-RATIONAL-COEFFS>
151
- <COMPU-NUMERATOR>
152
- <V>{{cm.offset}}</V>
153
- <V>{{cm.factor}}</V>
154
- </COMPU-NUMERATOR>
155
- {%- if cm.denominator != 1 %}
156
- <COMPU-DENOMINATOR>
157
- <V>{{cm.denominator}}</V>
158
- </COMPU-DENOMINATOR>
159
- {%- endif %}
160
- </COMPU-RATIONAL-COEFFS>
161
- </COMPU-SCALE>
162
- </COMPU-SCALES>
163
- </COMPU-INTERNAL-TO-PHYS>
164
- {%- elif cm.category == "SCALE-LINEAR" %}
165
- <COMPU-INTERNAL-TO-PHYS>
166
- <COMPU-SCALES>
167
- {%- for lm in cm.linear_methods %}
168
- <COMPU-SCALE>
169
- {{printLimit("LOWER-LIMIT", lm.internal_lower_limit) }}
170
- {{printLimit("UPPER-LIMIT", lm.internal_upper_limit) }}
171
- <COMPU-RATIONAL-COEFFS>
172
- <COMPU-NUMERATOR>
173
- <V>{{lm.offset}}</V>
174
- <V>{{lm.factor}}</V>
175
- </COMPU-NUMERATOR>
176
- {%- if lm.denominator != 1 %}
177
- <COMPU-DENOMINATOR>
178
- <V>{{lm.denominator}}</V>
179
- </COMPU-DENOMINATOR>
180
- {%- endif %}
181
- </COMPU-RATIONAL-COEFFS>
182
- </COMPU-SCALE>
183
- {%- endfor %}
184
- </COMPU-SCALES>
185
- </COMPU-INTERNAL-TO-PHYS>
186
- {%- elif cm.category == "TAB-INTP" %}
187
- <COMPU-INTERNAL-TO-PHYS>
188
- <COMPU-SCALES>
189
- {%- for idx in range( cm.internal_points | length ) %}
190
- <COMPU-SCALE>
191
- <LOWER-LIMIT>{{ cm.internal_points[idx] }}</LOWER-LIMIT>
192
- <COMPU-CONST>
193
- <V>{{ cm.physical_points[idx] }}</V>
194
- </COMPU-CONST>
195
- </COMPU-SCALE>
196
- {%- endfor %}
197
- </COMPU-SCALES>
198
- </COMPU-INTERNAL-TO-PHYS>
199
- {%- endif %}
200
- </COMPU-METHOD>
201
- {%- endmacro -%}
202
-
203
81
  {%- macro printDopBaseAttribs(dop) %}
204
82
  {{- make_xml_attrib("ID", dop.odx_id.local_id) }}
205
83
  {{- make_xml_attrib("OID", dop.oid) }}
@@ -225,7 +103,7 @@
225
103
  {%- macro printDataObjectProp(dop) %}
226
104
  <DATA-OBJECT-PROP {{- printDopBaseAttribs(dop) }}>
227
105
  {{- printDopBaseSubtags(dop) }}
228
- {{- printCompuMethod(dop.compu_method)|indent(1) }}
106
+ {{- pcm.printCompuMethod(dop.compu_method)|indent(1) }}
229
107
  {{- printDiagCodedType(dop.diag_coded_type)|indent(1) }}
230
108
  {{- printPhysicalType(dop.physical_type)|indent(1) }}
231
109
  {%- if dop.internal_constr %}
@@ -246,7 +124,7 @@
246
124
  {{- printDopBaseSubtags(dop)|indent(1) }}
247
125
  {{- printDiagCodedType(dop.diag_coded_type)|indent(1) }}
248
126
  {{- printPhysicalType(dop.physical_type)|indent(1) }}
249
- {{- printCompuMethod(dop.compu_method)|indent(1) }}
127
+ {{- pcm.printCompuMethod(dop.compu_method)|indent(1) }}
250
128
  <DTCS>
251
129
  {%- for dtc in dop.dtcs_raw %}
252
130
  {%- if hasattr(dtc, "ref_id") %}
@@ -0,0 +1,18 @@
1
+ {#- -*- mode: sgml; tab-width: 1; sgml-basic-offset: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- macro printDescription(desc) %}
7
+ {%- if desc is not none %}
8
+ <DESC {{make_xml_attrib("TI", desc.text_identifier)}}>{{desc.text}}
9
+ {%- if desc.external_docs %}
10
+ <EXTERNAL-DOCS>
11
+ {%- for ed in desc.external_docs %}
12
+ <EXTERNAL-DOC HREF="{{ed}}" />
13
+ {%- endfor %}
14
+ </EXTERNAL-DOCS>
15
+ {%- endif -%}
16
+ </DESC>
17
+ {%- endif %}
18
+ {%- endmacro %}
@@ -3,12 +3,12 @@
3
3
  # SPDX-License-Identifier: MIT
4
4
  -#}
5
5
 
6
+ {%- import('macros/printDescription.xml.jinja2') as pd %}
7
+
6
8
  {%- macro printElementIdSubtags(obj) -%}
7
9
  <SHORT-NAME>{{ obj.short_name }}</SHORT-NAME>
8
10
  {%- if obj.long_name %}
9
11
  <LONG-NAME>{{ obj.long_name|e }}</LONG-NAME>
10
12
  {%- endif %}
11
- {%- if obj.description %}
12
- <DESC>{{ obj.description }}</DESC>
13
- {%- endif %}
13
+ {{- pd.printDescription(obj.description) }}
14
14
  {%- endmacro -%}
@@ -4,6 +4,7 @@
4
4
  -#}
5
5
 
6
6
  {%- import('macros/printElementId.xml.jinja2') as peid %}
7
+ {%- import('macros/printCompuMethod.xml.jinja2') as pcm %}
7
8
  {%- import('macros/printDOP.xml.jinja2') as pdop %}
8
9
 
9
10
  {%- macro printMux(mux) %}
@@ -41,8 +42,8 @@
41
42
  {%- if case.structure_snref is not none %}
42
43
  <STRUCTURE-SNREF SHORT_NAME="{{case.structure_snref}}"/>
43
44
  {%- endif %}
44
- {{ pdop.printLimit("LOWER-LIMIT", case.lower_limit) }}
45
- {{ pdop.printLimit("UPPER-LIMIT", case.upper_limit) }}
45
+ {{ pcm.printLimit("LOWER-LIMIT", case.lower_limit) }}
46
+ {{ pcm.printLimit("UPPER-LIMIT", case.upper_limit) }}
46
47
  </CASE>
47
48
  {%- endfor %}
48
49
  </CASES>
@@ -5,6 +5,7 @@
5
5
 
6
6
  {%- import('macros/printElementId.xml.jinja2') as peid %}
7
7
  {%- import('macros/printSpecialData.xml.jinja2') as psd %}
8
+ {%- import('macros/printDescription.xml.jinja2') as pd %}
8
9
 
9
10
  {%- macro printTable(table) %}
10
11
  <TABLE ID="{{table.odx_id.local_id}}"
@@ -21,9 +22,7 @@
21
22
  {%- if table_row.long_name %}
22
23
  <LONG-NAME>{{table_row.long_name|e}}</LONG-NAME>
23
24
  {%- endif %}
24
- {%- if table_row.description %}
25
- <DESC>{{table_row.description}}</DESC>
26
- {%- endif %}
25
+ {{ pd.printDescription(table_row.description) }}
27
26
  <KEY>{{table_row.key|e}}</KEY>
28
27
  {%- if table_row.dop_ref %}
29
28
  <DATA-OBJECT-PROP-REF ID-REF="{{ table_row.dop_ref.ref_id }}" />
odxtools/unit.py CHANGED
@@ -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
3
+ from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import IdentifiableElement
7
7
  from .exceptions import odxassert, odxrequire
8
8
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
9
9
  from .physicaldimension import PhysicalDimension
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
 
16
14
  @dataclass
17
15
  class Unit(IdentifiableElement):
@@ -104,5 +102,5 @@ class Unit(IdentifiableElement):
104
102
  f"The physical_dimension_ref must be resolved to a PhysicalDimension."
105
103
  f" {self.physical_dimension_ref} referenced {self._physical_dimension}")
106
104
 
107
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
105
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
108
106
  pass
odxtools/unitgroup.py CHANGED
@@ -1,19 +1,17 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
3
  from enum import Enum
4
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
4
+ from typing import Any, Dict, List, Optional, cast
5
5
  from xml.etree import ElementTree
6
6
 
7
7
  from .element import NamedElement
8
8
  from .exceptions import odxraise, odxrequire
9
9
  from .nameditemlist import NamedItemList
10
10
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
11
+ from .snrefcontext import SnRefContext
11
12
  from .unit import Unit
12
13
  from .utils import dataclass_fields_asdict
13
14
 
14
- if TYPE_CHECKING:
15
- from .diaglayer import DiagLayer
16
-
17
15
 
18
16
  class UnitGroupCategory(Enum):
19
17
  COUNTRY = "COUNTRY"
@@ -57,7 +55,7 @@ class UnitGroup(NamedElement):
57
55
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
58
56
  self._units = NamedItemList[Unit]([odxlinks.resolve(ref) for ref in self.unit_refs])
59
57
 
60
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
58
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
61
59
  pass
62
60
 
63
61
  @property
odxtools/unitspec.py CHANGED
@@ -1,19 +1,16 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Dict, List, Union
3
+ from typing import Any, Dict, List, Union
4
4
  from xml.etree import ElementTree
5
5
 
6
- from .createsdgs import create_sdgs_from_et
7
6
  from .nameditemlist import NamedItemList
8
7
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
9
8
  from .physicaldimension import PhysicalDimension
9
+ from .snrefcontext import SnRefContext
10
10
  from .specialdatagroup import SpecialDataGroup
11
11
  from .unit import Unit
12
12
  from .unitgroup import UnitGroup
13
13
 
14
- if TYPE_CHECKING:
15
- from .diaglayer import DiagLayer
16
-
17
14
 
18
15
  @dataclass
19
16
  class UnitSpec:
@@ -49,7 +46,9 @@ class UnitSpec:
49
46
  PhysicalDimension.from_et(el, doc_frags)
50
47
  for el in et_element.iterfind("PHYSICAL-DIMENSIONS/PHYSICAL-DIMENSION")
51
48
  ]
52
- sdgs = create_sdgs_from_et(et_element.find("SDGS"), doc_frags)
49
+ sdgs = [
50
+ SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
51
+ ]
53
52
 
54
53
  return UnitSpec(
55
54
  unit_groups=unit_groups,
@@ -76,10 +75,10 @@ class UnitSpec:
76
75
  for sdg in self.sdgs:
77
76
  sdg._resolve_odxlinks(odxlinks)
78
77
 
79
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
78
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
80
79
  for unit in self.units:
81
- unit._resolve_snrefs(diag_layer)
80
+ unit._resolve_snrefs(context)
82
81
  for group in self.unit_groups:
83
- group._resolve_snrefs(diag_layer)
82
+ group._resolve_snrefs(context)
84
83
  for sdg in self.sdgs:
85
- sdg._resolve_snrefs(diag_layer)
84
+ sdg._resolve_snrefs(context)
odxtools/utils.py CHANGED
@@ -1,32 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import dataclasses
3
3
  import re
4
- from typing import Any, Dict, Optional
5
- from xml.etree import ElementTree
6
-
7
-
8
- def create_description_from_et(et_element: Optional[ElementTree.Element],) -> Optional[str]:
9
- """Read a description tag.
10
-
11
- The description is located underneath the DESC tag of an an ODX
12
- element."""
13
-
14
- if et_element is None:
15
- return None
16
-
17
- if et_element.tag != "DESC":
18
- raise TypeError(f"Attempted to extract an ODX description from a "
19
- f"'{et_element.tag}' XML node. (Must be a 'DESC' node!)")
20
-
21
- # Extract the contents of the tag as a XHTML string.
22
- raw_string = et_element.text or ""
23
- for e in et_element:
24
- raw_string += ElementTree.tostring(e, encoding="unicode")
25
-
26
- # remove white spaces at the beginning and at the end of lines
27
- stripped_lines = [x.strip() for x in raw_string.split("\n")]
28
-
29
- return "\n".join(stripped_lines).strip()
4
+ from typing import Any, Dict
30
5
 
31
6
 
32
7
  def dataclass_fields_asdict(obj: Any) -> Dict[str, Any]:
odxtools/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '7.1.0'
16
- __version_tuple__ = version_tuple = (7, 1, 0)
15
+ __version__ = version = '7.2.0'
16
+ __version_tuple__ = version_tuple = (7, 2, 0)
@@ -1,10 +1,11 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import datetime
3
3
  import inspect
4
+ import mimetypes
4
5
  import os
5
6
  import time
6
7
  import zipfile
7
- from typing import Any, Dict, List, Optional, Tuple
8
+ from typing import Any, Dict, Optional
8
9
 
9
10
  import jinja2
10
11
 
@@ -60,7 +61,6 @@ __templates_dir = os.path.sep.join([os.path.dirname(__module_filename), "templat
60
61
  def write_pdx_file(
61
62
  output_file_name: str,
62
63
  database: Database,
63
- auxiliary_content_specifiers: Optional[List[Tuple[str, bytes]]] = None,
64
64
  templates_dir: str = __templates_dir,
65
65
  ) -> bool:
66
66
  """
@@ -68,9 +68,6 @@ def write_pdx_file(
68
68
  """
69
69
  global odxdatabase
70
70
 
71
- if auxiliary_content_specifiers is None:
72
- auxiliary_content_specifiers = []
73
-
74
71
  odxdatabase = database
75
72
 
76
73
  file_index = []
@@ -96,12 +93,18 @@ def write_pdx_file(
96
93
  # are written based on the database)
97
94
  continue
98
95
 
99
- template_file_mime_type = "text/plain"
96
+ template_file_mime_type = None
100
97
  if template_file_name.endswith(".odx-cs"):
101
98
  template_file_mime_type = "application/x-asam.odx.odx-cs"
102
99
  elif template_file_name.endswith(".odx-d"):
103
100
  template_file_mime_type = "application/x-asam.odx.odx-d"
104
101
 
102
+ guessed_mime_type, guessed_encoding = mimetypes.guess_type(template_file_name)
103
+ if template_file_mime_type is None and guessed_mime_type is not None:
104
+ template_file_mime_type = guessed_mime_type
105
+ else:
106
+ template_file_mime_type = "application/octet-stream"
107
+
105
108
  in_path = [root]
106
109
  in_path.append(template_file_name)
107
110
  in_file_name = os.path.sep.join(in_path)
@@ -115,20 +118,26 @@ def write_pdx_file(
115
118
  out_file.write(open(in_file_name, "rb").read())
116
119
 
117
120
  # write the auxiliary files
118
- for output_file_name, data in auxiliary_content_specifiers:
121
+ for output_file_name, data_file in database.auxiliary_files.items():
119
122
  file_cdate = datetime.datetime.fromtimestamp(time.time())
120
123
  creation_date = file_cdate.strftime("%Y-%m-%dT%H:%M:%S")
121
124
 
122
- mime_type = "text/plain"
125
+ mime_type = None
123
126
  if output_file_name.endswith(".odx-cs"):
124
127
  mime_type = "application/x-asam.odx.odx-cs"
125
128
  elif output_file_name.endswith(".odx-d"):
126
129
  mime_type = "application/x-asam.odx.odx-d"
127
130
 
131
+ guessed_mime_type, guessed_encoding = mimetypes.guess_type(output_file_name)
132
+ if mime_type is None and guessed_mime_type is not None:
133
+ mime_type = guessed_mime_type
134
+ else:
135
+ mime_type = "application/octet-stream"
136
+
128
137
  zf_name = os.path.basename(output_file_name)
129
138
  with zf.open(zf_name, "w") as out_file:
130
139
  file_index.append((zf_name, creation_date, mime_type))
131
- out_file.write(data)
140
+ out_file.write(data_file.read())
132
141
 
133
142
  jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_dir))
134
143
  jinja_env.globals["hasattr"] = hasattr
@@ -187,7 +196,7 @@ def write_pdx_file(
187
196
 
188
197
  # write the index.xml file
189
198
  vars["file_index"] = file_index
190
- index_tpl = jinja_env.get_template("index.xml.xml.jinja2")
199
+ index_tpl = jinja_env.get_template("index.xml.jinja2")
191
200
  text = index_tpl.render(**vars)
192
201
  zf.writestr("index.xml", text)
193
202
 
odxtools/xdoc.py CHANGED
@@ -1,15 +1,13 @@
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 Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from .element import NamedElement
7
7
  from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
8
+ from .snrefcontext import SnRefContext
8
9
  from .utils import dataclass_fields_asdict
9
10
 
10
- if TYPE_CHECKING:
11
- from .diaglayer import DiagLayer
12
-
13
11
 
14
12
  @dataclass
15
13
  class XDoc(NamedElement):
@@ -45,5 +43,5 @@ class XDoc(NamedElement):
45
43
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
46
44
  pass
47
45
 
48
- def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
46
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
49
47
  pass