def setUp(self):
        cl = Class.rule.parseString("""
            template<T={string}>
            class Foo {
                template<C={int}>
                Foo(C& c);

                template<S={char}>
                static T staticMethod(const S& s);

                template<M={double}>
                T method(const M& m);

                T operator*(T other) const;

                T prop;
            };
        """)[0]
        class_instantiations = [Typename.rule.parseString('string')[0]]
        self.member_instantiations = [
            Typename.rule.parseString('int')[0],
            Typename.rule.parseString('char')[0],
            Typename.rule.parseString('double')[0],
        ]
        self.cl = InstantiatedClass(cl, class_instantiations)
        self.typenames = self.cl.original.template.typenames
    def test_construct(self):
        """Test the construct classmethod."""
        static_method = StaticMethod.rule.parseString("""
            template<U={double}>
            static T staticMethod(U& param);
            """)[0]
        method_instantiations = [Typename.rule.parseString("double")[0]]
        c = Class.rule.parseString("""
            template<T={string}>
            class Class {};
        """)[0]
        class_instantiations = [Typename.rule.parseString("string")[0]]

        typenames = ['T', 'U']
        parent = InstantiatedClass(c, class_instantiations)
        instantiated_args = instantiate_args_list(
            static_method.args.list(),
            typenames, class_instantiations + method_instantiations,
            parent.cpp_typename())

        instantiated_static_method = InstantiatedStaticMethod.construct(
            static_method, typenames, class_instantiations,
            method_instantiations, instantiated_args, parent)
        self.assertEqual(instantiated_static_method.name, "staticMethodDouble")
        self.assertEqual(
            instantiated_static_method.args.list()[0].ctype.get_typename(),
            "double")
        self.assertEqual(
            instantiated_static_method.return_type.type1.get_typename(),
            "string")
    def test_construct(self):
        """Test the construct classmethod."""
        constructor = Constructor.rule.parseString("""
            template<U={double}>
            Class(C x, const U& param);
            """)[0]
        c = Class.rule.parseString("""
            template<C={string}>
            class Class {};
        """)[0]
        class_instantiations = [Typename.rule.parseString("double")[0]]
        method_instantiations = [Typename.rule.parseString("string")[0]]
        typenames = ['C', 'U']
        parent = InstantiatedClass(c, class_instantiations)
        instantiated_args = instantiate_args_list(
            constructor.args.list(),
            typenames, class_instantiations + method_instantiations,
            parent.cpp_typename())

        instantiated_constructor = InstantiatedConstructor.construct(
            constructor, typenames, class_instantiations,
            method_instantiations, instantiated_args, parent)
        self.assertEqual(instantiated_constructor.name, "ClassDouble")
        self.assertEqual(
            instantiated_constructor.args.list()[0].ctype.get_typename(),
            "double")
        self.assertEqual(
            instantiated_constructor.args.list()[1].ctype.get_typename(),
            "string")
Esempio n. 4
0
    def wrap_instantiated_class(
            self, instantiated_class: instantiator.InstantiatedClass):
        """Wrap the class."""
        module_var = self._gen_module_var(instantiated_class.namespaces())
        cpp_class = instantiated_class.to_cpp()
        if cpp_class in self.ignore_classes:
            return ""
        if instantiated_class.parent_class:
            class_parent = "{instantiated_class.parent_class}, ".format(
                instantiated_class=instantiated_class)
        else:
            class_parent = ''

        if instantiated_class.enums:
            # If class has enums, define an instance and set module_var to the instance
            instance_name = instantiated_class.name.lower()
            class_declaration = (
                '\n    py::class_<{cpp_class}, {class_parent}'
                '{shared_ptr_type}::shared_ptr<{cpp_class}>> '
                '{instance_name}({module_var}, "{class_name}");'
                '\n    {instance_name}').format(
                    shared_ptr_type=('boost' if self.use_boost else 'std'),
                    cpp_class=cpp_class,
                    class_name=instantiated_class.name,
                    class_parent=class_parent,
                    instance_name=instance_name,
                    module_var=module_var)
            module_var = instance_name

        else:
            class_declaration = (
                '\n    py::class_<{cpp_class}, {class_parent}'
                '{shared_ptr_type}::shared_ptr<{cpp_class}>>({module_var}, "{class_name}")'
            ).format(shared_ptr_type=('boost' if self.use_boost else 'std'),
                     cpp_class=cpp_class,
                     class_name=instantiated_class.name,
                     class_parent=class_parent,
                     module_var=module_var)

        return ('{class_declaration}'
                '{wrapped_ctors}'
                '{wrapped_methods}'
                '{wrapped_static_methods}'
                '{wrapped_properties}'
                '{wrapped_operators};\n'.format(
                    class_declaration=class_declaration,
                    wrapped_ctors=self.wrap_ctors(instantiated_class),
                    wrapped_methods=self.wrap_methods(
                        instantiated_class.methods, cpp_class),
                    wrapped_static_methods=self.wrap_methods(
                        instantiated_class.static_methods, cpp_class),
                    wrapped_properties=self.wrap_properties(
                        instantiated_class.properties, cpp_class),
                    wrapped_operators=self.wrap_operators(
                        instantiated_class.operators, cpp_class)))
    def test_instantiate(self):
        """Test instantiate method."""
        method = Method.rule.parseString("""
            template<U={double}>
            double method(const T x, const U& param);
            """)[0]
        cls = Class.rule.parseString("""
            template<T={string}>
            class Foo {};
        """)[0]
        typenames = ['T', 'U']
        class_instantiations = [Typename.rule.parseString("string")[0]]
        method_instantiations = [Typename.rule.parseString("double")[0]]

        parent = InstantiatedClass(cls, class_instantiations)

        helper = InstantiationHelper(InstantiatedMethod)
        instantiated_methods = helper.instantiate([], method, typenames,
                                                  class_instantiations,
                                                  method_instantiations,
                                                  parent)

        self.assertEqual(len(instantiated_methods), 1)
        args_list = instantiated_methods[0].args.list()
        self.assertEqual(args_list[0].ctype.get_typename(), 'string')
        self.assertEqual(args_list[1].ctype.get_typename(), 'double')
    def test_multilevel_instantiation(self):
        """
        Test method for multilevel instantiation
        i.e. instantiation at both the class and method level.
        """
        cls = Class.rule.parseString("""
            template<T={string}>
            class Foo {
                template<U={double}>
                double method1(const T x, const U& param);

                template<V={int}>
                V method2(const T x);
            };
        """)[0]

        typenames = ['T']
        class_instantiations = [Typename.rule.parseString("string")[0]]
        parent = InstantiatedClass(cls, class_instantiations)

        helper = InstantiationHelper(InstantiatedMethod)

        instantiated_methods = helper.multilevel_instantiation(
            cls.methods, typenames, parent)
        self.assertEqual(len(instantiated_methods), 2)
        self.assertEqual(
            instantiated_methods[0].args.list()[0].ctype.get_typename(),
            'string')
        self.assertEqual(
            instantiated_methods[0].args.list()[1].ctype.get_typename(),
            'double')
        self.assertEqual(
            instantiated_methods[1].args.list()[0].ctype.get_typename(),
            'string')
        self.assertEqual(
            instantiated_methods[1].return_type.type1.get_typename(), 'int')
