From 1963d0814ffa3464f3536da2aaa469f096770073 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 14:41:04 +0000 Subject: [PATCH 1/7] #4 Rename generated files for consistency --- cppwg/utils/constants.py | 2 +- cppwg/writers/module_writer.py | 6 ++++-- examples/shapes/wrapper/geometry/Point_2.cppwg.cpp | 2 +- examples/shapes/wrapper/geometry/Point_3.cppwg.cpp | 2 +- ...{geometry.main.cpp => _pyshapes_geometry.main.cppwg.cpp} | 2 +- ...h_funcs.main.cpp => _pyshapes_math_funcs.main.cppwg.cpp} | 2 +- examples/shapes/wrapper/mesh/AbstractMesh_2_2.cppwg.cpp | 2 +- examples/shapes/wrapper/mesh/AbstractMesh_3_3.cppwg.cpp | 2 +- examples/shapes/wrapper/mesh/ConcreteMesh_2.cppwg.cpp | 2 +- examples/shapes/wrapper/mesh/ConcreteMesh_3.cppwg.cpp | 2 +- .../mesh/{mesh.main.cpp => _pyshapes_mesh.main.cppwg.cpp} | 2 +- examples/shapes/wrapper/primitives/Cuboid.cppwg.cpp | 2 +- examples/shapes/wrapper/primitives/Rectangle.cppwg.cpp | 2 +- examples/shapes/wrapper/primitives/Shape_2.cppwg.cpp | 2 +- examples/shapes/wrapper/primitives/Shape_3.cppwg.cpp | 2 +- ...mitives.main.cpp => _pyshapes_primitives.main.cppwg.cpp} | 2 +- ...r_collection.hpp => wrapper_header_collection.cppwg.hpp} | 0 17 files changed, 19 insertions(+), 17 deletions(-) rename examples/shapes/wrapper/geometry/{geometry.main.cpp => _pyshapes_geometry.main.cppwg.cpp} (86%) rename examples/shapes/wrapper/math_funcs/{math_funcs.main.cpp => _pyshapes_math_funcs.main.cppwg.cpp} (84%) rename examples/shapes/wrapper/mesh/{mesh.main.cpp => _pyshapes_mesh.main.cppwg.cpp} (91%) rename examples/shapes/wrapper/primitives/{primitives.main.cpp => _pyshapes_primitives.main.cppwg.cpp} (90%) rename examples/shapes/wrapper/{wrapper_header_collection.hpp => wrapper_header_collection.cppwg.hpp} (100%) diff --git a/cppwg/utils/constants.py b/cppwg/utils/constants.py index 32799c5..0c729bb 100644 --- a/cppwg/utils/constants.py +++ b/cppwg/utils/constants.py @@ -4,7 +4,7 @@ CPPWG_ALL_STRING = "CPPWG_ALL" CPPWG_EXT = "cppwg" -CPPWG_HEADER_COLLECTION_FILENAME = "wrapper_header_collection.hpp" +CPPWG_HEADER_COLLECTION_FILENAME = f"wrapper_header_collection.{CPPWG_EXT}.hpp" CPPWG_TRUE_STRINGS = ["ON", "YES", "Y", "TRUE", "T"] CPPWG_FALSE_STRINGS = ["OFF", "NO", "N", "FALSE", "F"] diff --git a/cppwg/writers/module_writer.py b/cppwg/writers/module_writer.py index 793620c..2bba96a 100644 --- a/cppwg/writers/module_writer.py +++ b/cppwg/writers/module_writer.py @@ -96,7 +96,7 @@ def write_module_wrapper(self) -> None: # Format module name as _packagename_modulename full_module_name = ( - "_" + self.module_info.package_info.name + "_" + self.module_info.name + f"_{self.module_info.package_info.name}_{self.module_info.name}" ) # Create the pybind11 module @@ -132,7 +132,9 @@ def write_module_wrapper(self) -> None: if not os.path.isdir(module_dir): os.makedirs(module_dir) - module_cpp_file = os.path.join(module_dir, self.module_info.name + ".main.cpp") + module_cpp_file = os.path.join( + module_dir, f"{full_module_name}.main.{CPPWG_EXT}.cpp" + ) with open(module_cpp_file, "w") as out_file: out_file.write(cpp_string) diff --git a/examples/shapes/wrapper/geometry/Point_2.cppwg.cpp b/examples/shapes/wrapper/geometry/Point_2.cppwg.cpp index 33864ac..190020d 100644 --- a/examples/shapes/wrapper/geometry/Point_2.cppwg.cpp +++ b/examples/shapes/wrapper/geometry/Point_2.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Point_2.cppwg.hpp" diff --git a/examples/shapes/wrapper/geometry/Point_3.cppwg.cpp b/examples/shapes/wrapper/geometry/Point_3.cppwg.cpp index 1ac38c7..24c8bf7 100644 --- a/examples/shapes/wrapper/geometry/Point_3.cppwg.cpp +++ b/examples/shapes/wrapper/geometry/Point_3.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Point_3.cppwg.hpp" diff --git a/examples/shapes/wrapper/geometry/geometry.main.cpp b/examples/shapes/wrapper/geometry/_pyshapes_geometry.main.cppwg.cpp similarity index 86% rename from examples/shapes/wrapper/geometry/geometry.main.cpp rename to examples/shapes/wrapper/geometry/_pyshapes_geometry.main.cppwg.cpp index 7cf21be..6d7d31b 100644 --- a/examples/shapes/wrapper/geometry/geometry.main.cpp +++ b/examples/shapes/wrapper/geometry/_pyshapes_geometry.main.cppwg.cpp @@ -2,7 +2,7 @@ // Do not modify this file directly. #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Point_2.cppwg.hpp" #include "Point_3.cppwg.hpp" diff --git a/examples/shapes/wrapper/math_funcs/math_funcs.main.cpp b/examples/shapes/wrapper/math_funcs/_pyshapes_math_funcs.main.cppwg.cpp similarity index 84% rename from examples/shapes/wrapper/math_funcs/math_funcs.main.cpp rename to examples/shapes/wrapper/math_funcs/_pyshapes_math_funcs.main.cppwg.cpp index a5ad656..78ba6d1 100644 --- a/examples/shapes/wrapper/math_funcs/math_funcs.main.cpp +++ b/examples/shapes/wrapper/math_funcs/_pyshapes_math_funcs.main.cppwg.cpp @@ -2,7 +2,7 @@ // Do not modify this file directly. #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" namespace py = pybind11; diff --git a/examples/shapes/wrapper/mesh/AbstractMesh_2_2.cppwg.cpp b/examples/shapes/wrapper/mesh/AbstractMesh_2_2.cppwg.cpp index ffdd409..b2a60a7 100644 --- a/examples/shapes/wrapper/mesh/AbstractMesh_2_2.cppwg.cpp +++ b/examples/shapes/wrapper/mesh/AbstractMesh_2_2.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "AbstractMesh_2_2.cppwg.hpp" diff --git a/examples/shapes/wrapper/mesh/AbstractMesh_3_3.cppwg.cpp b/examples/shapes/wrapper/mesh/AbstractMesh_3_3.cppwg.cpp index 9c7df91..f5b2b97 100644 --- a/examples/shapes/wrapper/mesh/AbstractMesh_3_3.cppwg.cpp +++ b/examples/shapes/wrapper/mesh/AbstractMesh_3_3.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "AbstractMesh_3_3.cppwg.hpp" diff --git a/examples/shapes/wrapper/mesh/ConcreteMesh_2.cppwg.cpp b/examples/shapes/wrapper/mesh/ConcreteMesh_2.cppwg.cpp index 10ac791..8750693 100644 --- a/examples/shapes/wrapper/mesh/ConcreteMesh_2.cppwg.cpp +++ b/examples/shapes/wrapper/mesh/ConcreteMesh_2.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "ConcreteMesh_2.cppwg.hpp" diff --git a/examples/shapes/wrapper/mesh/ConcreteMesh_3.cppwg.cpp b/examples/shapes/wrapper/mesh/ConcreteMesh_3.cppwg.cpp index 7ba503e..3c96c97 100644 --- a/examples/shapes/wrapper/mesh/ConcreteMesh_3.cppwg.cpp +++ b/examples/shapes/wrapper/mesh/ConcreteMesh_3.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "ConcreteMesh_3.cppwg.hpp" diff --git a/examples/shapes/wrapper/mesh/mesh.main.cpp b/examples/shapes/wrapper/mesh/_pyshapes_mesh.main.cppwg.cpp similarity index 91% rename from examples/shapes/wrapper/mesh/mesh.main.cpp rename to examples/shapes/wrapper/mesh/_pyshapes_mesh.main.cppwg.cpp index a02dce2..4361e15 100644 --- a/examples/shapes/wrapper/mesh/mesh.main.cpp +++ b/examples/shapes/wrapper/mesh/_pyshapes_mesh.main.cppwg.cpp @@ -2,7 +2,7 @@ // Do not modify this file directly. #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "AbstractMesh_2_2.cppwg.hpp" #include "AbstractMesh_3_3.cppwg.hpp" #include "ConcreteMesh_2.cppwg.hpp" diff --git a/examples/shapes/wrapper/primitives/Cuboid.cppwg.cpp b/examples/shapes/wrapper/primitives/Cuboid.cppwg.cpp index 485dfae..cfaa752 100644 --- a/examples/shapes/wrapper/primitives/Cuboid.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Cuboid.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Cuboid.cppwg.hpp" diff --git a/examples/shapes/wrapper/primitives/Rectangle.cppwg.cpp b/examples/shapes/wrapper/primitives/Rectangle.cppwg.cpp index c5fabb2..83a286b 100644 --- a/examples/shapes/wrapper/primitives/Rectangle.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Rectangle.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Rectangle.cppwg.hpp" diff --git a/examples/shapes/wrapper/primitives/Shape_2.cppwg.cpp b/examples/shapes/wrapper/primitives/Shape_2.cppwg.cpp index 290702c..680e76d 100644 --- a/examples/shapes/wrapper/primitives/Shape_2.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Shape_2.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Shape_2.cppwg.hpp" diff --git a/examples/shapes/wrapper/primitives/Shape_3.cppwg.cpp b/examples/shapes/wrapper/primitives/Shape_3.cppwg.cpp index 709daf5..b775a6e 100644 --- a/examples/shapes/wrapper/primitives/Shape_3.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Shape_3.cppwg.cpp @@ -3,7 +3,7 @@ #include #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Shape_3.cppwg.hpp" diff --git a/examples/shapes/wrapper/primitives/primitives.main.cpp b/examples/shapes/wrapper/primitives/_pyshapes_primitives.main.cppwg.cpp similarity index 90% rename from examples/shapes/wrapper/primitives/primitives.main.cpp rename to examples/shapes/wrapper/primitives/_pyshapes_primitives.main.cppwg.cpp index 4d9eefa..f76918f 100644 --- a/examples/shapes/wrapper/primitives/primitives.main.cpp +++ b/examples/shapes/wrapper/primitives/_pyshapes_primitives.main.cppwg.cpp @@ -2,7 +2,7 @@ // Do not modify this file directly. #include -#include "wrapper_header_collection.hpp" +#include "wrapper_header_collection.cppwg.hpp" #include "Shape_2.cppwg.hpp" #include "Shape_3.cppwg.hpp" #include "Rectangle.cppwg.hpp" diff --git a/examples/shapes/wrapper/wrapper_header_collection.hpp b/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp similarity index 100% rename from examples/shapes/wrapper/wrapper_header_collection.hpp rename to examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp From 76bead14a4ed22b0e8af00223ff75be939a1a025 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 14:41:45 +0000 Subject: [PATCH 2/7] #12 Pre-sort classes by path --- cppwg/input/class_info.py | 21 +++++++++++++++------ cppwg/input/cpp_type_info.py | 4 ++-- cppwg/input/module_info.py | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cppwg/input/class_info.py b/cppwg/input/class_info.py index c4b274f..2971a48 100644 --- a/cppwg/input/class_info.py +++ b/cppwg/input/class_info.py @@ -211,6 +211,11 @@ def update_from_ns(self, source_ns: "namespace_t") -> None: # noqa: F821 self.decls.append(class_decl) + # Update the class source file if not already set + if not self.source_file_full_path: + self.source_file_full_path = self.decls[0].location.file_name + self.source_file = os.path.basename(self.source_file_full_path) + # Update the base class declarations self.base_decls = [ base.related_class for decl in self.decls for base in decl.bases @@ -229,13 +234,17 @@ def update_from_source(self, source_file_paths: List[str]) -> None: if self.excluded: return - # Map class to a source file, assuming the file name is the class name - for file_path in source_file_paths: - file_name = os.path.basename(file_path) - if self.name == os.path.splitext(file_name)[0]: - self.source_file_full_path = file_path - if self.source_file is None: + # Attempt to map class to a source file + if not self.source_file_full_path: + for file_path in source_file_paths: + file_name = os.path.basename(file_path) + # Match file name if set + if self.source_file == file_name: + self.source_file_full_path = file_path + # Match class name, assuming the file name is the class name + elif self.name == os.path.splitext(file_name)[0]: self.source_file = file_name + self.source_file_full_path = file_path # Extract template args from the source file self.extract_templates_from_source() diff --git a/cppwg/input/cpp_type_info.py b/cppwg/input/cpp_type_info.py index 1c89538..dd846eb 100644 --- a/cppwg/input/cpp_type_info.py +++ b/cppwg/input/cpp_type_info.py @@ -34,8 +34,8 @@ def __init__(self, name: str, type_config: Optional[Dict[str, Any]] = None): super().__init__(name) self.module_info: Optional["ModuleInfo"] = None # noqa: F821 - self.source_file_full_path: Optional[str] = None - self.source_file: Optional[str] = None + self.source_file_full_path: str = "" + self.source_file: str = "" self.name_override: Optional[str] = None self.template_signature: Optional[str] = None self.template_params: Optional[List[str]] = None diff --git a/cppwg/input/module_info.py b/cppwg/input/module_info.py index fbbea44..d826b71 100644 --- a/cppwg/input/module_info.py +++ b/cppwg/input/module_info.py @@ -125,7 +125,7 @@ def compare(a: CppClassInfo, b: CppClassInfo) -> int: cache[(b, a)] = 0 return 0 - self.class_info_collection.sort(key=lambda x: x.name) + self.class_info_collection.sort(key=lambda x: x.source_file_full_path) i = 0 n = len(self.class_info_collection) From 8811842cb4cb0fdbf17e825466ad225bfb99f195 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 14:55:38 +0000 Subject: [PATCH 3/7] #4 Fix formatting --- cppwg/writers/method_writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index c840cce..5cb7f4b 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -240,7 +240,7 @@ def generate_virtual_override_wrapper(self) -> str: if i == 0: arg_name_list.append(f"{arg.name}") else: - arg_name_list.append(" "*12 + f"{arg.name}") + arg_name_list.append(" " * 12 + f"{arg.name}") arg_string = ", ".join(arg_list) # e.g. "int a, bool b, double c" arg_name_string = ",\n".join(arg_name_list) # e.g. "a,\n b,\n c" From f759432ac34ed6fca567a5d9aee5db075e1ed1d5 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 15:03:55 +0000 Subject: [PATCH 4/7] 20 More informative diff test --- tests/test_shapes.py | 54 ++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 290a0bb..b6d3745 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -1,55 +1,35 @@ import os import subprocess import unittest +from difflib import context_diff from glob import glob -from typing import List -def get_file_lines(file_path: str) -> List[str]: - """ - Load a file into a list of lines - - Parameters - ---------- - file_path : str - The path to the file to load - - Returns - ------- - List[str] - A list of lines read from the file, with excess whitespace and empty lines removed - """ - - with open(file_path, "r") as in_file: - # remove excess whitespace - lines = [line.rstrip().lstrip() for line in in_file] - # remove empty lines - lines = [line for line in lines if line] - - return lines - - -def compare_files(file_path_a: str, file_path_b: str) -> bool: - """ - Check if two files have the same content +def file_diff(file_a: str, file_b: str) -> bool: + """Check if two files have the same content. Parameters __________ - file_path_a: str + file_a: str The path to the first file - file_path_b: str + file__b: str The path to the second file Returns __________ - bool - True if the files have the same content + str + A diff of the two files """ - # Get file lines with whitespace and empty lines stripped - file_lines_a = get_file_lines(file_path_a) - file_lines_b = get_file_lines(file_path_b) + # Read files and remove excess whitespace + with open(file_a, "r") as fa: + a = [line.strip() for line in fa] + a = [line for line in a if line] + + with open(file_b, "r") as fb: + b = [line.strip() for line in fb] + b = [line for line in b if line] - return file_lines_a == file_lines_b + return "\n".join(context_diff(a, b)) class TestShapes(unittest.TestCase): @@ -104,7 +84,7 @@ def test_wrapper_generation(self) -> None: self.assertTrue(os.path.isfile(file_ref)) self.assertTrue(os.path.isfile(file_gen)) - self.assertTrue(compare_files(file_gen, file_ref)) + self.assertEqual(file_diff(file_gen, file_ref), "") if __name__ == "__main__": From 6fc9a2aa7270d970e43c432a6f399d85b6a1f75f Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 15:13:04 +0000 Subject: [PATCH 5/7] #20 Increase test maxDiff --- tests/test_shapes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index b6d3745..260b9aa 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -76,6 +76,7 @@ def test_wrapper_generation(self) -> None: self.assertTrue(os.path.isdir(wrapper_root_gen)) # Compare the generated files with reference files + self.maxDiff = None for dirpath, _, filenames in os.walk(wrapper_root_ref): for filename in filenames: if filename.endswith(".cppwg.cpp") or filename.endswith(".cppwg.hpp"): @@ -84,7 +85,7 @@ def test_wrapper_generation(self) -> None: self.assertTrue(os.path.isfile(file_ref)) self.assertTrue(os.path.isfile(file_gen)) - self.assertEqual(file_diff(file_gen, file_ref), "") + self.assertEqual(file_diff(file_gen, file_ref), "", f"\n{file_ref}") if __name__ == "__main__": From 9863d06e18f4f91b2c1f8e22cb0148644befb6c8 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 15:22:20 +0000 Subject: [PATCH 6/7] #12 Secondary sort classes by name --- cppwg/input/module_info.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cppwg/input/module_info.py b/cppwg/input/module_info.py index d826b71..7a48e50 100644 --- a/cppwg/input/module_info.py +++ b/cppwg/input/module_info.py @@ -125,7 +125,9 @@ def compare(a: CppClassInfo, b: CppClassInfo) -> int: cache[(b, a)] = 0 return 0 - self.class_info_collection.sort(key=lambda x: x.source_file_full_path) + self.class_info_collection.sort( + key=lambda x: (os.path.dirname(x.source_file_full_path), x.name) + ) i = 0 n = len(self.class_info_collection) From ce6c51e94e401f0cd1857c4d63871bdf2f427822 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 26 Sep 2024 17:05:11 +0000 Subject: [PATCH 7/7] #20 Sort headers consistently --- cppwg/input/class_info.py | 4 +- cppwg/input/package_info.py | 3 + cppwg/parsers/package_info_parser.py | 4 + cppwg/writers/header_collection_writer.py | 77 ++++++++----------- .../wrapper_header_collection.cppwg.hpp | 18 ++--- 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/cppwg/input/class_info.py b/cppwg/input/class_info.py index 2971a48..c2edd6e 100644 --- a/cppwg/input/class_info.py +++ b/cppwg/input/class_info.py @@ -235,7 +235,9 @@ def update_from_source(self, source_file_paths: List[str]) -> None: return # Attempt to map class to a source file - if not self.source_file_full_path: + if self.source_file_full_path: + self.source_file = os.path.basename(self.source_file_full_path) + else: for file_path in source_file_paths: file_name = os.path.basename(file_path) # Match file name if set diff --git a/cppwg/input/package_info.py b/cppwg/input/package_info.py index f90f24a..b31ca76 100644 --- a/cppwg/input/package_info.py +++ b/cppwg/input/package_info.py @@ -111,6 +111,9 @@ def collect_source_headers(self, restricted_paths: List[str]) -> None: logger.error(f"No header files found in source root: {self.source_root}") raise FileNotFoundError() + # Sort by filename + self.source_hpp_files.sort(key=lambda x: os.path.basename(x)) + def update_from_source(self) -> None: """ Update modules with information from the source headers. diff --git a/cppwg/parsers/package_info_parser.py b/cppwg/parsers/package_info_parser.py index 8f59f78..e2b62f7 100644 --- a/cppwg/parsers/package_info_parser.py +++ b/cppwg/parsers/package_info_parser.py @@ -215,6 +215,8 @@ def parse(self) -> PackageInfo: class_info.module_info = module_info module_info.class_info_collection.append(class_info) + module_info.class_info_collection.sort(key=lambda x: x.name) + # Parse the free function data and create free function info objects. # Note: if module_config["use_all_free_functions"] == True, free function # info objects will be added later after parsing the C++ source code. @@ -243,6 +245,8 @@ def parse(self) -> PackageInfo: free_function_info ) + module_info.free_function_info_collection.sort(key=lambda x: x.name) + # Parse the variable data if not module_config["use_all_variables"]: for raw_variable_info in module_config["variables"]: diff --git a/cppwg/writers/header_collection_writer.py b/cppwg/writers/header_collection_writer.py index 0c4fdbf..6ddc5c3 100644 --- a/cppwg/writers/header_collection_writer.py +++ b/cppwg/writers/header_collection_writer.py @@ -23,9 +23,9 @@ class CppHeaderCollectionWriter: The package information wrapper_root : str The output directory for the generated wrapper code - hpp_collection_filepath : str + hpp_collection_file : str The path to save the header collection file to - hpp_collection_string : str + hpp_collection : str The output string that gets written to the header collection file class_dict : Dict[str, CppClassInfo] A dictionary of all class info objects @@ -37,13 +37,13 @@ def __init__( self, package_info: PackageInfo, wrapper_root: str, - hpp_collection_filepath: str, + hpp_collection_file: str, ): self.package_info: PackageInfo = package_info self.wrapper_root: str = wrapper_root - self.hpp_collection_filepath: str = hpp_collection_filepath - self.hpp_collection_string: str = "" + self.hpp_collection_file: str = hpp_collection_file + self.hpp_collection: str = "" # For convenience, collect all class and free function info into dicts keyed by name self.class_dict: Dict[str, CppClassInfo] = {} @@ -73,24 +73,23 @@ def should_include_all(self) -> bool: def write(self) -> None: """Generate the header file output string and write it to file.""" # Add the top prefix text - self.hpp_collection_string += self.package_info.prefix_text + "\n" + self.hpp_collection += self.package_info.prefix_text + "\n" # Add opening header guard - self.hpp_collection_string += f"#ifndef {self.package_info.name}_HEADERS_HPP_\n" - self.hpp_collection_string += f"#define {self.package_info.name}_HEADERS_HPP_\n" + self.hpp_collection += f"#ifndef {self.package_info.name}_HEADERS_HPP_\n" + self.hpp_collection += f"#define {self.package_info.name}_HEADERS_HPP_\n" - self.hpp_collection_string += "\n// Includes\n" + self.hpp_collection += "\n// Includes\n" - included_files = set() # Keep track of included files to avoid duplicates + seen_files = set() # Keep track of included files to avoid duplicates if self.should_include_all(): # Include all the headers - for hpp_filepath in self.package_info.source_hpp_files: - hpp_filename = os.path.basename(hpp_filepath) - - if hpp_filename not in included_files: - self.hpp_collection_string += f'#include "{hpp_filename}"\n' - included_files.add(hpp_filename) + for filepath in self.package_info.source_hpp_files: + filename = os.path.basename(filepath) + if filename not in seen_files: + self.hpp_collection += f'#include "{filename}"\n' + seen_files.add(filename) else: # Include specific headers needed by classes @@ -100,30 +99,20 @@ def write(self) -> None: if class_info.excluded: continue - hpp_filename = None - - if class_info.source_file: - hpp_filename = class_info.source_file - - elif class_info.source_file_full_path: - hpp_filename = os.path.basename( - class_info.source_file_full_path - ) - - if hpp_filename and hpp_filename not in included_files: - self.hpp_collection_string += f'#include "{hpp_filename}"\n' - included_files.add(hpp_filename) + filename = class_info.source_file + if filename and filename not in seen_files: + self.hpp_collection += f'#include "{filename}"\n' + seen_files.add(filename) # Include specific headers needed by free functions for free_function_info in module_info.free_function_info_collection: if free_function_info.source_file_full_path: - hpp_filename = os.path.basename( + filename = os.path.basename( free_function_info.source_file_full_path ) - - if hpp_filename not in included_files: - self.hpp_collection_string += f'#include "{hpp_filename}"\n' - included_files.add(hpp_filename) + if filename not in seen_files: + self.hpp_collection += f'#include "{filename}"\n' + seen_files.add(filename) # Add the template instantiations e.g. `template class Foo<2,2>;` # and typdefs e.g. `typedef Foo<2,2> Foo_2_2;` @@ -150,19 +139,17 @@ def write(self) -> None: template_instantiations += f"template class {cpp_name};\n" template_typedefs += f" typedef {cpp_name} {py_name};\n" - self.hpp_collection_string += "\n// Instantiate Template Classes\n" - self.hpp_collection_string += template_instantiations + self.hpp_collection += "\n// Instantiate Template Classes\n" + self.hpp_collection += template_instantiations - self.hpp_collection_string += "\n// Typedefs for nicer naming\n" - self.hpp_collection_string += "namespace cppwg\n{\n" - self.hpp_collection_string += template_typedefs - self.hpp_collection_string += "} // namespace cppwg\n" + self.hpp_collection += "\n// Typedefs for nicer naming\n" + self.hpp_collection += "namespace cppwg\n{\n" + self.hpp_collection += template_typedefs + self.hpp_collection += "} // namespace cppwg\n" # Add closing header guard - self.hpp_collection_string += ( - f"\n#endif // {self.package_info.name}_HEADERS_HPP_\n" - ) + self.hpp_collection += f"\n#endif // {self.package_info.name}_HEADERS_HPP_\n" # Write the header collection string to file - with open(self.hpp_collection_filepath, "w") as hpp_file: - hpp_file.write(self.hpp_collection_string) + with open(self.hpp_collection_file, "w") as hpp_file: + hpp_file.write(self.hpp_collection) diff --git a/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp b/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp index dfad45a..8eb7eb1 100644 --- a/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp +++ b/examples/shapes/wrapper/wrapper_header_collection.cppwg.hpp @@ -5,26 +5,26 @@ #define pyshapes_HEADERS_HPP_ // Includes +#include "AbstractMesh.hpp" #include "ConcreteMesh.hpp" +#include "Cuboid.hpp" #include "MeshFactory.hpp" -#include "AbstractMesh.hpp" +#include "Point.hpp" +#include "Rectangle.hpp" +#include "Shape.hpp" #include "SimpleMathFunctions.hpp" #include "Square.hpp" -#include "Shape.hpp" -#include "Cuboid.hpp" #include "Triangle.hpp" -#include "Rectangle.hpp" -#include "Point.hpp" // Instantiate Template Classes template class Point<2>; template class Point<3>; template class Shape<2>; template class Shape<3>; -template class ConcreteMesh<2>; -template class ConcreteMesh<3>; template class AbstractMesh<2, 2>; template class AbstractMesh<3, 3>; +template class ConcreteMesh<2>; +template class ConcreteMesh<3>; // Typedefs for nicer naming namespace cppwg @@ -33,10 +33,10 @@ namespace cppwg typedef Point<3> Point_3; typedef Shape<2> Shape_2; typedef Shape<3> Shape_3; - typedef ConcreteMesh<2> ConcreteMesh_2; - typedef ConcreteMesh<3> ConcreteMesh_3; typedef AbstractMesh<2, 2> AbstractMesh_2_2; typedef AbstractMesh<3, 3> AbstractMesh_3_3; + typedef ConcreteMesh<2> ConcreteMesh_2; + typedef ConcreteMesh<3> ConcreteMesh_3; } // namespace cppwg #endif // pyshapes_HEADERS_HPP_