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
vspec/loggingconfig.py ADDED
@@ -0,0 +1,22 @@
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
+ #
12
+ # Convert vspec files to various other formats
13
+ #
14
+
15
+ import logging
16
+
17
+
18
+ def initLogging():
19
+ """
20
+ Initialize logging
21
+ """
22
+ logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
@@ -0,0 +1,7 @@
1
+ # Copyright (c) 2021 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
@@ -0,0 +1,307 @@
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
+ #
12
+ # Constant Types and Mappings
13
+ #
14
+ # noinspection PyPackageRequirements
15
+ from __future__ import annotations
16
+ import logging
17
+ import re
18
+ import sys
19
+ from collections import abc
20
+ from collections.abc import Sequence
21
+ from enum import Enum, EnumMeta
22
+ from typing import TextIO, TypeVar
23
+
24
+ import yaml
25
+
26
+ NON_ALPHANUMERIC_WORD = re.compile("[^A-Za-z0-9]+")
27
+
28
+ T = TypeVar("T")
29
+
30
+
31
+ class VSSUnit(str):
32
+ """String subclass for storing unit information."""
33
+
34
+ id: str # Typically abbreviation like "V"
35
+ unit: str | None = None # Typically full name like "Volt"
36
+ definition: str | None = None
37
+ quantity: str | None = None # Typically quantity, like "Voltage"
38
+ allowed_datatypes: list[str] | None = None # Typically quantity, like "Voltage"
39
+
40
+ def __new__(
41
+ cls,
42
+ id: str,
43
+ unit: str | None = None,
44
+ definition: str | None = None,
45
+ quantity: str | None = None,
46
+ allowed_datatypes: list[str] | None = None,
47
+ ) -> VSSUnit:
48
+ self = super().__new__(cls, id)
49
+ self.id = id
50
+ self.unit = unit
51
+ self.definition = definition
52
+ self.quantity = quantity
53
+ self.allowed_datatypes = allowed_datatypes
54
+ return self
55
+
56
+ @property
57
+ def value(self):
58
+ return self
59
+
60
+
61
+ class VSSQuantity(str):
62
+ """String subclass for storing quantity information."""
63
+
64
+ id: str # Identifier preferably taken from a standard, like ISO 80000
65
+ definition: str # Explanation of quantity, for example reference to standard
66
+ remark: str | None = None # remark as defined in for example ISO 80000
67
+ comment: str | None = None
68
+
69
+ def __new__(
70
+ cls,
71
+ id: str,
72
+ definition: str,
73
+ remark: str | None = None,
74
+ comment: str | None = None,
75
+ ) -> VSSQuantity:
76
+ self = super().__new__(cls, id)
77
+ self.id = id
78
+ self.definition = definition
79
+ self.remark = remark
80
+ self.comment = comment
81
+ return self
82
+
83
+ @property
84
+ def value(self):
85
+ return self
86
+
87
+
88
+ class EnumMetaWithReverseLookup(EnumMeta):
89
+ """This class extends EnumMeta and adds:
90
+ - from_str(str): reverse lookup
91
+ - values(): sequence of values
92
+ """
93
+
94
+ def __new__(typ, *args, **kwargs):
95
+ cls = super().__new__(typ, *args, **kwargs)
96
+ if not hasattr(cls, "__reverse_lookup__"):
97
+ cls.__reverse_lookup__ = {v.value: v for v in cls.__members__.values()}
98
+ if not hasattr(cls, "__values__"):
99
+ cls.__values__ = tuple(v.value for v in cls.__members__.values())
100
+ return cls
101
+
102
+ def from_str(cls: type[T], value: str) -> T:
103
+ return cls.__reverse_lookup__[value] # type: ignore[attr-defined]
104
+
105
+ def values(cls: type[T]) -> Sequence[str]:
106
+ return cls.__values__ # type: ignore[attr-defined]
107
+
108
+
109
+ class VSSType(Enum, metaclass=EnumMetaWithReverseLookup):
110
+ BRANCH = "branch"
111
+ ATTRIBUTE = "attribute"
112
+ SENSOR = "sensor"
113
+ ACTUATOR = "actuator"
114
+ STRUCT = "struct"
115
+ PROPERTY = "property"
116
+
117
+
118
+ class VSSDataType(Enum, metaclass=EnumMetaWithReverseLookup):
119
+ INT8 = "int8"
120
+ UINT8 = "uint8"
121
+ INT16 = "int16"
122
+ UINT16 = "uint16"
123
+ INT32 = "int32"
124
+ UINT32 = "uint32"
125
+ INT64 = "int64"
126
+ UINT64 = "uint64"
127
+ BOOLEAN = "boolean"
128
+ FLOAT = "float"
129
+ DOUBLE = "double"
130
+ STRING = "string"
131
+ INT8_ARRAY = "int8[]"
132
+ UINT8_ARRAY = "uint8[]"
133
+ INT16_ARRAY = "int16[]"
134
+ UINT16_ARRAY = "uint16[]"
135
+ INT32_ARRAY = "int32[]"
136
+ UINT32_ARRAY = "uint32[]"
137
+ INT64_ARRAY = "int64[]"
138
+ UINT64_ARRAY = "uint64[]"
139
+ BOOLEAN_ARRAY = "boolean[]"
140
+ FLOAT_ARRAY = "float[]"
141
+ DOUBLE_ARRAY = "double[]"
142
+ STRING_ARRAY = "string[]"
143
+
144
+ @classmethod
145
+ def is_numeric(cls, datatype):
146
+ """
147
+ Return true if this datatype accepts numerical values
148
+ """
149
+ if datatype in [
150
+ VSSDataType.STRING,
151
+ VSSDataType.STRING_ARRAY,
152
+ VSSDataType.BOOLEAN,
153
+ VSSDataType.BOOLEAN_ARRAY,
154
+ ]:
155
+ return False
156
+ return True
157
+
158
+
159
+ class VSSUnitCollection:
160
+ units: dict[str, VSSUnit] = dict()
161
+
162
+ @staticmethod
163
+ def get_config_dict(yaml_file: TextIO, key: str) -> dict[str, dict[str, str]]:
164
+ yaml_config = yaml.safe_load(yaml_file)
165
+ if (len(yaml_config) == 1) and (key in yaml_config):
166
+ # Old style unit file
167
+ configs = yaml_config.get(key, {})
168
+ else:
169
+ # New style unit file
170
+ configs = yaml_config
171
+ return configs
172
+
173
+ @classmethod
174
+ def reset_units(cls):
175
+ cls.units = dict()
176
+
177
+ @classmethod
178
+ def load_config_file(cls, config_file: str) -> int:
179
+ added_configs = 0
180
+ with open(config_file) as my_yaml_file:
181
+ my_units = cls.get_config_dict(my_yaml_file, "units")
182
+ added_configs = len(my_units)
183
+ for k, v in my_units.items():
184
+ unit = k
185
+ if "unit" in v:
186
+ unit = v["unit"]
187
+ elif "label" in v:
188
+ # Old syntax
189
+ unit = v["label"]
190
+ definition = None
191
+ if "definition" in v:
192
+ definition = v["definition"]
193
+ elif "description" in v:
194
+ # Old syntax
195
+ definition = v["description"]
196
+
197
+ quantity = None
198
+ if "quantity" in v:
199
+ quantity = v["quantity"]
200
+ elif "domain" in v:
201
+ # Old syntax
202
+ quantity = v["domain"]
203
+ else:
204
+ logging.error("No quantity (domain) found for unit %s", k)
205
+ sys.exit(-1)
206
+
207
+ if (VSSQuantityCollection.nbr_quantities() > 0) and (
208
+ VSSQuantityCollection.get_quantity(quantity) is None
209
+ ):
210
+ # Only give info on first occurance and only if quantities exist at all
211
+ logging.info(
212
+ "Quantity %s used by unit %s has not been defined", quantity, k
213
+ )
214
+ VSSQuantityCollection.add_quantity(quantity)
215
+
216
+ allowed_datatypes = None
217
+
218
+ if "allowed_datatypes" in v:
219
+ allowed_datatypes = []
220
+ for datatype in v["allowed_datatypes"]:
221
+ allowed_datatypes.append(datatype)
222
+ if datatype == "numeric":
223
+ # Symbolic type for all numeric types
224
+ continue
225
+ try:
226
+ VSSDataType.from_str(datatype)
227
+ except KeyError:
228
+ logging.error(
229
+ "Unknown datatype %s in unit definition", datatype
230
+ )
231
+ sys.exit(-1)
232
+
233
+ unit_node = VSSUnit(k, unit, definition, quantity, allowed_datatypes)
234
+ if k in cls.units:
235
+ logging.warning("Redefinition of unit %s", k)
236
+ cls.units[k] = unit_node
237
+ return added_configs
238
+
239
+ @classmethod
240
+ def get_unit(cls, id: str) -> VSSUnit | None:
241
+ if id in cls.units:
242
+ return cls.units[id]
243
+ else:
244
+ return None
245
+
246
+
247
+ class VSSQuantityCollection:
248
+ quantities: dict[str, VSSQuantity] = dict()
249
+
250
+ @classmethod
251
+ def reset_quantities(cls):
252
+ cls.quantities = dict()
253
+
254
+ @classmethod
255
+ def load_config_file(cls, config_file: str) -> int:
256
+ added_quantities = 0
257
+ with open(config_file) as my_yaml_file:
258
+ my_quantities = yaml.safe_load(my_yaml_file)
259
+ added_quantities = len(my_quantities)
260
+ for k, v in my_quantities.items():
261
+ if isinstance(v, abc.Mapping) and "definition" in v:
262
+ definition = v["definition"]
263
+ else:
264
+ logging.error("No definition found for quantity %s", k)
265
+ sys.exit(-1)
266
+ remark = None
267
+ if "remark" in v:
268
+ remark = v["remark"]
269
+ comment = None
270
+ if "comment" in v:
271
+ comment = v["comment"]
272
+
273
+ quantity_node = VSSQuantity(k, definition, remark, comment)
274
+ if k in cls.quantities:
275
+ logging.warning("Redefinition of quantity %s", k)
276
+ cls.quantities[k] = quantity_node
277
+ return added_quantities
278
+
279
+ @classmethod
280
+ def get_quantity(cls, id: str) -> VSSQuantity | None:
281
+ if id in cls.quantities:
282
+ return cls.quantities[id]
283
+ else:
284
+ return None
285
+
286
+ @classmethod
287
+ def nbr_quantities(cls) -> int:
288
+ return len(cls.quantities)
289
+
290
+ @classmethod
291
+ def add_quantity(cls, id: str) -> None:
292
+ if id not in cls.quantities:
293
+ quantity_node = VSSQuantity(id, "Automatically generated quantity")
294
+ cls.quantities[id] = quantity_node
295
+
296
+
297
+ class VSSTreeType(Enum, metaclass=EnumMetaWithReverseLookup):
298
+ SIGNAL_TREE = "signal_tree"
299
+ DATA_TYPE_TREE = "data_type_tree"
300
+
301
+ def available_types(self):
302
+ if self.value == "signal_tree":
303
+ available_types = {"branch", "sensor", "actuator", "attribute"}
304
+ else:
305
+ available_types = {"branch", "struct", "property"}
306
+
307
+ return available_types
@@ -0,0 +1,29 @@
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 NameStyleValidationException(Exception):
12
+ def __init__(self, message):
13
+
14
+ # Call the base class constructor with the parameters it needs
15
+ super().__init__(message)
16
+
17
+
18
+ class ImpossibleMergeException(Exception):
19
+ def __init__(self, message):
20
+
21
+ # Call the base class constructor with the parameters it needs
22
+ super().__init__(message)
23
+
24
+
25
+ class IncompleteElementException(Exception):
26
+ def __init__(self, message):
27
+
28
+ # Call the base class constructor with the parameters it needs
29
+ super().__init__(message)