vss-tools 0.5.0.dev0__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 (39) hide show
  1. vspec/__init__.py +996 -0
  2. vspec/loggingconfig.py +22 -0
  3. vspec/model/__init__.py +7 -0
  4. vspec/model/constants.py +307 -0
  5. vspec/model/exceptions.py +29 -0
  6. vspec/model/vsstree.py +602 -0
  7. vspec/py.typed +0 -0
  8. vspec/utils/__init__.py +23 -0
  9. vspec/utils/idgen_utils.py +97 -0
  10. vspec/utils/stringstyle.py +25 -0
  11. vspec/utils/vss2id_val.py +165 -0
  12. vspec/vspec2vss_config.py +53 -0
  13. vspec/vspec2x.py +191 -0
  14. vspec/vss2x.py +38 -0
  15. vspec/vssexporters/__init__.py +7 -0
  16. vspec/vssexporters/vss2binary.py +147 -0
  17. vspec/vssexporters/vss2csv.py +82 -0
  18. vspec/vssexporters/vss2ddsidl.py +295 -0
  19. vspec/vssexporters/vss2franca.py +98 -0
  20. vspec/vssexporters/vss2graphql.py +143 -0
  21. vspec/vssexporters/vss2id.py +172 -0
  22. vspec/vssexporters/vss2json.py +116 -0
  23. vspec/vssexporters/vss2jsonschema.py +159 -0
  24. vspec/vssexporters/vss2protobuf.py +171 -0
  25. vspec/vssexporters/vss2yaml.py +122 -0
  26. vss_tools-0.5.0.dev0.data/scripts/vspec2csv.py +29 -0
  27. vss_tools-0.5.0.dev0.data/scripts/vspec2ddsidl.py +29 -0
  28. vss_tools-0.5.0.dev0.data/scripts/vspec2franca.py +29 -0
  29. vss_tools-0.5.0.dev0.data/scripts/vspec2graphql.py +29 -0
  30. vss_tools-0.5.0.dev0.data/scripts/vspec2id.py +28 -0
  31. vss_tools-0.5.0.dev0.data/scripts/vspec2json.py +29 -0
  32. vss_tools-0.5.0.dev0.data/scripts/vspec2jsonschema.py +29 -0
  33. vss_tools-0.5.0.dev0.data/scripts/vspec2protobuf.py +29 -0
  34. vss_tools-0.5.0.dev0.data/scripts/vspec2yaml.py +29 -0
  35. vss_tools-0.5.0.dev0.dist-info/LICENSE +373 -0
  36. vss_tools-0.5.0.dev0.dist-info/METADATA +65 -0
  37. vss_tools-0.5.0.dev0.dist-info/RECORD +39 -0
  38. vss_tools-0.5.0.dev0.dist-info/WHEEL +5 -0
  39. vss_tools-0.5.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright (c) 2022 Contributors to COVESA
