Skip to content

Commit

Permalink
Merge pull request #55 from Chaste/13-template-syntax
Browse files Browse the repository at this point in the history
Cosmetic template enhancements
  • Loading branch information
kwabenantim authored Sep 24, 2024
2 parents 0149425 + 3b2d10d commit 6c2e0a4
Show file tree
Hide file tree
Showing 47 changed files with 464 additions and 474 deletions.
16 changes: 8 additions & 8 deletions cppwg/input/class_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class CppClassInfo(CppTypeInfo):
cpp_names : List[str]
The C++ names of the class e.g. ["Foo<2,2>", "Foo<3,3>"]
py_names : List[str]
The Python names of the class e.g. ["Foo2_2", "Foo3_3"]
The Python names of the class e.g. ["Foo_2_2", "Foo_3_3"]
decls : pygccxml.declarations.declaration_t
Declarations for this type's base class, one per template instantiation
"""
Expand Down Expand Up @@ -252,7 +252,7 @@ def update_py_names(self) -> None:
special characters. The return type is a list, as a class can have
multiple names if it is templated. For example, a class "Foo" with
template arguments [[2, 2], [3, 3]] will have a python name list
["Foo2_2", "Foo3_3"].
["Foo_2_2", "Foo_3_3"].
"""
# Handles untemplated classes
if self.template_arg_lists is None:
Expand Down Expand Up @@ -308,7 +308,7 @@ def update_py_names(self) -> None:
if idx < len(template_arg_list) - 1:
template_string += "_"

self.py_names.append(type_name + template_string)
self.py_names.append(type_name + "_" + template_string)

def update_cpp_names(self) -> None:
"""
Expand All @@ -318,7 +318,7 @@ def update_cpp_names(self) -> None:
The return type is a list, as a class can have multiple names
if it is templated. For example, a class "Foo" with
template arguments [[2, 2], [3, 3]] will have a C++ name list
["Foo<2,2 >", "Foo<3,3 >"].
["Foo<2, 2>", "Foo<3, 3>"].
"""
# Handles untemplated classes
if self.template_arg_lists is None:
Expand All @@ -327,11 +327,11 @@ def update_cpp_names(self) -> None:

self.cpp_names = []
for template_arg_list in self.template_arg_lists:
# Create template string from arg list e.g. [2, 2] -> "<2,2 >"
template_string = ",".join([str(arg) for arg in template_arg_list])
template_string = "<" + template_string + " >"
# Create template string from arg list e.g. [2, 2] -> "<2, 2>"
template_string = ", ".join([str(arg) for arg in template_arg_list])
template_string = "<" + template_string + ">"

# Join full name e.g. "Foo<2,2 >"
# Join full name e.g. "Foo<2, 2>"
self.cpp_names.append(self.name + template_string)

