diff --git a/tests/test_callbacks.cpp b/tests/test_callbacks.cpp index 80a0d0ead..270ff5ccd 100644 --- a/tests/test_callbacks.cpp +++ b/tests/test_callbacks.cpp @@ -12,18 +12,16 @@ #include -bool test_callback1(py::object func) { - func(); - return false; +py::object test_callback1(py::object func) { + return func(); } -int test_callback2(py::object func) { - py::object result = func("Hello", 'x', true, 5); - return result.cast(); +py::tuple test_callback2(py::object func) { + return func("Hello", 'x', true, 5); } -void test_callback3(const std::function &func) { - cout << "func(43) = " << func(43)<< std::endl; +std::string test_callback3(const std::function &func) { + return "func(43) = " + std::to_string(func(43)); } std::function test_callback4() { @@ -37,27 +35,24 @@ py::cpp_function test_callback5() { int dummy_function(int i) { return i + 1; } int dummy_function2(int i, int j) { return i + j; } -std::function roundtrip(std::function f) { - if (!f) - std::cout << "roundtrip (got None).." << std::endl; - else - std::cout << "roundtrip.." << std::endl; +std::function roundtrip(std::function f, bool expect_none = false) { + if (expect_none && f) { + throw std::runtime_error("Expected None to be converted to empty std::function"); + } return f; } -void test_dummy_function(const std::function &f) { +std::string test_dummy_function(const std::function &f) { using fn_type = int (*)(int); auto result = f.target(); if (!result) { - std::cout << "could not convert to a function pointer." << std::endl; auto r = f(1); - std::cout << "eval(1) = " << r << std::endl; + return "can't convert to function pointer: eval(1) = " + std::to_string(r); } else if (*result == dummy_function) { - std::cout << "argument matches dummy_function" << std::endl; auto r = (*result)(1); - std::cout << "eval(1) = " << r << std::endl; + return "matches dummy_function: eval(1) = " + std::to_string(r); } else { - std::cout << "argument does NOT match dummy_function. This should never happen!" << std::endl; + return "argument does NOT match dummy_function. This should never happen!"; } } @@ -96,7 +91,7 @@ void init_ex_callbacks(py::module &m) { /* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */ m.def("dummy_function", &dummy_function); m.def("dummy_function2", &dummy_function2); - m.def("roundtrip", &roundtrip); + m.def("roundtrip", &roundtrip, py::arg("f"), py::arg("expect_none")=false); m.def("test_dummy_function", &test_dummy_function); // Export the payload constructor statistics for testing purposes: m.def("payload_cstats", &ConstructorStats::get); diff --git a/tests/test_callbacks.py b/tests/test_callbacks.py index 3f70e87c4..83bc01635 100644 --- a/tests/test_callbacks.py +++ b/tests/test_callbacks.py @@ -1,70 +1,51 @@ import pytest -def test_inheritance(capture, msg): - from pybind11_tests import Pet, Dog, Rabbit, dog_bark, pet_print +def test_inheritance(msg): + from pybind11_tests import Pet, Dog, Rabbit, dog_bark, pet_name_species roger = Rabbit('Rabbit') assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot" - with capture: - pet_print(roger) - assert capture == "Rabbit is a parrot" + assert pet_name_species(roger) == "Rabbit is a parrot" polly = Pet('Polly', 'parrot') assert polly.name() + " is a " + polly.species() == "Polly is a parrot" - with capture: - pet_print(polly) - assert capture == "Polly is a parrot" + assert pet_name_species(polly) == "Polly is a parrot" molly = Dog('Molly') assert molly.name() + " is a " + molly.species() == "Molly is a dog" - with capture: - pet_print(molly) - assert capture == "Molly is a dog" + assert pet_name_species(molly) == "Molly is a dog" - with capture: - dog_bark(molly) - assert capture == "Woof!" + assert dog_bark(molly) == "Woof!" with pytest.raises(TypeError) as excinfo: dog_bark(polly) assert msg(excinfo.value) == """ Incompatible function arguments. The following argument types are supported: - 1. (arg0: m.Dog) -> None + 1. (arg0: m.Dog) -> str Invoked with: """ -def test_callbacks(capture): +def test_callbacks(): from functools import partial from pybind11_tests import (test_callback1, test_callback2, test_callback3, test_callback4, test_callback5) def func1(): - print('Callback function 1 called!') + return "func1" def func2(a, b, c, d): - print('Callback function 2 called : {}, {}, {}, {}'.format(a, b, c, d)) - return d + return "func2", a, b, c, d def func3(a): - print('Callback function 3 called : {}'.format(a)) + return "func3({})".format(a) - with capture: - assert test_callback1(func1) is False - assert capture == "Callback function 1 called!" - with capture: - assert test_callback2(func2) == 5 - assert capture == "Callback function 2 called : Hello, x, True, 5" - with capture: - assert test_callback1(partial(func2, "Hello", "from", "partial", "object")) is False - assert capture == "Callback function 2 called : Hello, from, partial, object" - with capture: - assert test_callback1(partial(func3, "Partial object with one argument")) is False - assert capture == "Callback function 3 called : Partial object with one argument" - with capture: - test_callback3(lambda i: i + 1) - assert capture == "func(43) = 44" + assert test_callback1(func1) == "func1" + assert test_callback2(func2) == ("func2", "Hello", "x", True, 5) + assert test_callback1(partial(func2, 1, 2, 3, 4)) == ("func2", 1, 2, 3, 4) + assert test_callback1(partial(func3, "partial")) == "func3(partial)" + assert test_callback3(lambda i: i + 1) == "func(43) = 44" f = test_callback4() assert f(43) == 44 @@ -82,49 +63,27 @@ def test_lambda_closure_cleanup(): assert cstats.move_constructions >= 1 -def test_cpp_function_roundtrip(capture): +def test_cpp_function_roundtrip(): """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer""" from pybind11_tests import dummy_function, dummy_function2, test_dummy_function, roundtrip - with capture: - test_dummy_function(dummy_function) - assert capture == """ - argument matches dummy_function - eval(1) = 2 - """ - with capture: - test_dummy_function(roundtrip(dummy_function)) - assert capture == """ - roundtrip.. - argument matches dummy_function - eval(1) = 2 - """ - with capture: - assert roundtrip(None) is None - assert capture == "roundtrip (got None).." - with capture: - test_dummy_function(lambda x: x + 2) - assert capture == """ - could not convert to a function pointer. - eval(1) = 3 - """ + assert test_dummy_function(dummy_function) == "matches dummy_function: eval(1) = 2" + assert test_dummy_function(roundtrip(dummy_function)) == "matches dummy_function: eval(1) = 2" + assert roundtrip(None, expect_none=True) is None + assert test_dummy_function(lambda x: x + 2) == "can't convert to function pointer: eval(1) = 3" - with capture: - with pytest.raises(TypeError) as excinfo: - test_dummy_function(dummy_function2) - assert "Incompatible function arguments" in str(excinfo.value) - assert capture == "could not convert to a function pointer." + with pytest.raises(TypeError) as excinfo: + test_dummy_function(dummy_function2) + assert "Incompatible function arguments" in str(excinfo.value) - with capture: - with pytest.raises(TypeError) as excinfo: - test_dummy_function(lambda x, y: x + y) - assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument", - "takes exactly 2 arguments")) - assert capture == "could not convert to a function pointer." + with pytest.raises(TypeError) as excinfo: + test_dummy_function(lambda x, y: x + y) + assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument", + "takes exactly 2 arguments")) def test_function_signatures(doc): from pybind11_tests import test_callback3, test_callback4 - assert doc(test_callback3) == "test_callback3(arg0: Callable[[int], int]) -> None" + assert doc(test_callback3) == "test_callback3(arg0: Callable[[int], int]) -> str" assert doc(test_callback4) == "test_callback4() -> Callable[[int], int]" diff --git a/tests/test_constants_and_functions.cpp b/tests/test_constants_and_functions.cpp index 1977a0aef..077fa7884 100644 --- a/tests/test_constants_and_functions.cpp +++ b/tests/test_constants_and_functions.cpp @@ -27,27 +27,24 @@ public: }; static EMode test_function(EMode mode) { - std::cout << "ExampleWithEnum::test_function(enum=" << mode << ")" << std::endl; return mode; } }; -bool test_function1() { - std::cout << "test_function()" << std::endl; - return false; +std::string test_function1() { + return "test_function()"; } -void test_function2(EMyEnumeration k) { - std::cout << "test_function(enum=" << k << ")" << std::endl; +std::string test_function2(EMyEnumeration k) { + return "test_function(enum=" + std::to_string(k) + ")"; } -float test_function3(int i) { - std::cout << "test_function(" << i << ")" << std::endl; - return (float) i / 2.f; +std::string test_function3(int i) { + return "test_function(" + std::to_string(i) + ")"; } -void test_ecenum(ECMyEnum z) { - std::cout << "test_ecenum(ECMyEnum::" << (z == ECMyEnum::Two ? "Two" : "Three") << ")" << std::endl; +std::string test_ecenum(ECMyEnum z) { + return "test_ecenum(ECMyEnum::" + std::string(z == ECMyEnum::Two ? "Two" : "Three") + ")"; } py::bytes return_bytes() { @@ -55,10 +52,14 @@ py::bytes return_bytes() { return std::string(data, 4); } -void print_bytes(py::bytes bytes) { - std::string value = (std::string) bytes; - for (size_t i = 0; i < value.length(); ++i) - std::cout << "bytes[" << i << "]=" << (int) value[i] << std::endl; +std::string print_bytes(py::bytes bytes) { + std::string ret = "bytes["; + const auto value = static_cast(bytes); + for (size_t i = 0; i < value.length(); ++i) { + ret += std::to_string(static_cast(value[i])) + " "; + } + ret.back() = ']'; + return ret; } void init_ex_constants_and_functions(py::module &m) { diff --git a/tests/test_constants_and_functions.py b/tests/test_constants_and_functions.py index 119965bf0..8295ef6f9 100644 --- a/tests/test_constants_and_functions.py +++ b/tests/test_constants_and_functions.py @@ -7,20 +7,13 @@ def test_constants(): assert some_constant == 14 -def test_function_overloading(capture): +def test_function_overloading(): from pybind11_tests import EMyEnumeration, test_function - with capture: - assert test_function() is False - assert test_function(7) == 3.5 - assert test_function(EMyEnumeration.EFirstEntry) is None - assert test_function(EMyEnumeration.ESecondEntry) is None - assert capture == """ - test_function() - test_function(7) - test_function(enum=1) - test_function(enum=2) - """ + assert test_function() == "test_function()" + assert test_function(7) == "test_function(7)" + assert test_function(EMyEnumeration.EFirstEntry) == "test_function(enum=1)" + assert test_function(EMyEnumeration.ESecondEntry) == "test_function(enum=2)" def test_unscoped_enum(): @@ -39,16 +32,12 @@ def test_unscoped_enum(): assert str(EMyEnumeration(2)) == "EMyEnumeration.ESecondEntry" -def test_scoped_enum(capture): +def test_scoped_enum(): from pybind11_tests import ECMyEnum, test_ecenum - with capture: - test_ecenum(ECMyEnum.Three) - assert capture == "test_ecenum(ECMyEnum::Three)" + assert test_ecenum(ECMyEnum.Three) == "test_ecenum(ECMyEnum::Three)" z = ECMyEnum.Two - with capture: - test_ecenum(z) - assert capture == "test_ecenum(ECMyEnum::Two)" + assert test_ecenum(z) == "test_ecenum(ECMyEnum::Two)" # expected TypeError exceptions for scoped enum ==/!= int comparisons with pytest.raises(TypeError): @@ -57,7 +46,7 @@ def test_scoped_enum(capture): assert z != 3 -def test_implicit_conversion(capture): +def test_implicit_conversion(): from pybind11_tests import ExampleWithEnum assert str(ExampleWithEnum.EMode.EFirstMode) == "EMode.EFirstMode" @@ -67,64 +56,29 @@ def test_implicit_conversion(capture): first = ExampleWithEnum.EFirstMode second = ExampleWithEnum.ESecondMode - with capture: - f(first) - assert capture == "ExampleWithEnum::test_function(enum=1)" + assert f(first) == 1 - with capture: - assert f(first) == f(first) - assert not f(first) != f(first) + assert f(first) == f(first) + assert not f(first) != f(first) - assert f(first) != f(second) - assert not f(first) == f(second) + assert f(first) != f(second) + assert not f(first) == f(second) - assert f(first) == int(f(first)) - assert not f(first) != int(f(first)) + assert f(first) == int(f(first)) + assert not f(first) != int(f(first)) - assert f(first) != int(f(second)) - assert not f(first) == int(f(second)) - assert capture == """ - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=2) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=2) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=2) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=2) - """ + assert f(first) != int(f(second)) + assert not f(first) == int(f(second)) - with capture: - # noinspection PyDictCreation - x = {f(first): 1, f(second): 2} - x[f(first)] = 3 - x[f(second)] = 4 - assert capture == """ - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=2) - ExampleWithEnum::test_function(enum=1) - ExampleWithEnum::test_function(enum=2) - """ + # noinspection PyDictCreation + x = {f(first): 1, f(second): 2} + x[f(first)] = 3 + x[f(second)] = 4 # Hashing test assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}" -def test_bytes(capture): +def test_bytes(): from pybind11_tests import return_bytes, print_bytes - with capture: - print_bytes(return_bytes()) - assert capture == """ - bytes[0]=1 - bytes[1]=0 - bytes[2]=2 - bytes[3]=0 - """ + assert print_bytes(return_bytes()) == "bytes[1 0 2 0]" diff --git a/tests/test_inheritance.cpp b/tests/test_inheritance.cpp index b70ea77a1..2997ccece 100644 --- a/tests/test_inheritance.cpp +++ b/tests/test_inheritance.cpp @@ -23,7 +23,7 @@ private: class Dog : public Pet { public: Dog(const std::string &name) : Pet(name, "dog") {} - void bark() const { std::cout << "Woof!" << std::endl; } + std::string bark() const { return "Woof!"; } }; class Rabbit : public Pet { @@ -31,12 +31,12 @@ public: Rabbit(const std::string &name) : Pet(name, "parrot") {} }; -void pet_print(const Pet &pet) { - std::cout << pet.name() + " is a " + pet.species() << std::endl; +std::string pet_name_species(const Pet &pet) { + return pet.name() + " is a " + pet.species(); } -void dog_bark(const Dog &dog) { - dog.bark(); +std::string dog_bark(const Dog &dog) { + return dog.bark(); } @@ -59,7 +59,7 @@ void init_ex_inheritance(py::module &m) { py::class_(m, "Rabbit", py::base()) .def(py::init()); - m.def("pet_print", pet_print); + m.def("pet_name_species", pet_name_species); m.def("dog_bark", dog_bark); py::class_(m, "BaseClass").def(py::init<>()); diff --git a/tests/test_issues.cpp b/tests/test_issues.cpp index 085dff90c..a0d1fd5e8 100644 --- a/tests/test_issues.cpp +++ b/tests/test_issues.cpp @@ -34,19 +34,20 @@ void init_issues(py::module &m) { #endif // #137: const char* isn't handled properly - m2.def("print_cchar", [](const char *string) { std::cout << string << std::endl; }); + m2.def("print_cchar", [](const char *s) { return std::string(s); }); // #150: char bindings broken - m2.def("print_char", [](char c) { std::cout << c << std::endl; }); + m2.def("print_char", [](char c) { return std::string(1, c); }); // #159: virtual function dispatch has problems with similar-named functions - struct Base { virtual void dispatch(void) const { + struct Base { virtual std::string dispatch() const { /* for some reason MSVC2015 can't compile this if the function is pure virtual */ + return {}; }; }; struct DispatchIssue : Base { - virtual void dispatch(void) const { - PYBIND11_OVERLOAD_PURE(void, Base, dispatch, /* no arguments */); + virtual std::string dispatch() const { + PYBIND11_OVERLOAD_PURE(std::string, Base, dispatch, /* no arguments */); } }; @@ -54,7 +55,7 @@ void init_issues(py::module &m) { .def(py::init<>()) .def("dispatch", &Base::dispatch); - m2.def("dispatch_issue_go", [](const Base * b) { b->dispatch(); }); + m2.def("dispatch_issue_go", [](const Base * b) { return b->dispatch(); }); struct Placeholder { int i; Placeholder(int i) : i(i) { } }; @@ -171,7 +172,7 @@ void init_issues(py::module &m) { .def("as_base", [](NestA &a) -> NestABase& { return (NestABase&) a; }, py::return_value_policy::reference_internal); py::class_(m2, "NestB").def(py::init<>()).def(py::self -= int()).def_readwrite("a", &NestB::a); py::class_(m2, "NestC").def(py::init<>()).def(py::self *= int()).def_readwrite("b", &NestC::b); - m2.def("print_NestA", [](const NestA &a) { std::cout << a.value << std::endl; }); - m2.def("print_NestB", [](const NestB &b) { std::cout << b.value << std::endl; }); - m2.def("print_NestC", [](const NestC &c) { std::cout << c.value << std::endl; }); + m2.def("get_NestA", [](const NestA &a) { return a.value; }); + m2.def("get_NestB", [](const NestB &b) { return b.value; }); + m2.def("get_NestC", [](const NestC &c) { return c.value; }); } diff --git a/tests/test_issues.py b/tests/test_issues.py index 0ab2e3608..f76813964 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -2,24 +2,22 @@ import pytest import gc -def test_regressions(capture): +def test_regressions(): from pybind11_tests.issues import print_cchar, print_char - with capture: - print_cchar("const char *") # #137: const char* isn't handled properly - assert capture == "const char *" - with capture: - print_char("c") # #150: char bindings broken - assert capture == "c" + # #137: const char* isn't handled properly + assert print_cchar("const char *") == "const char *" + # #150: char bindings broken + assert print_char("c") == "c" -def test_dispatch_issue(capture, msg): +def test_dispatch_issue(msg): """#159: virtual function dispatch has problems with similar-named functions""" from pybind11_tests.issues import DispatchIssue, dispatch_issue_go class PyClass1(DispatchIssue): def dispatch(self): - print("Yay..") + return "Yay.." class PyClass2(DispatchIssue): def dispatch(self): @@ -28,12 +26,10 @@ def test_dispatch_issue(capture, msg): assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"' p = PyClass1() - dispatch_issue_go(p) + return dispatch_issue_go(p) b = PyClass2() - with capture: - dispatch_issue_go(b) - assert capture == "Yay.." + assert dispatch_issue_go(b) == "Yay.." def test_reference_wrapper(): @@ -127,36 +123,26 @@ def test_str_issue(capture, msg): """ -def test_nested(capture): +def test_nested(): """ #328: first member in a class can't be used in operators""" - from pybind11_tests.issues import NestA, NestB, NestC, print_NestA, print_NestB, print_NestC + from pybind11_tests.issues import NestA, NestB, NestC, get_NestA, get_NestB, get_NestC a = NestA() b = NestB() c = NestC() a += 10 + assert get_NestA(a) == 13 b.a += 100 + assert get_NestA(b.a) == 103 c.b.a += 1000 + assert get_NestA(c.b.a) == 1003 b -= 1 + assert get_NestB(b) == 3 c.b -= 3 + assert get_NestB(c.b) == 1 c *= 7 - - with capture: - print_NestA(a) - print_NestA(b.a) - print_NestA(c.b.a) - print_NestB(b) - print_NestB(c.b) - print_NestC(c) - assert capture == """ - 13 - 103 - 1003 - 3 - 1 - 35 - """ + assert get_NestC(c) == 35 abase = a.as_base() assert abase.value == -2 diff --git a/tests/test_kwargs_and_defaults.cpp b/tests/test_kwargs_and_defaults.cpp index 281624615..3fefc798d 100644 --- a/tests/test_kwargs_and_defaults.cpp +++ b/tests/test_kwargs_and_defaults.cpp @@ -10,13 +10,14 @@ #include "pybind11_tests.h" #include -void kw_func(int x, int y) { std::cout << "kw_func(x=" << x << ", y=" << y << ")" << std::endl; } +std::string kw_func(int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); } -void kw_func4(const std::vector &entries) { - std::cout << "kw_func4: "; +std::string kw_func4(const std::vector &entries) { + std::string ret = "{"; for (int i : entries) - std::cout << i << " "; - std::cout << endl; + ret += std::to_string(i) + " "; + ret.back() = '}'; + return ret; } py::object call_kw_func(py::function f) { diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py index 0d785a426..735722dec 100644 --- a/tests/test_kwargs_and_defaults.py +++ b/tests/test_kwargs_and_defaults.py @@ -5,77 +5,51 @@ from pybind11_tests import (kw_func0, kw_func1, kw_func2, kw_func3, kw_func4, ca def test_function_signatures(doc): - assert doc(kw_func0) == "kw_func0(arg0: int, arg1: int) -> None" - assert doc(kw_func1) == "kw_func1(x: int, y: int) -> None" - assert doc(kw_func2) == "kw_func2(x: int=100, y: int=200) -> None" + assert doc(kw_func0) == "kw_func0(arg0: int, arg1: int) -> str" + assert doc(kw_func1) == "kw_func1(x: int, y: int) -> str" + assert doc(kw_func2) == "kw_func2(x: int=100, y: int=200) -> str" assert doc(kw_func3) == "kw_func3(data: str='Hello world!') -> None" - assert doc(kw_func4) == "kw_func4(myList: List[int]=[13, 17]) -> None" - assert doc(kw_func_udl) == "kw_func_udl(x: int, y: int=300) -> None" - assert doc(kw_func_udl_z) == "kw_func_udl_z(x: int, y: int=0) -> None" + assert doc(kw_func4) == "kw_func4(myList: List[int]=[13, 17]) -> str" + assert doc(kw_func_udl) == "kw_func_udl(x: int, y: int=300) -> str" + assert doc(kw_func_udl_z) == "kw_func_udl_z(x: int, y: int=0) -> str" assert doc(args_function) == "args_function(*args) -> None" assert doc(args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> None" assert doc(KWClass.foo0) == "foo0(self: m.KWClass, arg0: int, arg1: float) -> None" assert doc(KWClass.foo1) == "foo1(self: m.KWClass, x: int, y: float) -> None" -def test_named_arguments(capture, msg): - with capture: - kw_func1(5, 10) - assert capture == "kw_func(x=5, y=10)" - with capture: - kw_func1(5, y=10) - assert capture == "kw_func(x=5, y=10)" - with capture: - kw_func1(y=10, x=5) - assert capture == "kw_func(x=5, y=10)" +def test_named_arguments(msg): + assert kw_func0(5, 10) == "x=5, y=10" - with capture: - kw_func2() - assert capture == "kw_func(x=100, y=200)" - with capture: - kw_func2(5) - assert capture == "kw_func(x=5, y=200)" - with capture: - kw_func2(x=5) - assert capture == "kw_func(x=5, y=200)" - with capture: - kw_func2(y=10) - assert capture == "kw_func(x=100, y=10)" - with capture: - kw_func2(5, 10) - assert capture == "kw_func(x=5, y=10)" - with capture: - kw_func2(x=5, y=10) - assert capture == "kw_func(x=5, y=10)" + assert kw_func1(5, 10) == "x=5, y=10" + assert kw_func1(5, y=10) == "x=5, y=10" + assert kw_func1(y=10, x=5) == "x=5, y=10" + + assert kw_func2() == "x=100, y=200" + assert kw_func2(5) == "x=5, y=200" + assert kw_func2(x=5) == "x=5, y=200" + assert kw_func2(y=10) == "x=100, y=10" + assert kw_func2(5, 10) == "x=5, y=10" + assert kw_func2(x=5, y=10) == "x=5, y=10" with pytest.raises(TypeError) as excinfo: # noinspection PyArgumentList kw_func2(x=5, y=10, z=12) assert msg(excinfo.value) == """ Incompatible function arguments. The following argument types are supported: - 1. (x: int=100, y: int=200) -> None + 1. (x: int=100, y: int=200) -> str Invoked with: """ - with capture: - kw_func4() - assert capture == "kw_func4: 13 17" - with capture: - kw_func4(myList=[1, 2, 3]) - assert capture == "kw_func4: 1 2 3" + assert kw_func4() == "{13 17}" + assert kw_func4(myList=[1, 2, 3]) == "{1 2 3}" - with capture: - kw_func_udl(x=5, y=10) - assert capture == "kw_func(x=5, y=10)" - with capture: - kw_func_udl_z(x=5) - assert capture == "kw_func(x=5, y=0)" + assert kw_func_udl(x=5, y=10) == "x=5, y=10" + assert kw_func_udl_z(x=5) == "x=5, y=0" def test_arg_and_kwargs(capture): - with capture: - call_kw_func(kw_func2) - assert capture == "kw_func(x=1234, y=5678)" + assert call_kw_func(kw_func2) == "x=1234, y=5678" with capture: args_function('arg1_value', 'arg2_value', 3) assert capture.unordered == """ diff --git a/tests/test_modules.cpp b/tests/test_modules.cpp index 3d96df616..b77dacce0 100644 --- a/tests/test_modules.cpp +++ b/tests/test_modules.cpp @@ -11,8 +11,8 @@ #include "pybind11_tests.h" #include "constructor_stats.h" -void submodule_func() { - std::cout << "submodule_func()" << std::endl; +std::string submodule_func() { + return "submodule_func()"; } class A { diff --git a/tests/test_modules.py b/tests/test_modules.py index 3deb02e3b..fe72f190a 100644 --- a/tests/test_modules.py +++ b/tests/test_modules.py @@ -1,14 +1,12 @@ -def test_nested_modules(capture): +def test_nested_modules(): import pybind11_tests from pybind11_tests.submodule import submodule_func assert pybind11_tests.__name__ == "pybind11_tests" assert pybind11_tests.submodule.__name__ == "pybind11_tests.submodule" - with capture: - submodule_func() - assert capture == "submodule_func()" + assert submodule_func() == "submodule_func()" def test_reference_internal(): diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index 9afd342b2..b4266d0f3 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -8,7 +8,6 @@ */ #include "pybind11_tests.h" - #include #ifdef __GNUC__ @@ -139,29 +138,48 @@ py::array_t create_string_array(bool non_empty) { } template -void print_recarray(py::array_t arr) { - auto req = arr.request(); - auto ptr = static_cast(req.ptr); - for (size_t i = 0; i < req.size; i++) - std::cout << ptr[i] << std::endl; +py::list print_recarray(py::array_t arr) { + const auto req = arr.request(); + const auto ptr = static_cast(req.ptr); + auto l = py::list(); + for (size_t i = 0; i < req.size; i++) { + std::stringstream ss; + ss << ptr[i]; + l.append(py::str(ss.str())); + } + return l; } -void print_format_descriptors() { - std::cout << py::format_descriptor::format() << std::endl; - std::cout << py::format_descriptor::format() << std::endl; - std::cout << py::format_descriptor::format() << std::endl; - std::cout << py::format_descriptor::format() << std::endl; - std::cout << py::format_descriptor::format() << std::endl; - std::cout << py::format_descriptor::format() << std::endl; +py::list print_format_descriptors() { + const auto fmts = { + py::format_descriptor::format(), + py::format_descriptor::format(), + py::format_descriptor::format(), + py::format_descriptor::format(), + py::format_descriptor::format(), + py::format_descriptor::format() + }; + auto l = py::list(); + for (const auto &fmt : fmts) { + l.append(py::cast(fmt)); + } + return l; } -void print_dtypes() { - std::cout << (std::string) py::dtype::of().str() << std::endl; - std::cout << (std::string) py::dtype::of().str() << std::endl; - std::cout << (std::string) py::dtype::of().str() << std::endl; - std::cout << (std::string) py::dtype::of().str() << std::endl; - std::cout << (std::string) py::dtype::of().str() << std::endl; - std::cout << (std::string) py::dtype::of().str() << std::endl; +py::list print_dtypes() { + const auto dtypes = { + py::dtype::of().str(), + py::dtype::of().str(), + py::dtype::of().str(), + py::dtype::of().str(), + py::dtype::of().str(), + py::dtype::of().str() + }; + auto l = py::list(); + for (const auto &s : dtypes) { + l.append(s); + } + return l; } py::array_t test_array_ctors(int i) { diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index 783f6ad25..73da34644 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -13,39 +13,35 @@ packed_dtype = np.dtype([('x', '?'), ('y', 'u4'), ('z', 'f4')]) @pytest.requires_numpy -def test_format_descriptors(capture): +def test_format_descriptors(): from pybind11_tests import get_format_unbound, print_format_descriptors with pytest.raises(RuntimeError) as excinfo: get_format_unbound() assert 'unsupported buffer format' in str(excinfo.value) - with capture: - print_format_descriptors() - assert capture == """ - T{=?:x:3x=I:y:=f:z:} - T{=?:x:=I:y:=f:z:} - T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:} - T{=?:x:3x=I:y:=f:z:12x} - T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x} - T{=3s:a:=3s:b:} - """ + assert print_format_descriptors() == [ + "T{=?:x:3x=I:y:=f:z:}", + "T{=?:x:=I:y:=f:z:}", + "T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:}", + "T{=?:x:3x=I:y:=f:z:12x}", + "T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x}", + "T{=3s:a:=3s:b:}" + ] @pytest.requires_numpy -def test_dtype(capture): +def test_dtype(): from pybind11_tests import print_dtypes, test_dtype_ctors, test_dtype_methods - with capture: - print_dtypes() - assert capture == """ - {'names':['x','y','z'], 'formats':['?',') { std::cout << "Int branch taken." << std::endl; }); - m.def("selective_func", [](py::array_t) { std::cout << "Float branch taken." << std::endl; }); - m.def("selective_func", [](py::array_t, py::array::c_style>) { std::cout << "Complex float branch taken." << std::endl; }); + m.def("selective_func", [](py::array_t) { return "Int branch taken."; }); + m.def("selective_func", [](py::array_t) { return "Float branch taken."; }); + m.def("selective_func", [](py::array_t, py::array::c_style>) { return "Complex float branch taken."; }); } diff --git a/tests/test_numpy_vectorize.py b/tests/test_numpy_vectorize.py index 6fcf80814..73da819a4 100644 --- a/tests/test_numpy_vectorize.py +++ b/tests/test_numpy_vectorize.py @@ -59,18 +59,12 @@ def test_vectorize(capture): @pytest.requires_numpy -def test_type_selection(capture): +def test_type_selection(): from pybind11_tests import selective_func - with capture: - selective_func(np.array([1], dtype=np.int32)) - selective_func(np.array([1.0], dtype=np.float32)) - selective_func(np.array([1.0j], dtype=np.complex64)) - assert capture == """ - Int branch taken. - Float branch taken. - Complex float branch taken. - """ + assert selective_func(np.array([1], dtype=np.int32)) == "Int branch taken." + assert selective_func(np.array([1.0], dtype=np.float32)) == "Float branch taken." + assert selective_func(np.array([1.0j], dtype=np.complex64)) == "Complex float branch taken." @pytest.requires_numpy diff --git a/tests/test_opaque_types.cpp b/tests/test_opaque_types.cpp index 0ede5e328..901f05e13 100644 --- a/tests/test_opaque_types.cpp +++ b/tests/test_opaque_types.cpp @@ -38,21 +38,21 @@ void init_ex_opaque_types(py::module &m) { .def_readwrite("stringList", &ClassWithSTLVecProperty::stringList); m.def("print_opaque_list", [](const StringList &l) { - std::cout << "Opaque list: ["; + std::string ret = "Opaque list: ["; bool first = true; for (auto entry : l) { if (!first) - std::cout << ", "; - std::cout << entry; + ret += ", "; + ret += entry; first = false; } - std::cout << "]" << std::endl; + return ret + "]"; }); m.def("return_void_ptr", []() { return (void *) 0x1234; }); - m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : 0x" << std::hex << (uint64_t) ptr << std::dec << std::endl; }); + m.def("get_void_ptr_value", [](void *ptr) { return reinterpret_cast(ptr); }); m.def("return_null_str", []() { return (char *) nullptr; }); - m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : 0x" << std::hex << (uint64_t) ptr << std::dec << std::endl; }); + m.def("get_null_str_value", [](char *ptr) { return reinterpret_cast(ptr); }); m.def("return_unique_ptr", []() -> std::unique_ptr { StringList *result = new StringList(); diff --git a/tests/test_opaque_types.py b/tests/test_opaque_types.py index 5c2ca9248..943686383 100644 --- a/tests/test_opaque_types.py +++ b/tests/test_opaque_types.py @@ -1,64 +1,48 @@ import pytest -def test_string_list(capture): +def test_string_list(): from pybind11_tests import StringList, ClassWithSTLVecProperty, print_opaque_list l = StringList() l.push_back("Element 1") l.push_back("Element 2") - with capture: - print_opaque_list(l) - assert capture == "Opaque list: [Element 1, Element 2]" + assert print_opaque_list(l) == "Opaque list: [Element 1, Element 2]" assert l.back() == "Element 2" for i, k in enumerate(l, start=1): assert k == "Element {}".format(i) l.pop_back() - with capture: - print_opaque_list(l) - assert capture == "Opaque list: [Element 1]" + assert print_opaque_list(l) == "Opaque list: [Element 1]" cvp = ClassWithSTLVecProperty() - with capture: - print_opaque_list(cvp.stringList) - assert capture == "Opaque list: []" + assert print_opaque_list(cvp.stringList) == "Opaque list: []" cvp.stringList = l cvp.stringList.push_back("Element 3") - with capture: - print_opaque_list(cvp.stringList) - assert capture == "Opaque list: [Element 1, Element 3]" + assert print_opaque_list(cvp.stringList) == "Opaque list: [Element 1, Element 3]" -def test_pointers(capture, msg): - from pybind11_tests import (return_void_ptr, print_void_ptr, ExampleMandA, - print_opaque_list, return_null_str, print_null_str, +def test_pointers(msg): + from pybind11_tests import (return_void_ptr, get_void_ptr_value, ExampleMandA, + print_opaque_list, return_null_str, get_null_str_value, return_unique_ptr, ConstructorStats) - with capture: - print_void_ptr(return_void_ptr()) - assert capture == "Got void ptr : 0x1234" - with capture: - print_void_ptr(ExampleMandA()) # Should also work for other C++ types - assert "Got void ptr" in capture + assert get_void_ptr_value(return_void_ptr()) == 0x1234 + assert get_void_ptr_value(ExampleMandA()) # Should also work for other C++ types assert ConstructorStats.get(ExampleMandA).alive() == 0 with pytest.raises(TypeError) as excinfo: - print_void_ptr([1, 2, 3]) # This should not work + get_void_ptr_value([1, 2, 3]) # This should not work assert msg(excinfo.value) == """ Incompatible function arguments. The following argument types are supported: - 1. (arg0: capsule) -> None + 1. (arg0: capsule) -> int Invoked with: [1, 2, 3] """ assert return_null_str() is None - with capture: - print_null_str(return_null_str()) - assert capture == "Got null str : 0x0" + assert get_null_str_value(return_null_str()) is not None ptr = return_unique_ptr() assert "StringList" in repr(ptr) - with capture: - print_opaque_list(ptr) - assert capture == "Opaque list: [some value]" + assert print_opaque_list(ptr) == "Opaque list: [some value]" diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py index f2efb6bed..27b0222af 100644 --- a/tests/test_virtual_functions.py +++ b/tests/test_virtual_functions.py @@ -173,7 +173,7 @@ def test_inheriting_repeat(capture): assert obj.lucky_number() == -4.25 -def test_move_support(capture, msg): +def test_move_support(capture): from pybind11_tests import NCVirt, NonCopyable, Movable class NCVirtExt(NCVirt):