4
+ #
5
+ # This program and the accompanying materials are made available under the
6
+ # terms of the Mozilla Public License 2.0 which is available at
7
+ # https://www.mozilla.org/en-US/MPL/2.0/
8
+ #
9
+ # SPDX-License-Identifier: MPL-2.0
10
+
11
+ # Convert vspec tree to binary format
12
+
13
+ import argparse
14
+ import logging
15
+ import ctypes
16
+ import os.path
17
+ from typing import Optional
18
+ from vspec.model.vsstree import VSSNode, VSSType
19
+ from vspec.vss2x import Vss2X
20
+ from vspec.vspec2vss_config import Vspec2VssConfig
21
+
22
+ out_file = ""
23
+ _cbinary = None
24
+
25
+
26
+ def createBinaryCnode(fname, nodename, nodetype, uuid, description, nodedatatype, nodemin, nodemax, unit, allowed,
27
+ defaultAllowed, validate, children):
28
+ global _cbinary
29
+ _cbinary.createBinaryCnode(fname, nodename, nodetype, uuid, description, nodedatatype, nodemin, nodemax, unit,
30
+ allowed, defaultAllowed, validate, children)
31
+
32
+
33
+ def allowedString(allowedList):
34
+ allowedStr = ""
35
+ for elem in allowedList:
36
+ allowedStr += hexAllowedLen(elem) + elem
37
+ # print("allowedstr=" + allowedStr + "\n")
38
+ return allowedStr
39
+
40
+
41
+ def hexAllowedLen(allowed):
42
+ hexDigit1 = len(allowed) // 16
43
+ hexDigit2 = len(allowed) - hexDigit1*16
44
+ # print("Hexdigs:" + str(hexDigit1) + str(hexDigit2))
45
+ return "".join([intToHexChar(hexDigit1), intToHexChar(hexDigit2)])
46
+
47
+
48
+ def intToHexChar(hexInt):
49
+ if (hexInt < 10):
50
+ return chr(hexInt + ord('0'))
51
+ else:
52
+ return chr(hexInt - 10 + ord('A'))
53
+
54
+
55
+ def export_node(node, generate_uuid, out_file):
56
+ nodename = str(node.name)
57
+ b_nodename = nodename.encode('utf-8')
58
+
59
+ nodetype = str(node.type.value)
60
+ b_nodetype = nodetype.encode('utf-8')
61
+
62
+ nodedescription = str(node.description)
63
+ b_nodedescription = nodedescription.encode('utf-8')
64
+
65
+ children = len(node.children)
66
+
67
+ nodedatatype = ""
68
+ nodemin = ""
69
+ nodemax = ""
70
+ nodeunit = ""
71
+ nodeallowed = ""
72
+ nodedefault = ""
73
+ nodeuuid = ""
74
+ nodevalidate = "" # exported to binary
75
+
76
+ if node.type == VSSType.SENSOR or node.type == VSSType.ACTUATOR or node.type == VSSType.ATTRIBUTE:
77
+ nodedatatype = str(node.datatype.value)
78
+ b_nodedatatype = nodedatatype.encode('utf-8')
79
+
80
+ # many optional attributes are initilized to "" in vsstree.py
81
+ if node.min != "":
82
+ nodemin = str(node.min)
83
+ b_nodemin = nodemin.encode('utf-8')
84
+
85
+ if node.max != "":
86
+ nodemax = str(node.max)
87
+ b_nodemax = nodemax.encode('utf-8')
88
+
89
+ if node.allowed != "":
90
+ nodeallowed = allowedString(node.allowed)
91
+ b_nodeallowed = nodeallowed.encode('utf-8')
92
+
93
+ if node.default != "":
94
+ nodedefault = str(node.default)
95
+ b_nodedefault = nodedefault.encode('utf-8')
96
+
97
+ # in case of unit or aggregate, the attribute will be missing
98
+ try:
99
+ nodeunit = str(node.unit.value)
100
+ except AttributeError:
101
+ pass
102
+ b_nodeunit = nodeunit.encode('utf-8')
103
+
104
+ if generate_uuid:
105
+ nodeuuid = node.uuid
106
+ b_nodeuuid = nodeuuid.encode('utf-8')
107
+
108
+ if "validate" in node.extended_attributes:
109
+ nodevalidate = node.extended_attributes["validate"]
110
+ b_nodevalidate = nodevalidate.encode('utf-8')
111
+
112
+ b_fname = out_file.encode('utf-8')
113
+
114
+ createBinaryCnode(b_fname, b_nodename, b_nodetype, b_nodeuuid, b_nodedescription, b_nodedatatype, b_nodemin,
115
+ b_nodemax, b_nodeunit, b_nodeallowed, b_nodedefault, b_nodevalidate, children)
116
+
117
+ for child in node.children:
118
+ export_node(child, generate_uuid, out_file)
119
+
120
+
121
+ class Vss2Binary(Vss2X):
122
+
123
+ def __init__(self, vspec2vss_config: Vspec2VssConfig):
124
+ vspec2vss_config.type_tree_supported = False
125
+ vspec2vss_config.no_expand_option_supported = False
126
+
127
+ def generate(self, config: argparse.Namespace, root: VSSNode, vspec2vss_config: Vspec2VssConfig,
128
+ data_type_root: Optional[VSSNode] = None) -> None:
129
+ global _cbinary
130
+ dllName = "../../binary/binarytool.so"
131
+ dllAbsPath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + dllName
132
+ if not os.path.isfile(dllAbsPath):
133
+ logging.error("The required library binarytool.so is not available, exiting!")
134
+ logging.info("You must build the library, "
135
+ "see https://github.com/COVESA/vss-tools/blob/master/binary/README.md!")
136
+ return
137
+ _cbinary = ctypes.CDLL(dllAbsPath)
138
+
139
+ _cbinary.createBinaryCnode.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p,
140
+ ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p,
141
+ ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p,
142
+ ctypes.c_int)
143
+
144
+ logging.info("Generating binary output...")
145
+ out_file = config.output_file
146
+ export_node(root, vspec2vss_config.generate_uuid, out_file)
147
+ logging.info("Binary output generated in " + out_file)
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright (c) 2021 Contributors to COVESA
4
+ #
5
+ # This program and the accompanying materials are made available under the
6
+ # terms of the Mozilla Public License 2.0 which is available at
7
+ # https://www.mozilla.org/en-US/MPL/2.0/
8
+ #
9
+ # SPDX-License-Identifier: MPL-2.0
10
+
11
+ # Convert vspec tree to CSV
12
+
13
+
14
+ import argparse
15
+ import logging
16
+ from vspec.model.vsstree import VSSNode
17
+ from anytree import PreOrderIter # type: ignore[import]
18
+ from typing import AnyStr
19
+ from typing import Optional
20
+ from vspec.vss2x import Vss2X
21
+ from vspec.vspec2vss_config import Vspec2VssConfig
22
+
23
+
24
+ # Write the header line
25
+
26
+
27
+ def print_csv_header(file, uuid, entry_type: AnyStr, include_instance_column: bool):
28
+ arg_list = [entry_type, "Type", "DataType", "Deprecated", "Unit",
29
+ "Min", "Max", "Desc", "Comment", "Allowed", "Default"]
30
+ if uuid:
31
+ arg_list.append("Id")
32
+ if include_instance_column:
33
+ arg_list.append("Instances")
34
+ file.write(format_csv_line(arg_list))
35
+
36
+ # Format a data or header line according to the CSV standard (IETF RFC 4180)
37
+
38
+
39
+ def format_csv_line(csv_fields):
40
+ formatted_csv_line = ""
41
+ for csv_field in csv_fields:
42
+ formatted_csv_line = formatted_csv_line + '"' + str(csv_field).replace('"', '""') + '",'
43
+ return formatted_csv_line[:-1] + '\n'
44
+
45
+ # Write the data lines
46
+
47
+
48
+ def print_csv_content(file, tree: VSSNode, uuid, include_instance_column: bool):
49
+ tree_node: VSSNode
50
+ for tree_node in PreOrderIter(tree):
51
+ data_type_str = tree_node.get_datatype()
52
+ unit_str = tree_node.get_unit()
53
+ arg_list = [tree_node.qualified_name('.'), tree_node.type.value, data_type_str, tree_node.deprecation,
54
+ unit_str, tree_node.min, tree_node.max, tree_node.description, tree_node.comment,
55
+ tree_node.allowed, tree_node.default]
56
+ if uuid:
57
+ arg_list.append(tree_node.uuid)
58
+ if include_instance_column and tree_node.instances is not None:
59
+ arg_list.append(tree_node.instances)
60
+ file.write(format_csv_line(arg_list))
61
+
62
+
63
+ class Vss2Csv(Vss2X):
64
+
65
+ def generate(self, config: argparse.Namespace, signal_root: VSSNode, vspec2vss_config: Vspec2VssConfig,
66
+ data_type_root: Optional[VSSNode] = None) -> None:
67
+ logging.info("Generating CSV output...")
68
+
69
+ # generic entry should be written when both data types and signals are being written to the same file
70
+ generic_entry = data_type_root is not None and config.types_output_file is None
71
+ include_instance_column = not vspec2vss_config.expand_model
72
+ with open(config.output_file, 'w') as f:
73
+ signal_entry_type = "Node" if generic_entry else "Signal"
74
+ print_csv_header(f, vspec2vss_config.generate_uuid, signal_entry_type, include_instance_column)
75
+ print_csv_content(f, signal_root, vspec2vss_config.generate_uuid, include_instance_column)
76
+ if data_type_root is not None and generic_entry is True:
77
+ print_csv_content(f, data_type_root, vspec2vss_config.generate_uuid, include_instance_column)
78
+
79
+ if data_type_root is not None and generic_entry is False:
80
+ with open(config.types_output_file, 'w') as f:
81
+ print_csv_header(f, vspec2vss_config.generate_uuid, "Node", include_instance_column)
82
+ print_csv_content(f, data_type_root, vspec2vss_config.generate_uuid, include_instance_column)
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright (c) 2022 Contributors to COVESA
4
+ #
5
+ # This program and the accompanying materials are made available under the
6
+ # terms of the Mozilla Public License 2.0 which is available at
7
+ # https://www.mozilla.org/en-US/MPL/2.0/
8
+ #
9
+ # SPDX-License-Identifier: MPL-2.0
10
+
11
+ #
12
+ # Convert vspec files to DDS-IDL
13
+ #
14
+
15
+ import argparse
16
+ import keyword
17
+ import logging
18
+ from typing import Optional
19
+
20
+ from vspec.model.vsstree import VSSNode, VSSType
21
+ from vspec.vss2x import Vss2X
22
+ from vspec.vspec2vss_config import Vspec2VssConfig
23
+
24
+ c_keywords = [
25
+ "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float",
26
+ "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch",
27
+ "typedef", "union", "unsigned", "void", "volatile", "while"
28
+ ]
29
+
30
+ # Based on http://www.omg.org/spec/IDL/4.2/
31
+ idl_keywords = [
32
+ "abstract", "any", "alias", "attribute", "bitfield", "bitmask", "bitset", "boolean", "case", "char", "component",
33
+ "connector", "const", "consumes", "context", "custom", "default", "double", "exception", "emits", "enum",
34
+ "eventtype", "factory", "FALSE", "finder", "fixed", "float", "getraises", "home", "import", "in", "inout",
35
+ "interface", "local", "long", "manages", "map", "mirrorport", "module", "multiple", "native", "Object", "octet",
36
+ "oneway", "out", "primarykey", "private", "port", "porttype", "provides", "public", "publishes", "raises",
37
+ "readonly", "setraises", "sequence", "short", "string", "struct", "supports", "switch", "TRUE", "truncatable",
38
+ "typedef", "typeid", "typename", "typeprefix", "unsigned", "union", "uses", "ValueBase", "valuetype", "void",
39
+ "wchar", "wstring", "int8", "uint8", "int16", "int32", "int64", "uint16", "uint32", "uint64"
40
+ ]
41
+
42
+
43
+ def getAllowedName(name):
44
+ if (
45
+ name.lower() in c_keywords
46
+ or name.lower() in idl_keywords
47
+ or keyword.iskeyword(name.lower)
48
+ ):
49
+ return "_" + name
50
+ else:
51
+ return name
52
+
53
+
54
+ def get_allowed_enum_literal(name: str):
55
+ """
56
+ Check if this is is an allowed literal name, if not add prefix.
57
+
58
+ Background:
59
+
60
+ In VSS '123' is a perfectly fine string literal, usable as allowed value for a string.
61
+ The current exporter (this file) translated it previously to 123 which is not a valid DSS IDL literal.
62
+ Adding an underscore as prefix makes the generated IDL ok, but then gives problems if generating for example
63
+ Python code by Eclipse Cyclone DDS idlc Python Backend.
64
+ By that reason we now add a regular character instead.
65
+ """
66
+ if name[0].isdigit():
67
+ return "d" + name
68
+ return name
69
+
70
+
71
+ idlFileBuffer = []
72
+
73
+ dataTypesMap_covesa_dds = {"uint8": "octet",
74
+ "int8": "octet",
75
+ "uint16": "unsigned short",
76
+ "int16": "short",
77
+ "uint32": "unsigned long",
78
+ "int32": "long",
79
+ "uint64": "unsigned long long",
80
+ "int64": "long long",
81
+ "boolean": "boolean",
82
+ "float": "float",
83
+ "double": "double",
84
+ "string": "string"
85
+ }
86
+
87
+
88
+ def export_node(node, generate_uuid, generate_all_idl_features):
89
+ """
90
+ This method is used to traverse VSS node and to create corresponding DDS IDL buffer string
91
+ """
92
+ global idlFileBuffer
93
+ datatype = None
94
+ unit = None
95
+ min = None
96
+ max = None
97
+ defaultValue = None
98
+ allowedValues = None
99
+ arraysize = None
100
+
101
+ if node.type == VSSType.BRANCH:
102
+ idlFileBuffer.append("module " + getAllowedName(node.name))
103
+ idlFileBuffer.append("{")
104
+ for child in node.children:
105
+ export_node(child, generate_uuid, generate_all_idl_features)
106
+ idlFileBuffer.append("};")
107
+ idlFileBuffer.append("")
108
+ else:
109
+ isEnumCreated = False
110
+ # check if there is a need to create enum (based on the usage of allowed values)
111
+ if node.allowed != "":
112
+ """
113
+ enum should be enclosed under module block to avoid namespec conflict
114
+ module name for enum is chosen as the node name +
115
+ """
116
+ if (node.datatype.value in ["string", "string[]"]):
117
+ idlFileBuffer.append("module " + getAllowedName(node.name) + "_M")
118
+ idlFileBuffer.append("{")
119
+ idlFileBuffer.append("enum " + getAllowedName(node.name) +
120
+ "Values{"+str(",".join(get_allowed_enum_literal(item) for item in node.allowed)) +
121
+ "};")
122
+ isEnumCreated = True
123
+ idlFileBuffer.append("};")
124
+ allowedValues = str(node.allowed)
125
+ else:
126
+ print(f"Warning: VSS2IDL can only handle allowed values for string type, "
127
+ f"signal {node.name} has type {node.datatype.value}")
128
+
129
+ idlFileBuffer.append("struct " + getAllowedName(node.name))
130
+ idlFileBuffer.append("{")
131
+ if generate_uuid:
132
+ idlFileBuffer.append("string uuid;")
133
+ # fetching value of datatype and obtaining the equivalent DDS type
134
+ try:
135
+ datatype_str = node.get_datatype()
136
+ if node.has_datatype():
137
+ if datatype_str in dataTypesMap_covesa_dds:
138
+ datatype = str(dataTypesMap_covesa_dds[datatype_str])
139
+ elif '[' in datatype_str:
140
+ nodevalueArray = datatype_str.split("[", 1)
141
+ if str(nodevalueArray[0]) in dataTypesMap_covesa_dds:
142
+ datatype = str(dataTypesMap_covesa_dds[str(nodevalueArray[0])])
143
+ arraysize = '[' + str(arraysize) + nodevalueArray[1]
144
+ else: # no primitive type. this is custom
145
+ datatype = datatype_str.replace(".", "::") # custom data type
146
+
147
+ except AttributeError:
148
+ pass
149
+ # fetching value of unit
150
+ try:
151
+ unit = str(node.unit.value)
152
+ except AttributeError:
153
+ pass
154
+
155
+ if node.min != "":
156
+ min = str(node.min)
157
+ if node.max != "":
158
+ max = str(node.max)
159
+ if node.default != "":
160
+ defaultValue = node.default
161
+ if isinstance(defaultValue, str) and not isEnumCreated:
162
+ defaultValue = "\""+defaultValue+"\""
163
+
164
+ if datatype is not None:
165
+ # adding range if min and max are specified in vspec file
166
+ if min is not None and max is not None and generate_all_idl_features:
167
+ idlFileBuffer.append("@range(min=" + str(min) + " ,max=" + str(max) + ")")
168
+
169
+ if allowedValues is None:
170
+ if defaultValue is None:
171
+ idlFileBuffer.append(
172
+ ("sequence<" + datatype + "> value" if arraysize is not None else datatype + " value") + ";")
173
+ else:
174
+ # default values in IDL file are not accepted by CycloneDDS/FastDDS :
175
+ # these values can be generated if --all-idl-features is set as True
176
+ idlFileBuffer.append(
177
+ ("sequence<" + datatype + "> value" if arraysize is not None else datatype + " value") +
178
+ (" default " + str(defaultValue) if generate_all_idl_features else "") + ";")
179
+ else:
180
+ # this is the case where allowed values are provided, accordingly contents are converted to enum
181
+ if defaultValue is None:
182
+ idlFileBuffer.append(getAllowedName(node.name)+"_M::"+getAllowedName(node.name)+"Values value;")
183
+ else:
184
+ # default values in IDL file are not accepted by CycloneDDS/FastDDS :
185
+ # these values can be generated if --all-idl-features is set as True
186
+ idlFileBuffer.append(
187
+ getAllowedName(node.name) + "_M::" + getAllowedName(node.name) +
188
+ "Values value" + (" " + str(defaultValue) if generate_all_idl_features else "") + ";")
189
+
190
+ if unit is not None:
191
+ idlFileBuffer.append(("" if generate_all_idl_features else "//") + "const string unit=\"" + unit + "\";")
192
+
193
+ idlFileBuffer.append(("" if generate_all_idl_features else "//") + "const string type =\"" +
194
+ str(node.type.value) + "\";")
195
+
196
+ idlFileBuffer.append(("" if generate_all_idl_features else "//") + "const string description=\"" +
197
+ node.description + "\";")
198
+ idlFileBuffer.append("};")
199
+
200
+
201
+ class StructExporter(object):
202
+ """
203
+ Helper class used for generating export output for struct data types.
204
+ """
205
+
206
+ def __init__(self):
207
+ self.str_buf = ""
208
+ self.structs_seen = []
209
+
210
+ def export(self, root) -> str:
211
+ self.str_buf = ""
212
+ self.structs_seen = []
213
+ self.export_data_type_node(root)
214
+ return self.str_buf
215
+
216
+ def export_data_type_node(self, node):
217
+ """
218
+ This method is used to traverse VSS node and to create corresponding DDS IDL buffer string
219
+ """
220
+
221
+ prefix = ""
222
+ suffix = ""
223
+ if node.is_branch():
224
+ prefix = f"module {getAllowedName(node.name)}" + " {\n"
225
+ suffix = "};\n"
226
+ elif node.is_struct():
227
+ # check if the properties use structs that have not been seen before
228
+ # if not, add a forward declaration
229
+ fwds = []
230
+ for c in node.children:
231
+ # primtive type
232
+ if c.has_datatype():
233
+ continue
234
+
235
+ datatype_str = c.get_datatype().replace('.', '::').split("[", 1)[0]
236
+ if datatype_str not in self.structs_seen:
237
+ base_type = datatype_str.split("::")[-1]
238
+ fwds.append(base_type)
239
+
240
+ fwds.sort()
241
+ for f in set(fwds):
242
+ prefix += f"struct {f};\n"
243
+
244
+ prefix += f"struct {getAllowedName(node.name)}" + " {\n"
245
+ suffix = "};\n"
246
+ self.structs_seen.append(node.qualified_name("::").split("[", 1)[0])
247
+ else:
248
+ datatype_str = node.get_datatype().replace('.', '::').split("[", 1)[0]
249
+ is_seq = '[' in node.get_datatype()
250
+ if is_seq:
251
+ self.str_buf += f"sequence<{datatype_str}> {getAllowedName(node.name)};\n"
252
+ else:
253
+ self.str_buf += (f"{datatype_str} {getAllowedName(node.name)};\n")
254
+
255
+ self.str_buf += (f"{prefix}")
256
+
257
+ for child in node.children:
258
+ self.export_data_type_node(child)
259
+ self.str_buf += suffix
260
+
261
+
262
+ def export_idl(file, root, generate_uuids=True, generate_all_idl_features=False):
263
+ """This method is used to traverse through the root VSS node to build
264
+ -> DDS IDL equivalent string buffer and to serialize it acccordingly into a file
265
+ """
266
+ export_node(root, generate_uuids, generate_all_idl_features)
267
+ file.write('\n'.join(idlFileBuffer))
268
+ logging.info("IDL file generated at location : " + file.name)
269
+
270
+
271
+ class Vss2DdsIdl(Vss2X):
272
+
273
+ def __init__(self, vspec2vss_config: Vspec2VssConfig):
274
+ vspec2vss_config.no_expand_option_supported = False
275
+ vspec2vss_config.separate_output_type_file_supported = False
276
+
277
+ def add_arguments(self, parser: argparse.ArgumentParser):
278
+ parser.description = "The DDS-IDL exporter"
279
+ parser.add_argument('--all-idl-features', action='store_true',
280
+ help='Generate all features based on DDS IDL 4.2 specification')
281
+
282
+ def generate(self, config: argparse.Namespace, signal_root: VSSNode, vspec2vss_config: Vspec2VssConfig,
283
+ data_type_root: Optional[VSSNode] = None) -> None:
284
+ logging.info("Generating DDS-IDL output...")
285
+
286
+ if data_type_root is not None:
287
+ exporter = StructExporter()
288
+ with open(config.output_file, 'w') as idl_out:
289
+ idl_out.write(exporter.export(data_type_root))
290
+
291
+ with open(config.output_file, 'a' if data_type_root is not None else 'w') as idl_out:
292
+ export_idl(idl_out, signal_root, vspec2vss_config.generate_uuid, config.all_idl_features)
293
+
294
+ def __del__(self):
295
+ idlFileBuffer.clear()
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright (c) 2021 Contributors to COVESA
4
+ #
5
+ # This program and the accompanying materials are made available under the
6
+ # terms of the Mozilla Public License 2.0 which is available at
7
+ # https://www.mozilla.org/en-US/MPL/2.0/
8
+ #
9
+ # SPDX-License-Identifier: MPL-2.0
10
+
11
+ # Convert vspec tree to franca
12
+
13
+
14
+ import argparse
15
+ from typing import Optional
16
+ from vspec.model.vsstree import VSSNode
17
+ from anytree import PreOrderIter # type: ignore[import]
18
+ from vspec.vss2x import Vss2X
19
+ from vspec.vspec2vss_config import Vspec2VssConfig
20
+
21
+
22
+ # Write the header line
23
+
24
+
25
+ def print_franca_header(file, version="unknown"):
26
+ file.write(f"""
27
+ // Copyright (C) 2022, COVESA
28
+ //
29
+ // This program is licensed under the terms and conditions of the
30
+ // Mozilla Public License, version 2.0. The full text of the
31
+ // Mozilla Public License is at https://www.mozilla.org/MPL/2.0/
32
+
33
+ const UTF8String VSS_VERSION = "{version}"
34
+
35
+ struct SignalSpec {{
36
+ UInt32 id
37
+ String name
38
+ String type
39
+ String description
40
+ String datatype
41
+ String unit
42
+ Double min
43
+ Double max
44
+ }}
45
+
46
+ const SignalSpec[] signal_spec = [
47
+ """)
48
+
49
+
50
+ # Write the data lines
51
+ def print_franca_content(file, tree, uuid):
52
+ output = ""
53
+ for tree_node in PreOrderIter(tree):
54
+ if tree_node.parent:
55
+ if output:
56
+ output += ",\n{"
57
+ else:
58
+ output += "{"
59
+ output += f"\tname: \"{tree_node.qualified_name('.')}\""
60
+ output += f",\n\ttype: \"{tree_node.type.value}\""
61
+ output += f",\n\tdescription: \"{tree_node.description}\""
62
+ if tree_node.has_datatype():
63
+ output += f",\n\tdatatype: \"{tree_node.get_datatype()}\""
64
+ if uuid:
65
+ output += f",\n\tuuid: \"{tree_node.uuid}\""
66
+ if tree_node.has_unit():
67
+ output += f",\n\tunit: \"{tree_node.get_unit()}\""
68
+ if tree_node.min:
69
+ output += f",\n\tmin: {tree_node.min}"
70
+ if tree_node.max:
71
+ output += f",\n\tmax: {tree_node.max}"
72
+ if tree_node.allowed:
73
+ output += f",\n\tallowed: {tree_node.allowed}"
74
+
75
+ output += "\n}"
76
+ file.write(f"{output}")
77
+
78
+
79
+ class Vss2Franca(Vss2X):
80
+
81
+ def __init__(self, vspec2vss_config: Vspec2VssConfig):
82
+ vspec2vss_config.no_expand_option_supported = False
83
+ vspec2vss_config.type_tree_supported = False
84
+
85
+ def add_arguments(self, parser: argparse.ArgumentParser):
86
+ # Renamed from -v to --franca-vss-version to avoid conflict when using
87
+ # -vt (Otherwise -vt would be interpreted as "-v t")
88
+ parser.add_argument('--franca-vss-version', metavar='franca_vss_version',
89
+ help=" Add version information to franca file.")
90
+
91
+ def generate(self, config: argparse.Namespace, signal_root: VSSNode, vspec2vss_config: Vspec2VssConfig,
92
+ data_type_root: Optional[VSSNode] = None) -> None:
93
+ print("Generating Franca output...")
94
+ outfile = open(config.output_file, 'w')
95
+ print_franca_header(outfile, config.franca_vss_version)
96
+ print_franca_content(outfile, signal_root, vspec2vss_config.generate_uuid)
97
+ outfile.write("\n]")
98
+ outfile.close()