def update_names(self) -> None:
Expand Down
20 changes: 11 additions & 9 deletions cppwg/templates/pybind11_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,23 @@
""" % tuple([CPPWG_EXT]*3)

class_virtual_override_header = """\
class {class_py_name}%s : public {class_py_name}{{
public:
class {class_py_name}%s : public {class_py_name}
{{
public:
using {class_py_name}::{class_base_name};
""" % CPPWG_CLASS_OVERRIDE_SUFFIX

class_virtual_override_footer = "}\n"

class_definition = """\
void register_{class_py_name}_class(py::module &m){{
py::class_<{class_py_name} {overrides_string} {ptr_support} {bases} >(m, "{class_py_name}")
void register_{class_py_name}_class(py::module &m)
{{
py::class_<{class_py_name}{overrides_string}{ptr_support}{bases}>(m, "{class_py_name}")
"""

method_virtual_override = """\
{return_type} {method_name}({arg_string}){const_adorn} override {{
{return_type} {method_name}({arg_string}){const_adorn} override
{{
PYBIND11_OVERRIDE{overload_adorn}(
{tidy_method_name},
{class_py_name},
Expand All @@ -61,14 +64,13 @@ class {class_py_name}%s : public {class_py_name}{{
smart_pointer_holder = "PYBIND11_DECLARE_HOLDER_TYPE(T, {}<T>)"

free_function = """\
m.def{def_adorn}("{function_name}", &{function_name}, {function_docs} {default_args});
m.def{def_adorn}("{function_name}", &{function_name}, {function_docs}{default_args});
"""

class_method = """\
.def{def_adorn}(
"{method_name}",
.def{def_adorn}("{method_name}",
({return_type}({self_ptr})({arg_signature}){const_adorn}) &{class_py_name}::{method_name},
{method_docs} {default_args} {call_policy})
{method_docs}{default_args}{call_policy})
"""

template_collection = {
Expand Down
14 changes: 7 additions & 7 deletions cppwg/writers/class_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def add_hpp(self, class_py_name: str) -> None:
Parameters
----------
class_py_name: str
The Python name of the class e.g. Foo2_2
The Python name of the class e.g. Foo_2_2
"""
# Add the top prefix text
self.hpp_string += self.class_info.module_info.package_info.prefix_text + "\n"
Expand All @@ -88,7 +88,7 @@ def add_cpp_header(self, class_cpp_name: str, class_py_name: str) -> None:
class_cpp_name : str
The C++ name of the class e.g. Foo<2,2>
class_py_name : str
The Python name of the class e.g. Foo2_2
The Python name of the class e.g. Foo_2_2
"""
# Add the top prefix text
self.cpp_string += self.class_info.module_info.package_info.prefix_text + "\n"
Expand Down Expand Up @@ -214,7 +214,7 @@ def add_virtual_overrides(
# void bar(double d) const override {
# PYBIND11_OVERRIDE_PURE(
# bar,
# Foo2_2,
# Foo_2_2,
# bar,
# d);
# }
Expand All @@ -227,7 +227,7 @@ def add_virtual_overrides(
)
self.cpp_string += method_writer.generate_virtual_override_wrapper()

self.cpp_string += "\n};\n"
self.cpp_string += "};\n\n"

return methods_needing_override

Expand Down Expand Up @@ -301,7 +301,7 @@ def write(self, work_dir: str) -> None:
smart_ptr_type: str = self.class_info.hierarchy_attribute("smart_ptr_type")
ptr_support = ""
if self.has_shared_ptr and smart_ptr_type:
ptr_support = f", {smart_ptr_type}<{class_py_name} > "
ptr_support = f", {smart_ptr_type}<{class_py_name}>"

# Add base classes to the wrapper class definition if needed
# e.g. py::class_<Foo, AbstractFoo, InterfaceFoo >(m, "Foo")
Expand All @@ -314,7 +314,7 @@ def write(self, work_dir: str) -> None:

# Check if the base class is also wrapped in the module
if base.related_class in self.module_class_decls:
bases += f", {base.related_class.name} "
bases += f", {base.related_class.name}"

# Add the class registration
class_definition_dict = {
Expand Down Expand Up @@ -378,7 +378,7 @@ def write_files(self, work_dir: str, class_py_name: str) -> None:
work_dir : str
The directory to write the files to
class_py_name : str
The Python name of the class e.g. Foo2_2
The Python name of the class e.g. Foo_2_2
"""
hpp_filepath = os.path.join(work_dir, f"{class_py_name}.{CPPWG_EXT}.hpp")
cpp_filepath = os.path.join(work_dir, f"{class_py_name}.{CPPWG_EXT}.cpp")
Expand Down
4 changes: 2 additions & 2 deletions cppwg/writers/constructor_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class CppConstructorWrapperWriter(CppBaseWrapperWriter):
wrapper_templates : Dict[str, str]
String templates with placeholders for generating wrapper code
class_py_name : Optional[str]
The Python name of the class e.g. 'Foo2_2'
The Python name of the class e.g. 'Foo_2_2'
template_params: Optional[List[str]]
The template params for the class e.g. ['DIM_A', 'DIM_B']
template_args: Optional[List[str]]
Expand Down Expand Up @@ -165,7 +165,7 @@ def generate_wrapper(self) -> str:
arg_types = [t.decl_string for t in self.ctor_decl.argument_types]
wrapper_string += ", ".join(arg_types)

wrapper_string += " >()"
wrapper_string += ">()"

# Keyword args with default values e.g. py::arg("i") = 1
keyword_args = ""
Expand Down
12 changes: 6 additions & 6 deletions cppwg/writers/header_collection_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class CppHeaderCollectionWriter:
The header collection file includes all the headers to be parsed by CastXML.
It also contains explicit template instantiations and their corresponding
typedefs (e.g. typedef Foo<2,2> Foo2_2) for all classes that are to be
typedefs (e.g. typedef Foo<2,2> Foo_2_2) for all classes that are to be
automatically wrapped.
Attributes
Expand Down Expand Up @@ -126,7 +126,7 @@ def write(self) -> None:
included_files.add(hpp_filename)

# Add the template instantiations e.g. `template class Foo<2,2>;`
# and typdefs e.g. `typedef Foo<2,2> Foo2_2;`
# and typdefs e.g. `typedef Foo<2,2> Foo_2_2;`
template_instantiations = ""
template_typedefs = ""

Expand All @@ -141,14 +141,14 @@ def write(self) -> None:
continue

# C++ class names eg. ["Foo<2,2>", "Foo<3,3>"]
cpp_names = [name.replace(" ", "") for name in class_info.cpp_names]
cpp_names = [name.strip() for name in class_info.cpp_names]

# Python class names eg. ["Foo2_2", "Foo3_3"]
py_names = [name.replace(" ", "") for name in class_info.py_names]
# Python class names eg. ["Foo_2_2", "Foo_3_3"]
py_names = [name.strip() for name in class_info.py_names]

for cpp_name, py_name in zip(cpp_names, py_names):
template_instantiations += f"template class {cpp_name};\n"
template_typedefs += f"typedef {cpp_name} {py_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
Expand Down
12 changes: 6 additions & 6 deletions cppwg/writers/method_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class CppMethodWrapperWriter(CppBaseWrapperWriter):
wrapper_templates : Dict[str, str]
String templates with placeholders for generating wrapper code
class_py_name : Optional[str]
The Python name of the class e.g. 'Foo2_2'
The Python name of the class e.g. 'Foo_2_2'
template_params: Optional[List[str]]
The template params for the class e.g. ['DIM_A', 'DIM_B']
template_args: Optional[List[str]]
Expand Down Expand Up @@ -135,13 +135,13 @@ def generate_wrapper(self) -> str:
if self.method_decl.has_static:
self_ptr = "*"
else:
# e.g. Foo2_2::*
# e.g. Foo_2_2::*
self_ptr = self.class_py_name + "::*"

# Const-ness
const_adorn = ""
if self.method_decl.has_const:
const_adorn = " const "
const_adorn = " const"

# Get the arg signature e.g. "int, bool"
arg_types = [t.decl_string for t in self.method_decl.argument_types]
Expand Down Expand Up @@ -214,7 +214,7 @@ def generate_virtual_override_wrapper(self) -> str:
void bar(double d) const override {
PYBIND11_OVERRIDE_PURE(
bar,
Foo2_2,
Foo_2_2,
bar,
d);
}
Expand All @@ -237,15 +237,15 @@ def generate_virtual_override_wrapper(self) -> str:
self.method_decl.arguments, self.method_decl.argument_types
):
arg_list.append(f"{arg_type.decl_string} {arg.name}")
arg_name_list.append(f" {arg.name}")
arg_name_list.append(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"

# Const-ness
const_adorn = ""
if self.method_decl.has_const:
const_adorn = " const "
const_adorn = " const"

# For pure virtual methods, use PYBIND11_OVERRIDE_PURE
overload_adorn = ""
Expand Down
4 changes: 2 additions & 2 deletions cppwg/writers/module_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def write_module_wrapper(self) -> None:
continue

for py_name in class_info.py_names:
# Example: #include "Foo2_2.cppwg.hpp"
# Example: #include "Foo_2_2.cppwg.hpp"
cpp_string += f'#include "{py_name}.{CPPWG_EXT}.hpp"\n'

# Format module name as _packagename_modulename
Expand All @@ -118,7 +118,7 @@ def write_module_wrapper(self) -> None:
continue

for py_name in class_info.py_names:
# Example: register_Foo2_2_class(m);"
# Example: register_Foo_2_2_class(m);"
cpp_string += f" register_{py_name}_class(m);\n"

# Add code from the module's custom generator
Expand Down
12 changes: 6 additions & 6 deletions examples/shapes/src/python/test/test_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ class TestClasses(unittest.TestCase):

def testGeometry(self):

p0 = pyshapes.geometry.Point2()
p0 = pyshapes.geometry.Point_2()
self.assertTrue(p0.GetLocation() == [0.0, 0.0])

p1 = pyshapes.geometry.Point2(5.0, 0.0)
p1 = pyshapes.geometry.Point_2(5.0, 0.0)
self.assertTrue(p1.GetLocation() == [5.0, 0.0])

p2 = pyshapes.geometry.Point2(5.0, 5.0)
p2 = pyshapes.geometry.Point_2(5.0, 5.0)
self.assertTrue(p2.GetLocation() == [5.0, 5.0])

p3 = pyshapes.geometry.Point2(0.0, 5.0)
p3 = pyshapes.geometry.Point_2(0.0, 5.0)
self.assertTrue(p3.GetLocation() == [0.0, 5.0])

points = [p1, p2, p3]

triangle = pyshapes.primitives.Shape2()
triangle = pyshapes.primitives.Shape_2()
triangle.SetVertices(points)
self.assertTrue(len(triangle.rGetVertices()) == 3)

Expand All @@ -38,7 +38,7 @@ def testGeometry(self):

def testMesh(self):

cmesh = pyshapes.mesh.ConcreteMesh2()
cmesh = pyshapes.mesh.ConcreteMesh_2()
self.assertTrue(cmesh.GetIndex() == 0)

cmesh.SetIndex(1)
Expand Down
39 changes: 0 additions & 39 deletions examples/shapes/wrapper/geometry/Point2.cppwg.cpp

This file was deleted.

10 changes: 0 additions & 10 deletions examples/shapes/wrapper/geometry/Point2.cppwg.hpp

This file was deleted.

Loading

0 comments on commit 6c2e0a4

Please sign in to comment.