Skip to content

Commit

Permalink
merging embedSdf.py from sdf13
Browse files Browse the repository at this point in the history
Signed-off-by: Dharini Dutia <dharini@openrobotics.org>
  • Loading branch information
quarkytale committed Jun 29, 2023
1 parent 5478312 commit 02f19de
Showing 1 changed file with 110 additions and 58 deletions.
168 changes: 110 additions & 58 deletions sdf/embedSdf.py
Original file line number Diff line number Diff line change
@@ -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
*
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -61,60 +83,39 @@ def get_file_header_prolog() -> str:
const std::map<std::string, std::string> &GetEmbeddedSdf()
{
static const std::map<std::string, std::string> 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;
Expand All @@ -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())

0 comments on commit 02f19de

Please sign in to comment.