def test_string_vector(): with cython_extension_from("stringvector.hpp"): from stringvector import A a = A() substrings = ["AB", "CD", "EF"] res = a.concat(substrings) assert_equal(res, "ABCDEF")
def test_vector(): with cython_extension_from("vector.hpp"): from vector import A a = A() v = np.array([2.0, 1.0, 3.0]) n = a.norm(v) assert_equal(n, 14.0)
def test_operators(): with cython_extension_from("cppoperators.hpp"): from cppoperators import Operators op = Operators() assert_equal(op(2), 4) assert_equal(op[2], 2) assert_equal(op + 1, 6) assert_equal(op - 1, 4) assert_equal(op * 2, 10) assert_equal(op / 5, 1) assert_equal(op % 2, 1) assert_equal(op and True, True) op += 3 assert_equal(op.v, 3) op -= 1 assert_equal(op.v, 2) op *= 2 assert_equal(op.v, 4) op /= 4 assert_equal(op.v, 1) op %= 2 assert_equal(op.v, 1) op |= True assert_equal(op.b, True) op &= True assert_equal(op.b, True)
def test_template_class(): config = Config() config.register_class_specialization("A", "Ad", {"T": "double"}) with cython_extension_from("templateclass.hpp", config=config): from templateclass import Ad a = Ad(5.0) assert_equal(a.get(), 5.0)
def test_register_custom_type_converter(): class CustomTypeConverter(AbstractTypeConverter): def matches(self): raise NotImplementedError() def n_cpp_args(self): raise NotImplementedError() def add_includes(self, includes): raise NotImplementedError() def python_to_cpp(self): raise NotImplementedError() def cpp_call_args(self): raise NotImplementedError() def return_output(self, copy=True): raise NotImplementedError() def python_type_decl(self): raise NotImplementedError() def cpp_type_decl(self): raise NotImplementedError() config = Config() config.registered_converters.append(CustomTypeConverter) with cython_extension_from("boolinboolout.hpp", assert_warn=UserWarning, warn_msg="Ignoring method", config=config): pass
def test_dependent_parts(): with cython_extension_from(["deppart1.hpp", "deppart2.hpp"], modulename="depcombined"): from depcombined import A a = A() b = a.make() assert_equal(b.get_value(), 5)
def test_overloading_function_is_not_possible(): with cython_extension_from( "overloadfunction.hpp", assert_warn=UserWarning, warn_msg="Function 'plusOne' is already defined"): from overloadfunction import plus_one assert_equal(plus_one(3.0), 4.0)
def test_enum(): with cython_extension_from("enum.hpp"): from enum import MyEnum, enum_to_string assert_not_equal(MyEnum.FIRSTOPTION, MyEnum.SECONDOPTION) assert_not_equal(MyEnum.SECONDOPTION, MyEnum.THIRDOPTION) assert_equal(enum_to_string(MyEnum.FIRSTOPTION), "first") assert_equal(enum_to_string(MyEnum.SECONDOPTION), "second") assert_equal(enum_to_string(MyEnum.THIRDOPTION), "third")
def test_independent_parts(): with cython_extension_from(["indeppart1.hpp", "indeppart2.hpp"], modulename="combined"): from combined import ClassA, ClassB a = ClassA() assert_false(a.result()) b = ClassB() assert_true(b.result())
def test_overloading_method_is_not_possible(): with cython_extension_from("sgetternameclash.hpp"): from sgetternameclash import A a = A() a.n = 20 assert_equal(a.n, 20) a.set_n(30) assert_equal(a.get_n(), 30)
def test_ambiguous_method(): with cython_extension_from("subclass.hpp"): from subclass import A, B a = A() assert_equal(a.afun(), 1) b = B() assert_equal(b.afun(), 1) assert_equal(b.bfun(), 2)
def test_overloading_method_is_not_possible(): with cython_extension_from( "overloadmethod.hpp", assert_warn=UserWarning, warn_msg="Method 'A.plusOne' is already defined"): from overloadmethod import A a = A() assert_equal(a.plus_one(3.0), 4.0)
def test_inheritance_with_namespace(): with cython_extension_from("inheritancewithnamespace.hpp"): from inheritancewithnamespace import ClassA, ClassB a = ClassA() assert_equal(a.method_a(), 1) b = ClassB() assert_equal(b.method_a(), 1) assert_equal(b.method_b(), 2)
def test_blacklisted_method(): config = Config() config.ignore_method(class_name="MyClassB", method_name="myMethod") with cython_extension_from("ignoremethod.hpp", config=config, assert_warn=UserWarning, warn_msg="blacklist"): pass
def test_abstract_class(): config = Config() config.abstract_class("AbstractClass") with cython_extension_from("abstractclass.hpp", config=config, assert_warn=UserWarning, warn_msg="abstract"): from abstractclass import AbstractClass, DerivedClass d = DerivedClass(5.0) a = d.clone() assert_equal(a.square(), 25.0)
def test_blacklisted_class(): config = Config() config.ignore_class(full_paths("ignoreclass.hpp")[0], class_name="MyClassA") with cython_extension_from("ignoreclass.hpp", config=config, assert_warn=UserWarning, warn_msg="blacklist"): pass
def test_complex_field(): with cython_extension_from("complexfield.hpp"): from complexfield import A, B a = A() a.a = 5 b = B() b.a = a b.b = a assert_equal(b.a.a, 5) assert_equal(b.b.a, 5)
def test_comments(): with cython_extension_from("comments.hpp"): from comments import MyClass, MyEnum assert_multi_line_equal( lines("This is a brief class description.", "", " And this is a detailed description.", " "), MyClass.__doc__) assert_equal("Brief.", MyClass.method.__doc__.strip()) assert_equal("Brief description of enum.", MyEnum.__doc__.strip())
def test_template_function(): config = Config() config.register_function_specialization("addOne", "add_one_i", {"T": "int"}) config.register_function_specialization("addOne", "add_one_d", {"T": "double"}) with cython_extension_from("templatefunction.hpp", config=config): from templatefunction import add_one_i, add_one_d assert_equal(add_one_i(1), 2) assert_is_instance(add_one_i(1), int) assert_equal(add_one_d(2.0), 3.0) assert_is_instance(add_one_d(2.0), float)
def test_vector_of_struct(): with cython_extension_from("vectorofstruct.hpp"): from vectorofstruct import MyStruct, sum_of_activated_entries a = MyStruct() a.value = 5 a.active = False b = MyStruct() b.value = 10 b.active = True entries = [a, b] assert_equal(sum_of_activated_entries(entries), 10)
def test_complex_hierarchy(): with cython_extension_from("complexhierarchy.hpp"): from complexhierarchy import A, B a = A() assert_equal(a.base1_method(), 1) assert_equal(a.base2_method(), 2) assert_equal(a.a_method(), 3) b = B() assert_equal(b.base1_method(), 4) assert_equal(b.base2_method(), 2) assert_equal(b.b_method(), 5)
def test_comments(): with cython_extension_from("comments.hpp"): from comments import MyClass, MyEnum assert_multi_line_equal( lines("This is a brief class description.", " ", " And this is a detailed description.", " "), MyClass.__doc__) assert_equal("Brief.", MyClass.method.__doc__.strip()) assert_equal("Brief description of enum.", MyEnum.__doc__.strip())
def test_struct(): with cython_extension_from("mystruct.hpp"): from mystruct import A, print_mystruct_a, B, print_mystruct_b a = A() a.a = 5 a.b = [1.0, 2.0] assert_equal(a.a, 5) assert_equal(a.b, [1.0, 2.0]) assert_equal(print_mystruct_a(a), "a = 5, b[0] = 1, b[1] = 2, ") b = B() b.a = 10 assert_equal(b.a, 10) assert_equal(print_mystruct_b(b), "a = 10")
def test_template_method(): config = Config() specs = { "A::addOne": [ ("add_one_i", {"T": "int"}), ("add_one_d", {"T": "double"}) ] } config.register_method_specialization("A", "addOne", "add_one_i", {"T": "int"}) config.register_method_specialization("A", "addOne", "add_one_d", {"T": "double"}) with cython_extension_from("templatemethod.hpp", config=config): from templatemethod import A a = A() assert_equal(a.add_one_i(1), 2) assert_is_instance(a.add_one_i(1), int) assert_equal(a.add_one_d(2.0), 3.0) assert_is_instance(a.add_one_d(2.0), float)
def test_exceptions(): # A list of convertible exceptions can be found in the Cython docs: # http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#exceptions with cython_extension_from("throwexception.hpp"): from throwexception import (throw_bad_alloc, throw_bad_cast, throw_domain_error, throw_invalid_argument, throw_ios_base_failure, throw_out_of_range, throw_overflow_error, throw_range_error, throw_underflow_error, throw_other) assert_raises(MemoryError, throw_bad_alloc) assert_raises(TypeError, throw_bad_cast) assert_raises(ValueError, throw_domain_error) assert_raises(ValueError, throw_invalid_argument) assert_raises(IOError, throw_ios_base_failure) assert_raises(IndexError, throw_out_of_range) assert_raises(OverflowError, throw_overflow_error) assert_raises(ArithmeticError, throw_range_error) assert_raises(ArithmeticError, throw_underflow_error) assert_raises(RuntimeError, throw_other)
def test_template_method(): config = Config() specs = { "A::addOne": [("add_one_i", { "T": "int" }), ("add_one_d", { "T": "double" })] } config.register_method_specialization("A", "addOne", "add_one_i", {"T": "int"}) config.register_method_specialization("A", "addOne", "add_one_d", {"T": "double"}) with cython_extension_from("templatemethod.hpp", config=config): from templatemethod import A a = A() assert_equal(a.add_one_i(1), 2) assert_is_instance(a.add_one_i(1), int) assert_equal(a.add_one_d(2.0), 3.0) assert_is_instance(a.add_one_d(2.0), float)
def test_external_library(): library_dir = full_paths("externallib")[0] cwd = os.getcwd() try: os.chdir(library_dir) with hidden_stdout(): os.system("make") finally: os.chdir(cwd) shutil.copyfile(os.path.join(library_dir, "libmylib.so"), "libmylib.so") config = Config() config.add_library_dir(library_dir) config.add_library("mylib") with cython_extension_from("withexternallib.hpp", config=config, incdirs=["externallib"]): try: from withexternallib import get_number assert_equal(get_number(), 5) finally: os.remove("libmylib.so")
def test_python_keyword_conversion(): with cython_extension_from("pythonkeywords.hpp"): from pythonkeywords import my_fun assert_equal(my_fun(1, 2, 3), 6)
def test_missing_specialization(): with cython_extension_from("templatemethod.hpp", assert_warn=UserWarning, warn_msg="No template specialization"): from templatemethod import A assert_false(hasattr(A, "add_one"))
def test_constructor_args(): with cython_extension_from("constructorargs.hpp"): from constructorargs import A a = A(11, 7) assert_equal(18, a.sum())
def test_fails(): with cython_extension_from("fails.hpp", assert_warn=UserWarning, warn_msg="Ignoring method"): from fails import A assert_false(hasattr(A, "my_function"))
def test_namespaces(): with cython_extension_from("namespaces.hpp"): from namespaces import ClassA, ClassB
def test_twoctors(): with cython_extension_from("twoctors.hpp", assert_warn=UserWarning, warn_msg="'A' has more than one constructor"): pass
def test_function(): with cython_extension_from("function.hpp"): from function import fun1, fun2 assert_equal(fun1(0), 0) assert_equal(fun2(), 1)
def test_static_method(): with cython_extension_from("staticmethod.hpp"): from staticmethod import plus1, plus2 assert_equal(plus1(1), 2) assert_equal(plus2(1), 3)
def test_convert_vector(): eigen3_incdir = "/usr/include/eigen3" if not os.path.exists(eigen3_incdir): raise SkipTest("Eigen 3 include directory '%s' not found" % eigen3_incdir) eigen_vector_decl = """ cdef extern from "Eigen/Dense" namespace "Eigen": cdef cppclass VectorXd: VectorXd() VectorXd(int rows) VectorXd(VectorXd&) double* data() int rows() double& get "operator()"(int rows) """ class EigenConverter(AbstractTypeConverter): def __init__(self, tname, python_argname, type_info, context): super(EigenConverter, self).__init__( tname, python_argname, type_info, context) if self.python_argname is not None: self.cpp_argname = "cpp_" + python_argname else: self.cpp_argname = None def matches(self): return self.tname == "VectorXd" def n_cpp_args(self): return 1 def add_includes(self, includes): includes.numpy = True def python_to_cpp(self): return lines( "cdef int %(python_argname)s_length = %(python_argname)s.shape[0]", "cdef cpp.VectorXd %(cpp_argname)s = cpp.VectorXd(%(python_argname)s_length)", "cdef int %(python_argname)s_idx", "for %(python_argname)s_idx in range(%(python_argname)s_length):", " %(cpp_argname)s.data()[%(python_argname)s_idx] = %(python_argname)s[%(python_argname)s_idx]" ) % {"python_argname": self.python_argname, "cpp_argname": self.cpp_argname} def cpp_call_args(self): return [self.cpp_argname] def return_output(self, copy=True): return lines( "cdef int size = result.rows()", "cdef int res_idx", "cdef np.ndarray[double, ndim=1] res = np.ndarray(shape=(size,))", "for res_idx in range(size):", " res[res_idx] = result.get(res_idx)", "return res" ) def python_type_decl(self): return "np.ndarray[double, ndim=1] " + self.python_argname def cpp_type_decl(self): return "cdef cpp.VectorXd" config = Config() config.registered_converters.append(EigenConverter) config.add_decleration(eigen_vector_decl) with cython_extension_from("eigen.hpp", config=config, incdirs=eigen3_incdir): from eigen import make a = np.ones(5) assert_array_equal(make(a), a * 2.0)
def test_no_default_constructor(): with cython_extension_from("nodefaultctor.hpp"): from nodefaultctor import A a = A() a.set_member(5)
def test_typedef(): with cython_extension_from("typedef.hpp"): from typedef import fun assert_equal(fun(1.0), 2.0)
def test_another_include_dir(): with cython_extension_from("addincludedir.hpp", incdirs=["anotherincludedir"]): from addincludedir import length assert_equal(length(3.0, 4.0), 5.0)