diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/config.py b/src/vss_tools/vspec/vssexporters/vss2samm/config.py new file mode 100644 index 00000000..91078e8b --- /dev/null +++ b/src/vss_tools/vspec/vssexporters/vss2samm/config.py @@ -0,0 +1,26 @@ +# Copyright (c) 2024 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 + +# General CONFIG variables +# Custom string, which we use to escape " and ' characters in VSS node description/comments +# Used in file_helper.write_graph_to_file to properly escape characters in filedata, before to write it to a file. + + +class Config: + OUTPUT_NAMESPACE: str | None = None + VSPEC_VERSION: str | None = None + SPLIT_DEPTH: int | None = None + SAMM_TYPE = "samm" + SAMM_VERSION = "2.1.0" + CUSTOM_ESCAPE_CHAR = "#V2E-ESC-CHAR#" + + +def init(output_namespace: str, vspec_version: str, split_depth: int): + Config.OUTPUT_NAMESPACE = output_namespace + Config.VSPEC_VERSION = vspec_version + Config.SPLIT_DEPTH = split_depth if (type(split_depth) is int and split_depth > 0) else 1 diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/config/config.py b/src/vss_tools/vspec/vssexporters/vss2samm/config/config.py deleted file mode 100644 index 22cd8065..00000000 --- a/src/vss_tools/vspec/vssexporters/vss2samm/config/config.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2024 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 - -# General CONFIG variables -SAMM_TYPE = "samm" -SAMM_VERSION = "2.1.0" -# Custom string, which we use to escape " and ' characters in VSS node description/comments -# Used in file_helper.write_graph_to_file to properly escape characters in filedata, before to write it to a file. -CUSTOM_ESCAPE_CHAR = "#V2E-ESC-CHAR#" - -# CONFIG Variable defined at runtime as per user input and in available init function -OUTPUT_NAMESPACE = None -VSPEC_VERSION = None -SPLIT_DEPTH = None - - -def init(output_namespace: str, vspec_version: str, split_depth: int): - # Set user defined or OUTPUT_NAMESPACE - global OUTPUT_NAMESPACE - OUTPUT_NAMESPACE = output_namespace - - # Set user defined or OUTPUT_NAMESPACE - global VSPEC_VERSION - VSPEC_VERSION = vspec_version - - # Make sure that split_depth is in correct type and value, else set it to DEFAULT: 1 - global SPLIT_DEPTH - SPLIT_DEPTH = split_depth if (type(split_depth) is int and split_depth > 0) else 1 diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/file_helper.py b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/file_helper.py index 53daa48c..181461fc 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/file_helper.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/file_helper.py @@ -11,7 +11,7 @@ from rdflib import Graph from vss_tools import log -from ..config import config as cfg +from ..config import Config # Write RDF Graph data to specified file @@ -36,7 +36,7 @@ def write_graph_to_file(path_to_file: Path, file_name: str, graph: Graph): # Cleanup some CUSTOM ESCAPED, by this script characters. # Usually double and single quotes in node.description or node.comment field - filedata = filedata.replace(cfg.CUSTOM_ESCAPE_CHAR, "\\") + filedata = filedata.replace(Config.CUSTOM_ESCAPE_CHAR, "\\") # Cleanup xsd:anyURI with xsd:double filedata = filedata.replace("xsd:anyURI", "xsd:double") diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/namespaces.py b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/namespaces.py index 75bf46c5..5ce54de4 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/namespaces.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/namespaces.py @@ -7,9 +7,8 @@ # SPDX-License-Identifier: MPL-2.0 from rdflib import URIRef -from vss_tools import log -from ..config import config as cfg +from ..config import Config def get_vspec_uri(node_name: str): @@ -21,22 +20,20 @@ def get_node_name_from_vspec_uri(node_uri: URIRef): def get_unit_uri(unit_name: str): - return URIRef(f"{samm_base_namespace}:unit:{cfg.SAMM_VERSION}#{unit_name}") + return URIRef(f"{samm_base_namespace}:unit:{Config.SAMM_VERSION}#{unit_name}") -log.debug("VSS to SAMM CONFIG:\n -- SAMM_TYPE : %s\n -- SAMM_VERSION: %s\n", cfg.SAMM_TYPE, cfg.SAMM_VERSION) - # NOTE: samm_base_namespace is more for the ESMF core libraries samm_prefix = "urn:samm" samm_base_namespace = f"{samm_prefix}:org.eclipse.esmf.samm" Namespaces = { - "samm": f"{samm_base_namespace}:meta-model:{cfg.SAMM_VERSION}#", - "samm-c": f"{samm_base_namespace}:characteristic:{cfg.SAMM_VERSION}#", - "samm-e": f"{samm_base_namespace}:entity:{cfg.SAMM_VERSION}#", - "unit": f"{samm_base_namespace}:unit:{cfg.SAMM_VERSION}#", + "samm": f"{samm_base_namespace}:meta-model:{Config.SAMM_VERSION}#", + "samm-c": f"{samm_base_namespace}:characteristic:{Config.SAMM_VERSION}#", + "samm-e": f"{samm_base_namespace}:entity:{Config.SAMM_VERSION}#", + "unit": f"{samm_base_namespace}:unit:{Config.SAMM_VERSION}#", } # Below formatted namespace should look like: urn:samm:com.covesa.vss.spec:5.0.0# # and is used for the ":" bindings of the converted to TTLs, VSS Aspect models # that will refer to the user specified output_namespace -samm_output_namespace = f"{samm_prefix}:{cfg.OUTPUT_NAMESPACE}:{cfg.VSPEC_VERSION}#" +samm_output_namespace = f"{samm_prefix}:{Config.OUTPUT_NAMESPACE}:{Config.VSPEC_VERSION}#" diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/samm_concepts.py b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/samm_concepts.py index 9a8a13d6..f3eaa43c 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/samm_concepts.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/samm_concepts.py @@ -11,7 +11,7 @@ from rdflib import URIRef -from ..config import config as cfg +from ..config import Config from . import string_helper as str_helper from .namespaces import samm_base_namespace, samm_output_namespace @@ -63,7 +63,7 @@ class SammConcepts(Enum): PROPERTY = "Property" def __init__(self, vss_name): - self.ns = f"{samm_base_namespace}:meta-model:{cfg.SAMM_VERSION}#" + self.ns = f"{samm_base_namespace}:meta-model:{Config.SAMM_VERSION}#" self.vsso_name = vss_name @property @@ -100,7 +100,7 @@ class SammCConcepts(Enum): VALUES = "values" def __init__(self, vss_name): - self.ns = f"{samm_base_namespace}:characteristic:{cfg.SAMM_VERSION}#" + self.ns = f"{samm_base_namespace}:characteristic:{Config.SAMM_VERSION}#" self.vsso_name = vss_name @property diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_builder_helper.py b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_builder_helper.py index 43aed4dd..91b3dcb5 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_builder_helper.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_builder_helper.py @@ -9,7 +9,8 @@ from typing import Sequence from rdflib import Graph, Literal, URIRef -from rdflib.namespace import RDF, XSD +from rdflib.namespace._RDF import RDF +from rdflib.namespace._XSD import XSD from vss_tools import log from vss_tools.vspec.tree import VSSNode diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_helper.py b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_helper.py index fcb44a49..d4fe949b 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_helper.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/ttl_helper.py @@ -9,12 +9,12 @@ from pathlib import Path from rdflib import Graph, URIRef -from rdflib.namespace import RDF +from rdflib.namespace._RDF import RDF from vss_tools import log from vss_tools.vspec.model import NodeType from vss_tools.vspec.tree import VSSNode -from ..config import config as cfg +from ..config import Config from . import ttl_builder_helper as ttl_builder from . import vss_helper as vss_helper from .file_helper import write_graph_to_file @@ -148,7 +148,7 @@ def handle_branch_node( for child_node in vss_node.children: child_node_uri = None - if split_vss and child_node.depth <= cfg.SPLIT_DEPTH and child_node.data.type is NodeType.BRANCH: + if split_vss and child_node.depth <= Config.SPLIT_DEPTH and child_node.data.type is NodeType.BRANCH: # Build VSS node into separate Aspect model # when --split option is provided # and depth of current VSSNode is within specified config SPLIT_DEPT level, diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/vss_helper.py b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/vss_helper.py index 1f2a63d6..39913b49 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/helpers/vss_helper.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/helpers/vss_helper.py @@ -16,7 +16,7 @@ from vss_tools.vspec.model import NodeType from vss_tools.vspec.tree import VSSNode -from ..config import config as cfg +from ..config import Config from .data_types_and_units import DataTypes, DataUnits from .samm_concepts import SammCConcepts, SammConcepts from .string_helper import str_to_lc_first_camel_case, str_to_uc_first_camel_case @@ -329,7 +329,7 @@ def get_node_description(vss_node: VSSNode) -> str: ): if '"' in vss_node.data.description: # Escape double quotes within vss_node.description - vss_node.data.description = vss_node.data.description.replace('"', f'{cfg.CUSTOM_ESCAPE_CHAR}"') + vss_node.data.description = vss_node.data.description.replace('"', f'{Config.CUSTOM_ESCAPE_CHAR}"') # Set 3 spaces spacer, so to align 'VSS path:' with 'Description:' spacer = " " @@ -339,7 +339,7 @@ def get_node_description(vss_node: VSSNode) -> str: # Add the vss_node.comment to its description if hasattr(vss_node.data, "comment") and vss_node.data.comment and len(vss_node.data.comment.strip()) > 0: if '"' in vss_node.data.comment: - vss_node.data.comment = vss_node.data.comment.replace('"', f'{cfg.CUSTOM_ESCAPE_CHAR}"') + vss_node.data.comment = vss_node.data.comment.replace('"', f'{Config.CUSTOM_ESCAPE_CHAR}"') # Use the 3 empty spaces spacer, when there is description, # otherwise set it to align 'VSS path:' with 'Comment:' diff --git a/src/vss_tools/vspec/vssexporters/vss2samm/vss2samm.py b/src/vss_tools/vspec/vssexporters/vss2samm/vss2samm.py index 288787d0..597eb81a 100644 --- a/src/vss_tools/vspec/vssexporters/vss2samm/vss2samm.py +++ b/src/vss_tools/vspec/vssexporters/vss2samm/vss2samm.py @@ -10,35 +10,17 @@ # Convert all vspec input files to a ESMF - Aspect Model Editor (SAMM) - ttl formatted file(s). # - -import importlib from pathlib import Path import rich_click as click import vss_tools.vspec.cli_options as clo +import vss_tools.vspec.vssexporters.vss2samm.helpers.ttl_helper as ttl_helper +import vss_tools.vspec.vssexporters.vss2samm.helpers.vss_helper as vss_helper from vss_tools import log from vss_tools.vspec.main import get_trees from vss_tools.vspec.tree import VSSNode -from .config import config as cfg - -VSSConcepts = None -vss_helper = None -ttl_helper = None - - -def __setup_environment(output_namespace, vspec_version, split_depth: int) -> None: - # Initialize config before to load other helpers / libraries, based on defined by user input, config data - cfg.init(output_namespace, vspec_version, split_depth) - - global VSSConcepts - VSSConcepts = importlib.import_module("vss_tools.vspec.vssexporters.vss2samm.helpers.samm_concepts").VSSConcepts - - global vss_helper - vss_helper = importlib.import_module("vss_tools.vspec.vssexporters.vss2samm.helpers.vss_helper") - - global ttl_helper - ttl_helper = importlib.import_module("vss_tools.vspec.vssexporters.vss2samm.helpers.ttl_helper") +from . import config as cfg # TODO: Currently this is a workaround to read the Vehicle.VersionVSS, which is provided from COVESA/VSS @@ -181,14 +163,13 @@ def cli( log.info("Loading VSS Tree...\n") - tree, datatype_tree = get_trees( + tree, _ = get_trees( vspec, include_dirs, aborts, strict, extended_attributes, uuid, quantities, units, types, overlays, expand ) # Get the VSS version from the vss_tree::VersionVSS vss_version = __get_version_vss(tree) - - __setup_environment(output_namespace, vss_version, split_depth) + cfg.init(output_namespace, vss_version, split_depth) included_signals = None included_branches = None @@ -207,11 +188,11 @@ def cli( "Update output: '%s' with ESMF namespace: '%s' and VSS Version: '%s'.\n", target_folder, output_namespace, - cfg.VSPEC_VERSION, + cfg.Config.VSPEC_VERSION, ) # Make sure that target folder gets reflected with respect to current output_namespace and VSPEC_VERSION - target_folder = Path(f"{target_folder}/{output_namespace}/{cfg.VSPEC_VERSION}") + target_folder = Path(f"{target_folder}/{output_namespace}/{cfg.Config.VSPEC_VERSION}") log.info("Generating SAMM output...\n")