From 02f19de252de3399f5892fbff60ea97e57ea3e9b Mon Sep 17 00:00:00 2001 From: Dharini Dutia Date: Thu, 29 Jun 2023 17:34:18 +0000 Subject: [PATCH] merging embedSdf.py from sdf13 Signed-off-by: Dharini Dutia --- sdf/embedSdf.py | 168 +++++++++++++++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 58 deletions(-) diff --git a/sdf/embedSdf.py b/sdf/embedSdf.py index b89607fa6..c4bc0a1ab 100644 --- a/sdf/embedSdf.py +++ b/sdf/embedSdf.py @@ -1,29 +1,49 @@ #!/usr/bin/env python3 +""" +Script for generating a C++ file that contains the content from all SDF files +""" + +from typing import List, Optional + +import argparse import inspect -from pathlib import Path, PurePosixPath +import sys +from pathlib import Path -""""Script for generating a C++ file that contains the content from all SDF files""" # The list of supported SDF specification versions. This will let us drop # versions without removing the directories. -SUPPORTED_SDF_VERSIONS = ['1.10', '1.9', '1.8', '1.7', '1.6', '1.5', '1.4', '1.3', '1.2'] +SUPPORTED_SDF_VERSIONS = [ + "1.10", + "1.9", + "1.8", + "1.7", + "1.6", + "1.5", + "1.4", + "1.3", + "1.2", +] # The list of supported SDF conversions. This list includes versions that # a user can convert an existing SDF version to. -SUPPORTED_SDF_CONVERSIONS = ['1.10', '1.9', '1.8', '1.7', '1.6', '1.5', '1.4', '1.3'] +SUPPORTED_SDF_CONVERSIONS = ["1.10", "1.9", "1.8", "1.7", "1.6", "1.5", "1.4", "1.3"] # whitespace indentation for C++ code -INDENTATION = ' ' +INDENTATION = " " + # newline character -NEWLINE = '\n' +NEWLINE = "\n" + def get_copyright_notice() -> str: """ - Provides the copyrigt notice for the C++ file + Provides the copyright notice for the C++ file :returns: copyright notice """ - res = inspect.cleandoc(""" + res = inspect.cleandoc( + """ /* * Copyright 2022 Open Source Robotics Foundation * @@ -40,8 +60,9 @@ def get_copyright_notice() -> str: * limitations under the License. * */ - """) - return res + 2*NEWLINE + """ + ) + return res + 2 * NEWLINE def get_file_header_prolog() -> str: @@ -50,7 +71,8 @@ def get_file_header_prolog() -> str: :returns: prolog of the C++ file """ - res = inspect.cleandoc(""" + res = inspect.cleandoc( + """ #include "EmbeddedSdf.hh" namespace sdf @@ -61,60 +83,39 @@ def get_file_header_prolog() -> str: const std::map &GetEmbeddedSdf() { static const std::map result { - """) + """ + ) return res + NEWLINE def embed_sdf_content(arg_path: str, arg_file_content: str) -> str: """ - Generates a string pair with the folder and filename as well as the content of the file + Generates a string pair with the folder and filename + as well as the content of the file :param arg_path: Foldername and filename of the SDF :param arg_file_content: Content of the provided file :returns: raw string literal mapping pair for the std::map """ res = [] - res.append('// NOLINT') - res.append('{') + res.append("// NOLINT") + res.append("{") res.append(f'"{arg_path}",') res.append('R"__sdf_literal__(') - res.append(f'{arg_file_content}') + res.append(f"{arg_file_content}") res.append(')__sdf_literal__"') - res.append('},') - res.append('') + res.append("}") return NEWLINE.join(res) -def get_map_content(arg_pathlist: Path) -> str: - """ - Generates a string pair with the folder and filename as well as the content - of the file in ascending order - - :param arg_pathlist: Foldername and all filenames inside it - :returns: mapping pairs for the std::map - """ - map_str = '' - files = [] - for path in arg_pathlist: - # dir separator is hardcoded to '/' in C++ mapping - posix_path = PurePosixPath(path) - files.append(str(posix_path)) - # get ascending order - files.sort() - for file in files: - with Path(file).open() as f: - content = f.read() - map_str += embed_sdf_content(file, content) - return map_str - - def get_file_header_epilog() -> str: """ Provides the return statement and the closing brackets of the C++ file :returns: epilog of the C++ file """ - res = inspect.cleandoc(""" + res = inspect.cleandoc( + """ }; return result; @@ -123,29 +124,80 @@ def get_file_header_epilog() -> str: } } // namespace sdf - """) + """ + ) return NEWLINE + res -if __name__ == "__main__": - copyright = get_copyright_notice() +def write_output(file_content: str, output_filename: str) -> None: + """ + Print the content of the EmbeddedSdf.cc to a file + """ + copyright_notice = get_copyright_notice() prolog = get_file_header_prolog() + epilog = get_file_header_epilog() + output_content = copyright_notice + prolog + file_content + epilog - map_str = "" - for sdf_version in SUPPORTED_SDF_VERSIONS: - pathlist = Path(sdf_version).glob('*.sdf') - map_str += get_map_content(pathlist) + with open(output_filename, "w", encoding="utf8") as output_file: + output_file.write(output_content) - for sdf_conversion in SUPPORTED_SDF_CONVERSIONS: - pathlist = Path(sdf_conversion).glob('*.convert') - map_str += get_map_content(pathlist) - # remove the last comma - map_str = map_str[:-2] +def collect_file_locations() -> List[Path]: + paths: List[Path] = [] - epilog = get_file_header_epilog() + for sdf_version in SUPPORTED_SDF_VERSIONS: + paths.extend(Path(sdf_version).glob("*.sdf")) + for sdf_conversion in SUPPORTED_SDF_CONVERSIONS: + paths.extend(Path(sdf_conversion).glob("*.convert")) + return paths + + +def generate_map_content(paths: List[Path], relative_to: Optional[str] = None) -> str: + ''' + Generate the EmbeddedSdf.cc content + ''' + content = [] + for path in paths: + with open(path, "r", encoding="utf8") as input_sdf: + file_content = input_sdf.read() + + # Strip relative path if requested + if relative_to is not None: + path = path.relative_to(relative_to) + content.append(embed_sdf_content(str(path), file_content)) + return ",".join(content) + + +def main(args=None) -> int: + ''' + Main entrypoint + ''' + if args is None: + args = sys.argv[1:] + + parser = argparse.ArgumentParser() + + parser.add_argument( + "--sdf-root", + default=None, + help="Directory containing sdf description files for each version", + ) + parser.add_argument( + "--input-files", nargs="*", help="List of input files to be embedded" + ) + parser.add_argument( + "--output-file", help="File to output embeddedsdf.cc content to" + ) + + args = parser.parse_args(args) + if not args.input_files or len(args.input_files) == 0: + paths = collect_file_locations() + else: + paths = [Path(f) for f in args.input_files] + content = generate_map_content(paths, args.sdf_root) + write_output(content, args.output_file) + return 0 - output = copyright + prolog + map_str + epilog - # output to stdin so that CMake can read it and create the appropriate file - print(output) +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file