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.
- vspec/__init__.py +996 -0
- vspec/loggingconfig.py +22 -0
- vspec/model/__init__.py +7 -0
- vspec/model/constants.py +307 -0
- vspec/model/exceptions.py +29 -0
- vspec/model/vsstree.py +602 -0
- vspec/py.typed +0 -0
- vspec/utils/__init__.py +23 -0
- vspec/utils/idgen_utils.py +97 -0
- vspec/utils/stringstyle.py +25 -0
- vspec/utils/vss2id_val.py +165 -0
- vspec/vspec2vss_config.py +53 -0
- vspec/vspec2x.py +191 -0
- vspec/vss2x.py +38 -0
- vspec/vssexporters/__init__.py +7 -0
- vspec/vssexporters/vss2binary.py +147 -0
- vspec/vssexporters/vss2csv.py +82 -0
- vspec/vssexporters/vss2ddsidl.py +295 -0
- vspec/vssexporters/vss2franca.py +98 -0
- vspec/vssexporters/vss2graphql.py +143 -0
- vspec/vssexporters/vss2id.py +172 -0
- vspec/vssexporters/vss2json.py +116 -0
- vspec/vssexporters/vss2jsonschema.py +159 -0
- vspec/vssexporters/vss2protobuf.py +171 -0
- vspec/vssexporters/vss2yaml.py +122 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2csv.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2ddsidl.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2franca.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2graphql.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2id.py +28 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2json.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2jsonschema.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2protobuf.py +29 -0
- vss_tools-0.5.0.dev0.data/scripts/vspec2yaml.py +29 -0
- vss_tools-0.5.0.dev0.dist-info/LICENSE +373 -0
- vss_tools-0.5.0.dev0.dist-info/METADATA +65 -0
- vss_tools-0.5.0.dev0.dist-info/RECORD +39 -0
- vss_tools-0.5.0.dev0.dist-info/WHEEL +5 -0
- vss_tools-0.5.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Copyright (c) 2023 Contributors to COVESA
|
|
2
|
+
#
|
|
3
|
+
# This program and the accompanying materials are made available under the
|
|
4
|
+
# terms of the Mozilla Public License 2.0 which is available at
|
|
5
|
+
# https://www.mozilla.org/en-US/MPL/2.0/
|
|
6
|
+
#
|
|
7
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_node_identifier_bytes(
|
|
11
|
+
qualified_name: str,
|
|
12
|
+
data_type: str,
|
|
13
|
+
node_type: str,
|
|
14
|
+
unit: str,
|
|
15
|
+
allowed: str,
|
|
16
|
+
minimum: str,
|
|
17
|
+
maximum: str,
|
|
18
|
+
strict_mode: bool,
|
|
19
|
+
) -> bytes:
|
|
20
|
+
"""Get a node identifier as bytes. Used as an input for hashing
|
|
21
|
+
|
|
22
|
+
@param qualified_name: full path to the node
|
|
23
|
+
@param data_type: its datatype
|
|
24
|
+
@param node_type: its node type
|
|
25
|
+
@param unit: the unit if it uses one
|
|
26
|
+
@param allowed: the enum for allowed values
|
|
27
|
+
@param minimum: min value for the data if exists
|
|
28
|
+
@param maximum: max value for the data if exists
|
|
29
|
+
@param strict_mode: strict mode means case sensitivity of node qualified names
|
|
30
|
+
@return: a bytes representation of the node
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
node_identifier: bytes = (
|
|
34
|
+
f"{qualified_name}: "
|
|
35
|
+
f"unit: {unit}, "
|
|
36
|
+
f"datatype: {data_type}, "
|
|
37
|
+
f"type: {node_type}"
|
|
38
|
+
f"allowed: {allowed}"
|
|
39
|
+
f"min: {minimum}"
|
|
40
|
+
f"max: {maximum}"
|
|
41
|
+
).encode()
|
|
42
|
+
|
|
43
|
+
if strict_mode:
|
|
44
|
+
return node_identifier
|
|
45
|
+
else:
|
|
46
|
+
return node_identifier.lower()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def fnv1_32_hash(identifier: bytes) -> int:
|
|
50
|
+
"""32-bit hash of a node according to Fowler–Noll–Vo
|
|
51
|
+
|
|
52
|
+
@param identifier: a bytes representation of a node
|
|
53
|
+
@return: hashed value for the node as int
|
|
54
|
+
"""
|
|
55
|
+
id_hash = 2166136261
|
|
56
|
+
for byte in identifier:
|
|
57
|
+
id_hash = (id_hash * 16777619) & 0xFFFFFFFF
|
|
58
|
+
id_hash ^= byte
|
|
59
|
+
|
|
60
|
+
return id_hash
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def fnv1_32_wrapper(name: str, source: dict, strict_mode: bool):
|
|
64
|
+
"""A wrapper for the 32-bit hashing function if the input node
|
|
65
|
+
is represented as dict instead of VSSNode
|
|
66
|
+
|
|
67
|
+
@param name: full name aka qualified name
|
|
68
|
+
@param source:
|
|
69
|
+
@param strict_mode: strict mode means case sensitivity of node qualified names
|
|
70
|
+
@return:
|
|
71
|
+
"""
|
|
72
|
+
# Verify and assign values from source dictionary using source.get
|
|
73
|
+
allowed: str = source.get("allowed", "")
|
|
74
|
+
minimum: str = source.get("min", "")
|
|
75
|
+
maximum: str = source.get("max", "")
|
|
76
|
+
datatype: str = source.get("datatype", "")
|
|
77
|
+
vsstype: str = source.get("type", "")
|
|
78
|
+
unit: str = source.get("unit", "")
|
|
79
|
+
|
|
80
|
+
identifier = get_node_identifier_bytes(
|
|
81
|
+
name,
|
|
82
|
+
datatype,
|
|
83
|
+
vsstype,
|
|
84
|
+
unit,
|
|
85
|
+
allowed,
|
|
86
|
+
minimum,
|
|
87
|
+
maximum,
|
|
88
|
+
strict_mode,
|
|
89
|
+
)
|
|
90
|
+
return format(fnv1_32_hash(identifier), "08X")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_all_keys_values(d: dict):
|
|
94
|
+
for key, value in d.items():
|
|
95
|
+
yield key, value
|
|
96
|
+
if isinstance(value, dict):
|
|
97
|
+
yield from get_all_keys_values(value)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2023 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
|
+
import re
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def camel_case(st):
|
|
15
|
+
"""Camel case string conversion"""
|
|
16
|
+
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', st)
|
|
17
|
+
s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
|
18
|
+
return re.sub(r'(?:^|_)([a-z])', lambda x: x.group(1).upper(), s2)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def camel_back(st):
|
|
22
|
+
"""Camel back string conversion"""
|
|
23
|
+
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', st)
|
|
24
|
+
s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
|
25
|
+
return re.sub(r'_([a-z])', lambda x: x.group(1).upper(), s2)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Copyright (c) 2023 Contributors to COVESA
|
|
2
|
+
#
|
|
3
|
+
# This program and the accompanying materials are made available under the
|
|
4
|
+
# terms of the Mozilla Public License 2.0 which is available at
|
|
5
|
+
# https://www.mozilla.org/en-US/MPL/2.0/
|
|
6
|
+
#
|
|
7
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import logging
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
from anytree import PreOrderIter # type: ignore
|
|
15
|
+
|
|
16
|
+
from vspec.model.vsstree import VSSNode
|
|
17
|
+
from vspec.utils.idgen_utils import fnv1_32_wrapper
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def validate_static_uids(
|
|
21
|
+
signals_dict: dict, validation_tree: VSSNode, config: argparse.Namespace
|
|
22
|
+
):
|
|
23
|
+
"""Check if static UIDs have changed or if new ones need to be added
|
|
24
|
+
|
|
25
|
+
@param signals_dict: to be exported dict of all signals containing static UID
|
|
26
|
+
@param validation_tree: tree loaded from validation file
|
|
27
|
+
@param config: the command line arguments the script was run with
|
|
28
|
+
@return: None
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def check_description(k: str, v: dict, match_tuple: tuple):
|
|
32
|
+
validation_node: VSSNode = validation_tree_nodes[match_tuple[1]]
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
assert v["description"] == validation_node.description
|
|
36
|
+
|
|
37
|
+
except AssertionError:
|
|
38
|
+
logging.warning(
|
|
39
|
+
"[Validation] "
|
|
40
|
+
f"DESCRIPTION MISMATCH: The description of {k} has changed from "
|
|
41
|
+
f"\n\t Validation: '{validation_node.description}' to \n\t Current "
|
|
42
|
+
f"vspec: '{v['description']}'"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def check_semantics(k: str, v: dict, strict_mode: bool) -> Optional[int]:
|
|
46
|
+
"""Checks if the change was a semantic or path change. This can be triggered by
|
|
47
|
+
manually adding a fka (formerly known as) attribute to the vspec. The result
|
|
48
|
+
is that the old hash can be matched such that a node keeps the same UID.
|
|
49
|
+
|
|
50
|
+
@param k: the current key
|
|
51
|
+
@param v: the current value (dict)
|
|
52
|
+
@param strict_mode: strict mode means case sensitivity for static UID generation
|
|
53
|
+
@return: boolean if it was a semantic or path change
|
|
54
|
+
"""
|
|
55
|
+
if "fka" in v.keys():
|
|
56
|
+
semantic_match: Optional[int] = None
|
|
57
|
+
for fka_val in v["fka"]:
|
|
58
|
+
old_static_uid = "0x" + fnv1_32_wrapper(fka_val, v, strict_mode)
|
|
59
|
+
for i, validation_node in enumerate(validation_tree_nodes):
|
|
60
|
+
if (
|
|
61
|
+
old_static_uid
|
|
62
|
+
== validation_node.extended_attributes["staticUID"]
|
|
63
|
+
):
|
|
64
|
+
logging.warning(
|
|
65
|
+
f"[Validation] SEMANTIC NAME CHANGE or PATH CHANGE for '{k}', "
|
|
66
|
+
f"it used to be '{validation_node.qualified_name()}'."
|
|
67
|
+
)
|
|
68
|
+
semantic_match = i
|
|
69
|
+
return semantic_match
|
|
70
|
+
else:
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
def check_deprecation(k: str, v: dict, match_tuple: tuple):
|
|
74
|
+
if (
|
|
75
|
+
"deprecation" in v.keys()
|
|
76
|
+
and validation_tree_nodes[match_tuple[1]].deprecation
|
|
77
|
+
):
|
|
78
|
+
if v["deprecation"] != validation_tree_nodes[match_tuple[1]].deprecation:
|
|
79
|
+
logging.warning(
|
|
80
|
+
f"[Validation] DEPRECATION MSG CHANGE: Deprecation message "
|
|
81
|
+
f"for '{k}' was "
|
|
82
|
+
f"'{validation_tree_nodes[match_tuple[1]].deprecation}' "
|
|
83
|
+
f"in validation but now is '{v['deprecation']}'."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def hashed_pipeline():
|
|
87
|
+
"""This pipeline uses FNV-1 hash for static UIDs.
|
|
88
|
+
|
|
89
|
+
If no UID was matched we check if the user has written an old path or old name,
|
|
90
|
+
so we can tell if it was a semantic or path change. If semantic or path change
|
|
91
|
+
we trigger a corresponding warning.
|
|
92
|
+
If not semantic or path change we try to match the key:
|
|
93
|
+
If key was matched we know that it was a unit, datatype, type, enum, min/max change
|
|
94
|
+
which triggers `BREAKING CHANGE` warning. If key cannot be matched the node must have
|
|
95
|
+
been added since the last validation, so it triggers an `ADDED ATTRIBUTE` warning.
|
|
96
|
+
If there was a UID match we will continue to check for non-breaking changes and throw
|
|
97
|
+
corresponding logs.
|
|
98
|
+
In the end the remaining nodes correspond to deleted nodes, so we throw a
|
|
99
|
+
`DELETED ATTRIBUTE` warning.
|
|
100
|
+
"""
|
|
101
|
+
nonlocal validation_tree_nodes
|
|
102
|
+
|
|
103
|
+
for key, value in signals_dict.items():
|
|
104
|
+
matched_uids = []
|
|
105
|
+
for id_validation_tree, other_node in enumerate(validation_tree_nodes):
|
|
106
|
+
if value["staticUID"] == other_node.extended_attributes["staticUID"]:
|
|
107
|
+
if key != other_node.qualified_name():
|
|
108
|
+
_ = check_semantics(key, value, config.strict_mode)
|
|
109
|
+
matched_uids.append((key, id_validation_tree))
|
|
110
|
+
# if not matched via UID check semantics or path change
|
|
111
|
+
if len(matched_uids) == 0:
|
|
112
|
+
semantic_match = check_semantics(key, value, config.strict_mode)
|
|
113
|
+
if semantic_match is None:
|
|
114
|
+
key_found: bool = False
|
|
115
|
+
for i, node in enumerate(validation_tree_nodes):
|
|
116
|
+
if key == node.qualified_name():
|
|
117
|
+
key_found = True
|
|
118
|
+
validation_tree_nodes.pop(i)
|
|
119
|
+
break
|
|
120
|
+
|
|
121
|
+
if key_found:
|
|
122
|
+
logging.warning(
|
|
123
|
+
f"[Validation] BREAKING CHANGE: "
|
|
124
|
+
f"There was a breaking change for '{key}' which "
|
|
125
|
+
f"means its name, unit, datatype, type, enum or "
|
|
126
|
+
f"min/max has changed."
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
logging.warning(
|
|
130
|
+
f"[Validation] ADDED ATTRIBUTE: "
|
|
131
|
+
f"The node '{key}' was added since the last validation."
|
|
132
|
+
)
|
|
133
|
+
else:
|
|
134
|
+
validation_tree_nodes.pop(semantic_match)
|
|
135
|
+
|
|
136
|
+
elif len(matched_uids) == 1:
|
|
137
|
+
check_deprecation(key, value, matched_uids[0])
|
|
138
|
+
check_description(key, value, matched_uids[0])
|
|
139
|
+
|
|
140
|
+
validation_tree_nodes.pop(matched_uids[0][1])
|
|
141
|
+
|
|
142
|
+
else:
|
|
143
|
+
logging.error(
|
|
144
|
+
"[Validation] Multiple matches do not make sense "
|
|
145
|
+
"for the way we load the data. Please check your "
|
|
146
|
+
"input vspec!"
|
|
147
|
+
)
|
|
148
|
+
sys.exit(-1)
|
|
149
|
+
|
|
150
|
+
for node in validation_tree_nodes:
|
|
151
|
+
logging.warning(
|
|
152
|
+
"[Validation] DELETED ATTRIBUTE: "
|
|
153
|
+
f"'{node.qualified_name()}' was not matched so it must have "
|
|
154
|
+
f"been deleted."
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
if validation_tree.parent:
|
|
158
|
+
while validation_tree.parent:
|
|
159
|
+
validation_tree = validation_tree.parent
|
|
160
|
+
|
|
161
|
+
validation_tree_nodes: list = []
|
|
162
|
+
for val_node in PreOrderIter(validation_tree):
|
|
163
|
+
validation_tree_nodes.append(val_node)
|
|
164
|
+
|
|
165
|
+
hashed_pipeline()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2023 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
|
+
class Vspec2VssConfig:
|
|
12
|
+
"""
|
|
13
|
+
This class is intended to be a container for settings related to the conversion
|
|
14
|
+
from *.vspec files to the internal VSS model as well as for some generic vspec2x features.
|
|
15
|
+
A user may change settings before vspec2x.main is called.
|
|
16
|
+
Then vspec2x will use those settings to control which command line arguments
|
|
17
|
+
that will be accepted or considered, and based on those some of the settings in this
|
|
18
|
+
file may be overridden.
|
|
19
|
+
The config instance is later passed to the vss2x instance, so that it can consider
|
|
20
|
+
the settings as well.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self):
|
|
24
|
+
"""
|
|
25
|
+
Setting default/recommended features for vss-tools.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
# Input to model parsing
|
|
29
|
+
|
|
30
|
+
# Is it possible to request that uuid shall be generated
|
|
31
|
+
self.uuid_supported = True
|
|
32
|
+
# Shall it be possible to specify which extended attributes to consider?
|
|
33
|
+
self.extended_attributes_supported = True
|
|
34
|
+
# Shall it be possible to give a type tree
|
|
35
|
+
self.type_tree_supported = True
|
|
36
|
+
# Is it supported to get type data generated to a separate file
|
|
37
|
+
# Only relevant if self.type_tree_supported is True
|
|
38
|
+
self.separate_output_type_file_supported = True
|
|
39
|
+
|
|
40
|
+
# shall vspec2vss expand the model (by default)
|
|
41
|
+
self.expand_model = True
|
|
42
|
+
# if so shall there anyway be an option to NOT expand
|
|
43
|
+
self.no_expand_option_supported = True
|
|
44
|
+
|
|
45
|
+
# Is an output file required as part of command line arguments
|
|
46
|
+
self.output_file_required = True
|
|
47
|
+
|
|
48
|
+
# As of now we have only one type of nodes in the type tree
|
|
49
|
+
# and that is structs, so if we support type tree we assume structs are supported
|
|
50
|
+
|
|
51
|
+
# Default values for features
|
|
52
|
+
# These are typically updated by vspec2x when reading command line arguments
|
|
53
|
+
self.generate_uuid = False
|
vspec/vspec2x.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2016 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 various other formats
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
from vspec.model.vsstree import VSSNode
|
|
16
|
+
from vspec.model.constants import VSSTreeType
|
|
17
|
+
from vspec.loggingconfig import initLogging
|
|
18
|
+
from vspec.vss2x import Vss2X
|
|
19
|
+
from vspec.vspec2vss_config import Vspec2VssConfig
|
|
20
|
+
import argparse
|
|
21
|
+
import logging
|
|
22
|
+
import sys
|
|
23
|
+
import vspec
|
|
24
|
+
|
|
25
|
+
import pkg_resources # part of setuptools
|
|
26
|
+
VERSION = pkg_resources.require("vss-tools")[0].version
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Vspec2X():
|
|
30
|
+
"""
|
|
31
|
+
Framework for translating from *.vspec files to first an internal VSS model,
|
|
32
|
+
and then to something else called X.
|
|
33
|
+
Users must provide a Vss2X generator that can generate X if they get a VSS model as input.
|
|
34
|
+
"""
|
|
35
|
+
def __init__(self, generator: Vss2X, vspec2vss_config: Vspec2VssConfig):
|
|
36
|
+
|
|
37
|
+
self.generator = generator
|
|
38
|
+
self.vspec2vss_config = vspec2vss_config
|
|
39
|
+
|
|
40
|
+
def main(self, arguments):
|
|
41
|
+
initLogging()
|
|
42
|
+
parser = argparse.ArgumentParser(description="Convert vspec to other formats.")
|
|
43
|
+
|
|
44
|
+
parser.add_argument('--version', action='version', version=VERSION)
|
|
45
|
+
parser.add_argument('-I', '--include-dir', action='append', metavar='dir', type=str, default=[],
|
|
46
|
+
help='Add include directory to search for included vspec files.')
|
|
47
|
+
if self.vspec2vss_config.extended_attributes_supported:
|
|
48
|
+
parser.add_argument('-e', '--extended-attributes', type=str, default="",
|
|
49
|
+
help='Whitelisted extended attributes as comma separated list.')
|
|
50
|
+
parser.add_argument('-s', '--strict', action='store_true',
|
|
51
|
+
help='Use strict checking: Terminate when anything not covered or not recommended '
|
|
52
|
+
'by VSS language or extensions is found.')
|
|
53
|
+
parser.add_argument('--abort-on-unknown-attribute', action='store_true',
|
|
54
|
+
help="Terminate when an unknown attribute is found.")
|
|
55
|
+
parser.add_argument('--abort-on-name-style', action='store_true',
|
|
56
|
+
help="Terminate if name style does not follow VSS standard catalog naming convention.")
|
|
57
|
+
if self.vspec2vss_config.uuid_supported:
|
|
58
|
+
parser.add_argument('--uuid', action='store_true',
|
|
59
|
+
help='Include uuid in generated files. (Deprecated, will be removed in VSS-tools 6.0)')
|
|
60
|
+
if self.vspec2vss_config.expand_model and self.vspec2vss_config.no_expand_option_supported:
|
|
61
|
+
parser.add_argument('--no-expand', action='store_true',
|
|
62
|
+
help='Do not expand tree.')
|
|
63
|
+
parser.add_argument('-o', '--overlays', action='append', metavar='overlays', type=str, default=[],
|
|
64
|
+
help='Add overlay that will be layered on top of the VSS file in the order they appear.')
|
|
65
|
+
parser.add_argument('-q', '--quantity-file', action='append', metavar='quantity_file', type=str, default=[],
|
|
66
|
+
help='Quantity file to be used for generation. Argument -q may be used multiple times.')
|
|
67
|
+
parser.add_argument('-u', '--unit-file', action='append', metavar='unit_file', type=str, default=[],
|
|
68
|
+
help='Unit file to be used for generation. Argument -u may be used multiple times.')
|
|
69
|
+
parser.add_argument('vspec_file', metavar='<vspec_file>',
|
|
70
|
+
help='The vehicle specification file to convert.')
|
|
71
|
+
if self.vspec2vss_config.output_file_required:
|
|
72
|
+
parser.add_argument('output_file', metavar='<output_file>',
|
|
73
|
+
help='The file to write output to.')
|
|
74
|
+
|
|
75
|
+
if self.vspec2vss_config.type_tree_supported:
|
|
76
|
+
type_group = parser.add_argument_group('VSS Data Type Tree arguments',
|
|
77
|
+
'Arguments related to struct/type support')
|
|
78
|
+
|
|
79
|
+
type_group.add_argument('-vt', '--vspec-types-file', action='append', metavar='vspec_types_file', type=str,
|
|
80
|
+
default=[],
|
|
81
|
+
help='Data types file in vspec format.')
|
|
82
|
+
if self.vspec2vss_config.separate_output_type_file_supported:
|
|
83
|
+
# Note we might get some odd errors if using -ot in a tool not supporting it due to conflict with -o
|
|
84
|
+
type_group.add_argument('-ot', '--types-output-file', metavar='<types_output_file>',
|
|
85
|
+
help='Output file for writing data types from vspec file. ' +
|
|
86
|
+
'If not specified, a single file is used where applicable. ' +
|
|
87
|
+
'In case of JSON and YAML, the data is exported under a ' +
|
|
88
|
+
'special key - "ComplexDataTypes"')
|
|
89
|
+
|
|
90
|
+
self.generator.add_arguments(parser.add_argument_group(
|
|
91
|
+
"Exporter specific arguments", ""))
|
|
92
|
+
|
|
93
|
+
args = parser.parse_args(arguments)
|
|
94
|
+
|
|
95
|
+
logging.info("VSS-tools version %s", VERSION)
|
|
96
|
+
|
|
97
|
+
include_dirs = ["."]
|
|
98
|
+
include_dirs.extend(args.include_dir)
|
|
99
|
+
|
|
100
|
+
abort_on_unknown_attribute = False
|
|
101
|
+
abort_on_namestyle = False
|
|
102
|
+
|
|
103
|
+
if args.abort_on_unknown_attribute or args.strict:
|
|
104
|
+
abort_on_unknown_attribute = True
|
|
105
|
+
if args.abort_on_name_style or args.strict:
|
|
106
|
+
abort_on_namestyle = True
|
|
107
|
+
|
|
108
|
+
if self.vspec2vss_config.extended_attributes_supported and (len(args.extended_attributes) > 0):
|
|
109
|
+
known_extended_attributes_list = args.extended_attributes.split(",")
|
|
110
|
+
vspec.model.vsstree.VSSNode.whitelisted_extended_attributes = known_extended_attributes_list
|
|
111
|
+
logging.info(f"Known extended attributes: {', '.join(known_extended_attributes_list)}")
|
|
112
|
+
else:
|
|
113
|
+
known_extended_attributes_list = list()
|
|
114
|
+
|
|
115
|
+
self.vspec2vss_config.generate_uuid = self.vspec2vss_config.uuid_supported and args.uuid
|
|
116
|
+
|
|
117
|
+
# Follow up to https://github.com/COVESA/vehicle_signal_specification/pull/721
|
|
118
|
+
# Deprecate --uuid
|
|
119
|
+
if self.vspec2vss_config.generate_uuid:
|
|
120
|
+
logging.warning("The argument --uuid is deprecated and the uuid feature is planned "
|
|
121
|
+
"to be removed in VSS-tools 6.0")
|
|
122
|
+
logging.info("If you need static identifiers consider using the vspec2id tool")
|
|
123
|
+
|
|
124
|
+
self.vspec2vss_config.expand_model = (self.vspec2vss_config.expand_model and not
|
|
125
|
+
(self.vspec2vss_config.no_expand_option_supported and args.no_expand))
|
|
126
|
+
|
|
127
|
+
vspec.load_quantities(args.vspec_file, args.quantity_file)
|
|
128
|
+
vspec.load_units(args.vspec_file, args.unit_file)
|
|
129
|
+
|
|
130
|
+
# process data type tree
|
|
131
|
+
data_type_tree = None
|
|
132
|
+
if self.vspec2vss_config.type_tree_supported:
|
|
133
|
+
if self.vspec2vss_config.separate_output_type_file_supported:
|
|
134
|
+
if args.types_output_file is not None and not args.vspec_types_file:
|
|
135
|
+
parser.error("An output file for data types was provided. Please also provide "
|
|
136
|
+
"the input vspec file for data types")
|
|
137
|
+
if args.vspec_types_file:
|
|
138
|
+
data_type_tree = self.processDataTypeTree(
|
|
139
|
+
parser, args, include_dirs, abort_on_namestyle)
|
|
140
|
+
vspec.verify_mandatory_attributes(data_type_tree, abort_on_unknown_attribute)
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
logging.info(f"Loading vspec from {args.vspec_file}...")
|
|
144
|
+
tree = vspec.load_tree(
|
|
145
|
+
args.vspec_file, include_dirs, VSSTreeType.SIGNAL_TREE,
|
|
146
|
+
break_on_name_style_violation=abort_on_namestyle,
|
|
147
|
+
expand_inst=False, data_type_tree=data_type_tree)
|
|
148
|
+
|
|
149
|
+
for overlay in args.overlays:
|
|
150
|
+
logging.info(f"Applying VSS overlay from {overlay}...")
|
|
151
|
+
othertree = vspec.load_tree(overlay, include_dirs, VSSTreeType.SIGNAL_TREE,
|
|
152
|
+
break_on_name_style_violation=abort_on_namestyle, expand_inst=False,
|
|
153
|
+
data_type_tree=data_type_tree)
|
|
154
|
+
vspec.merge_tree(tree, othertree)
|
|
155
|
+
|
|
156
|
+
vspec.check_type_usage(tree, VSSTreeType.SIGNAL_TREE, data_type_tree)
|
|
157
|
+
if self.vspec2vss_config.expand_model:
|
|
158
|
+
vspec.expand_tree_instances(tree)
|
|
159
|
+
|
|
160
|
+
vspec.clean_metadata(tree)
|
|
161
|
+
vspec.verify_mandatory_attributes(tree, abort_on_unknown_attribute)
|
|
162
|
+
logging.info("Calling exporter...")
|
|
163
|
+
|
|
164
|
+
self.generator.generate(args, tree, self.vspec2vss_config, data_type_tree)
|
|
165
|
+
logging.info("All done.")
|
|
166
|
+
except vspec.VSpecError as e:
|
|
167
|
+
logging.error(f"Error: {e}")
|
|
168
|
+
sys.exit(255)
|
|
169
|
+
|
|
170
|
+
def processDataTypeTree(self, parser: argparse.ArgumentParser, args, include_dirs,
|
|
171
|
+
abort_on_namestyle: bool) -> VSSNode:
|
|
172
|
+
"""
|
|
173
|
+
Helper function to process command line arguments and invoke logic for processing data
|
|
174
|
+
type information provided in vspec format
|
|
175
|
+
"""
|
|
176
|
+
if self.vspec2vss_config.separate_output_type_file_supported and \
|
|
177
|
+
args.types_output_file is None:
|
|
178
|
+
logging.info("Sensors and custom data types will be consolidated into one file.")
|
|
179
|
+
|
|
180
|
+
first_tree = True
|
|
181
|
+
for type_file in args.vspec_types_file:
|
|
182
|
+
logging.info(f"Loading and processing struct/data type tree from {type_file}")
|
|
183
|
+
new_tree = vspec.load_tree(type_file, include_dirs, VSSTreeType.DATA_TYPE_TREE,
|
|
184
|
+
break_on_name_style_violation=abort_on_namestyle, expand_inst=False)
|
|
185
|
+
if first_tree:
|
|
186
|
+
tree = new_tree
|
|
187
|
+
first_tree = False
|
|
188
|
+
else:
|
|
189
|
+
vspec.merge_tree(tree, new_tree)
|
|
190
|
+
vspec.check_type_usage(tree, VSSTreeType.DATA_TYPE_TREE)
|
|
191
|
+
return tree
|
vspec/vss2x.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2023 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
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
import argparse
|
|
13
|
+
from typing import Optional
|
|
14
|
+
from vspec.model.vsstree import VSSNode
|
|
15
|
+
from vspec.vspec2vss_config import Vspec2VssConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Vss2X(ABC):
|
|
19
|
+
"""
|
|
20
|
+
Abstract class for something that takes a VSS model as input
|
|
21
|
+
(signal tree plus optionally a type tree)
|
|
22
|
+
and does "something". For now it is assumed that output is either files
|
|
23
|
+
or text output.
|
|
24
|
+
The generator may use both command line config as well as specific configs used for
|
|
25
|
+
creating the VSS model to control the generation.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
|
|
29
|
+
parser.description = "This generator does not support any additional arguments."
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def generate(self, config: argparse.Namespace, signal_root: VSSNode, vspec2vss_config: Vspec2VssConfig,
|
|
33
|
+
data_type_root: Optional[VSSNode] = None) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Previously called export, but changing to a more generic name.
|
|
36
|
+
Must be defined by the tool.
|
|
37
|
+
"""
|
|
38
|
+
pass
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Copyright (c) 2022 Contributors to COVESA
|
|
2
|
+
#
|
|
3
|
+
# This program and the accompanying materials are made available under the
|
|
4
|
+
# terms of the Mozilla Public License 2.0 which is available at
|
|
5
|
+
# https://www.mozilla.org/en-US/MPL/2.0/
|
|
6
|
+
#
|
|
7
|
+
# SPDX-License-Identifier: MPL-2.0
|