class TestInstantiatedClass(unittest.TestCase):
    """Tests for the InstantiatedClass class."""
    def setUp(self):
        cl = Class.rule.parseString("""
            template<T={string}>
            class Foo {
                template<C={int}>
                Foo(C& c);

                template<S={char}>
                static T staticMethod(const S& s);

                template<M={double}>
                T method(const M& m);

                T operator*(T other) const;

                T prop;
            };
        """)[0]
        class_instantiations = [Typename.rule.parseString('string')[0]]
        self.member_instantiations = [
            Typename.rule.parseString('int')[0],
            Typename.rule.parseString('char')[0],
            Typename.rule.parseString('double')[0],
        ]
        self.cl = InstantiatedClass(cl, class_instantiations)
        self.typenames = self.cl.original.template.typenames

    def test_constructor(self):
        """Test constructor."""
        self.assertIsInstance(self.cl, InstantiatedClass)
        self.assertIsInstance(self.cl.original, Class)
        self.assertEqual(self.cl.name, "FooString")

    def test_instantiate_ctors(self):
        """Test instantiate_ctors method."""
        ctors = self.cl.instantiate_ctors(self.typenames)
        self.assertEqual(len(ctors), 1)
        self.assertEqual(ctors[0].name, "FooString")
        self.assertEqual(ctors[0].args.list()[0].ctype.get_typename(), "int")

    def test_instantiate_static_methods(self):
        """Test instantiate_static_methods method."""
        static_methods = self.cl.instantiate_static_methods(self.typenames)
        self.assertEqual(len(static_methods), 1)
        self.assertEqual(static_methods[0].name, "staticMethodChar")
        self.assertEqual(static_methods[0].args.list()[0].ctype.get_typename(),
                         "char")
        self.assertEqual(static_methods[0].return_type.type1.get_typename(),
                         "string")

    def test_instantiate_methods(self):
        """Test instantiate_methods method."""
        methods = self.cl.instantiate_methods(self.typenames)
        self.assertEqual(len(methods), 1)
        self.assertEqual(methods[0].name, "methodDouble")
        self.assertEqual(methods[0].args.list()[0].ctype.get_typename(),
                         "double")
        self.assertEqual(methods[0].return_type.type1.get_typename(), "string")

    def test_instantiate_operators(self):
        """Test instantiate_operators method."""
        operators = self.cl.instantiate_operators(self.typenames)
        self.assertEqual(len(operators), 1)
        self.assertEqual(operators[0].operator, "*")
        self.assertEqual(operators[0].args.list()[0].ctype.get_typename(),
                         "string")
        self.assertEqual(operators[0].return_type.type1.get_typename(),
                         "string")

    def test_instantiate_properties(self):
        """Test instantiate_properties method."""
        properties = self.cl.instantiate_properties(self.typenames)
        self.assertEqual(len(properties), 1)
        self.assertEqual(properties[0].name, "prop")
        self.assertEqual(properties[0].ctype.get_typename(), "string")

    def test_cpp_typename(self):
        """Test cpp_typename method."""
        actual = self.cl.cpp_typename()
        self.assertEqual(actual.name, "Foo<string>")

    def test_to_cpp(self):
        """Test to_cpp method."""
        actual = self.cl.to_cpp()
        self.assertEqual(actual, "Foo<string>")