forked from COVESA/vss-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvspec2x.py
executable file
·186 lines (156 loc) · 9.55 KB
/
vspec2x.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# Copyright (c) 2016 Contributors to COVESA
#
# This program and the accompanying materials are made available under the
# terms of the Mozilla Public License 2.0 which is available at
# https://www.mozilla.org/en-US/MPL/2.0/
#
# SPDX-License-Identifier: MPL-2.0
#
# Convert vspec files to various other formats
#
from vspec.model.vsstree import VSSNode
from vspec.model.constants import VSSTreeType
from vspec.loggingconfig import initLogging
from vspec.vss2x import Vss2X
from vspec.vspec2vss_config import Vspec2VssConfig
import argparse
import logging
import sys
import vspec
class Vspec2X():
"""
Framework for translating from *.vspec files to first an internal VSS model,
and then to something else called X.
Users must provide a Vss2X generator that can generate X if they get a VSS model as input.
"""
def __init__(self, generator: Vss2X, vspec2vss_config: Vspec2VssConfig):
self.generator = generator
self.vspec2vss_config = vspec2vss_config
def main(self, arguments):
initLogging()
parser = argparse.ArgumentParser(description="Convert vspec to other formats.")
parser.add_argument('-I', '--include-dir', action='append', metavar='dir', type=str, default=[],
help='Add include directory to search for included vspec files.')
if self.vspec2vss_config.extended_attributes_supported:
parser.add_argument('-e', '--extended-attributes', type=str, default="",
help='Whitelisted extended attributes as comma separated list.')
parser.add_argument('-s', '--strict', action='store_true',
help='Use strict checking: Terminate when anything not covered or not recommended '
'by VSS language or extensions is found.')
parser.add_argument('--abort-on-unknown-attribute', action='store_true',
help="Terminate when an unknown attribute is found.")
parser.add_argument('--abort-on-name-style', action='store_true',
help="Terminate if name style does not follow VSS standard catalog naming convention.")
if self.vspec2vss_config.uuid_supported:
parser.add_argument('--uuid', action='store_true',
help='Include uuid in generated files. (Deprecated, will be removed in VSS-tools 6.0)')
if self.vspec2vss_config.expand_model and self.vspec2vss_config.no_expand_option_supported:
parser.add_argument('--no-expand', action='store_true',
help='Do not expand tree.')
parser.add_argument('-o', '--overlays', action='append', metavar='overlays', type=str, default=[],
help='Add overlay that will be layered on top of the VSS file in the order they appear.')
parser.add_argument('-q', '--quantity-file', action='append', metavar='quantity_file', type=str, default=[],
help='Quantity file to be used for generation. Argument -q may be used multiple times.')
parser.add_argument('-u', '--unit-file', action='append', metavar='unit_file', type=str, default=[],
help='Unit file to be used for generation. Argument -u may be used multiple times.')
parser.add_argument('vspec_file', metavar='<vspec_file>',
help='The vehicle specification file to convert.')
if self.vspec2vss_config.output_file_required:
parser.add_argument('output_file', metavar='<output_file>',
help='The file to write output to.')
if self.vspec2vss_config.type_tree_supported:
type_group = parser.add_argument_group('VSS Data Type Tree arguments',
'Arguments related to struct/type support')
type_group.add_argument('-vt', '--vspec-types-file', action='append', metavar='vspec_types_file', type=str,
default=[],
help='Data types file in vspec format.')
type_group.add_argument('-ot', '--types-output-file', metavar='<types_output_file>',
help='Output file for writing data types from vspec file. ' +
'If not specified, a single file is used where applicable. ' +
'In case of JSON and YAML, the data is exported under a ' +
'special key - "ComplexDataTypes"')
self.generator.add_arguments(parser.add_argument_group(
"Exporter specific arguments", ""))
args = parser.parse_args(arguments)
include_dirs = ["."]
include_dirs.extend(args.include_dir)
abort_on_unknown_attribute = False
abort_on_namestyle = False
if args.abort_on_unknown_attribute or args.strict:
abort_on_unknown_attribute = True
if args.abort_on_name_style or args.strict:
abort_on_namestyle = True
if self.vspec2vss_config.extended_attributes_supported and (len(args.extended_attributes) > 0):
known_extended_attributes_list = args.extended_attributes.split(",")
vspec.model.vsstree.VSSNode.whitelisted_extended_attributes = known_extended_attributes_list
logging.info(f"Known extended attributes: {', '.join(known_extended_attributes_list)}")
else:
known_extended_attributes_list = list()
self.vspec2vss_config.generate_uuid = self.vspec2vss_config.uuid_supported and args.uuid
# Follow up to https://github.com/COVESA/vehicle_signal_specification/pull/721
# Deprecate --uuid
if self.vspec2vss_config.generate_uuid:
logging.warning("The argument --uuid is deprecated and the uuid feature is planned "
"to be removed in VSS-tools 6.0")
logging.info("If you need static identifiers consider using the vspec2id tool")
self.vspec2vss_config.expand_model = (self.vspec2vss_config.expand_model and not
(self.vspec2vss_config.no_expand_option_supported and args.no_expand))
vspec.load_quantities(args.vspec_file, args.quantity_file)
vspec.load_units(args.vspec_file, args.unit_file)
# process data type tree
data_type_tree = None
if self.vspec2vss_config.type_tree_supported:
if args.types_output_file is not None and not args.vspec_types_file:
parser.error("An output file for data types was provided. Please also provide "
"the input vspec file for data types")
if args.vspec_types_file:
data_type_tree = self.processDataTypeTree(
parser, args, include_dirs, abort_on_namestyle)
vspec.verify_mandatory_attributes(data_type_tree, abort_on_unknown_attribute)
try:
logging.info(f"Loading vspec from {args.vspec_file}...")
tree = vspec.load_tree(
args.vspec_file, include_dirs, VSSTreeType.SIGNAL_TREE,
break_on_name_style_violation=abort_on_namestyle,
expand_inst=False, data_type_tree=data_type_tree)
for overlay in args.overlays:
logging.info(f"Applying VSS overlay from {overlay}...")
othertree = vspec.load_tree(overlay, include_dirs, VSSTreeType.SIGNAL_TREE,
break_on_name_style_violation=abort_on_namestyle, expand_inst=False,
data_type_tree=data_type_tree)
vspec.merge_tree(tree, othertree)
vspec.check_type_usage(tree, VSSTreeType.SIGNAL_TREE, data_type_tree)
if self.vspec2vss_config.expand_model:
vspec.expand_tree_instances(tree)
vspec.clean_metadata(tree)
vspec.verify_mandatory_attributes(tree, abort_on_unknown_attribute)
logging.info("Calling exporter...")
self.generator.generate(args, tree, self.vspec2vss_config, data_type_tree)
logging.info("All done.")
except vspec.VSpecError as e:
logging.error(f"Error: {e}")
sys.exit(255)
def processDataTypeTree(self, parser: argparse.ArgumentParser, args, include_dirs,
abort_on_namestyle: bool) -> VSSNode:
"""
Helper function to process command line arguments and invoke logic for processing data
type information provided in vspec format
"""
if args.types_output_file is None:
logging.info("Sensors and custom data types will be consolidated into one file.")
# Nope, we should not know this
# if args.format == Exporter.protobuf:
# logging.info("Proto files will be written to the current working directory")
logging.warning("All exports do not yet support structs. Please check documentation for your exporter!")
first_tree = True
for type_file in args.vspec_types_file:
logging.info(f"Loading and processing struct/data type tree from {type_file}")
new_tree = vspec.load_tree(type_file, include_dirs, VSSTreeType.DATA_TYPE_TREE,
break_on_name_style_violation=abort_on_namestyle, expand_inst=False)
if first_tree:
tree = new_tree
first_tree = False
else:
vspec.merge_tree(tree, new_tree)
vspec.check_type_usage(tree, VSSTreeType.DATA_TYPE_TREE)
return tree