mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
Simplify tests by replacing output capture with asserts where possible
The C++ part of the test code is modified to achieve this. As a result, this kind of test: ```python with capture: kw_func1(5, y=10) assert capture == "kw_func(x=5, y=10)" ``` can be replaced with a simple: `assert kw_func1(5, y=10) == "x=5, y=10"`
This commit is contained in:
parent
a0c1ccf0a9
commit
665e8804f3
@ -12,18 +12,16 @@
|
|||||||
#include <pybind11/functional.h>
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
|
||||||
bool test_callback1(py::object func) {
|
py::object test_callback1(py::object func) {
|
||||||
func();
|
return func();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_callback2(py::object func) {
|
py::tuple test_callback2(py::object func) {
|
||||||
py::object result = func("Hello", 'x', true, 5);
|
return func("Hello", 'x', true, 5);
|
||||||
return result.cast<int>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_callback3(const std::function<int(int)> &func) {
|
std::string test_callback3(const std::function<int(int)> &func) {
|
||||||
cout << "func(43) = " << func(43)<< std::endl;
|
return "func(43) = " + std::to_string(func(43));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<int(int)> test_callback4() {
|
std::function<int(int)> test_callback4() {
|
||||||
@ -37,27 +35,24 @@ py::cpp_function test_callback5() {
|
|||||||
|
|
||||||
int dummy_function(int i) { return i + 1; }
|
int dummy_function(int i) { return i + 1; }
|
||||||
int dummy_function2(int i, int j) { return i + j; }
|
int dummy_function2(int i, int j) { return i + j; }
|
||||||
std::function<int(int)> roundtrip(std::function<int(int)> f) {
|
std::function<int(int)> roundtrip(std::function<int(int)> f, bool expect_none = false) {
|
||||||
if (!f)
|
if (expect_none && f) {
|
||||||
std::cout << "roundtrip (got None).." << std::endl;
|
throw std::runtime_error("Expected None to be converted to empty std::function");
|
||||||
else
|
}
|
||||||
std::cout << "roundtrip.." << std::endl;
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_dummy_function(const std::function<int(int)> &f) {
|
std::string test_dummy_function(const std::function<int(int)> &f) {
|
||||||
using fn_type = int (*)(int);
|
using fn_type = int (*)(int);
|
||||||
auto result = f.target<fn_type>();
|
auto result = f.target<fn_type>();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
std::cout << "could not convert to a function pointer." << std::endl;
|
|
||||||
auto r = f(1);
|
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) {
|
} else if (*result == dummy_function) {
|
||||||
std::cout << "argument matches dummy_function" << std::endl;
|
|
||||||
auto r = (*result)(1);
|
auto r = (*result)(1);
|
||||||
std::cout << "eval(1) = " << r << std::endl;
|
return "matches dummy_function: eval(1) = " + std::to_string(r);
|
||||||
} else {
|
} 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 */
|
/* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
|
||||||
m.def("dummy_function", &dummy_function);
|
m.def("dummy_function", &dummy_function);
|
||||||
m.def("dummy_function2", &dummy_function2);
|
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);
|
m.def("test_dummy_function", &test_dummy_function);
|
||||||
// Export the payload constructor statistics for testing purposes:
|
// Export the payload constructor statistics for testing purposes:
|
||||||
m.def("payload_cstats", &ConstructorStats::get<Payload>);
|
m.def("payload_cstats", &ConstructorStats::get<Payload>);
|
||||||
|
@ -1,70 +1,51 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_inheritance(capture, msg):
|
def test_inheritance(msg):
|
||||||
from pybind11_tests import Pet, Dog, Rabbit, dog_bark, pet_print
|
from pybind11_tests import Pet, Dog, Rabbit, dog_bark, pet_name_species
|
||||||
|
|
||||||
roger = Rabbit('Rabbit')
|
roger = Rabbit('Rabbit')
|
||||||
assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
|
assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
|
||||||
with capture:
|
assert pet_name_species(roger) == "Rabbit is a parrot"
|
||||||
pet_print(roger)
|
|
||||||
assert capture == "Rabbit is a parrot"
|
|
||||||
|
|
||||||
polly = Pet('Polly', 'parrot')
|
polly = Pet('Polly', 'parrot')
|
||||||
assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
|
assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
|
||||||
with capture:
|
assert pet_name_species(polly) == "Polly is a parrot"
|
||||||
pet_print(polly)
|
|
||||||
assert capture == "Polly is a parrot"
|
|
||||||
|
|
||||||
molly = Dog('Molly')
|
molly = Dog('Molly')
|
||||||
assert molly.name() + " is a " + molly.species() == "Molly is a dog"
|
assert molly.name() + " is a " + molly.species() == "Molly is a dog"
|
||||||
with capture:
|
assert pet_name_species(molly) == "Molly is a dog"
|
||||||
pet_print(molly)
|
|
||||||
assert capture == "Molly is a dog"
|
|
||||||
|
|
||||||
with capture:
|
assert dog_bark(molly) == "Woof!"
|
||||||
dog_bark(molly)
|
|
||||||
assert capture == "Woof!"
|
|
||||||
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
dog_bark(polly)
|
dog_bark(polly)
|
||||||
assert msg(excinfo.value) == """
|
assert msg(excinfo.value) == """
|
||||||
Incompatible function arguments. The following argument types are supported:
|
Incompatible function arguments. The following argument types are supported:
|
||||||
1. (arg0: m.Dog) -> None
|
1. (arg0: m.Dog) -> str
|
||||||
Invoked with: <m.Pet object at 0>
|
Invoked with: <m.Pet object at 0>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def test_callbacks(capture):
|
def test_callbacks():
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pybind11_tests import (test_callback1, test_callback2, test_callback3,
|
from pybind11_tests import (test_callback1, test_callback2, test_callback3,
|
||||||
test_callback4, test_callback5)
|
test_callback4, test_callback5)
|
||||||
|
|
||||||
def func1():
|
def func1():
|
||||||
print('Callback function 1 called!')
|
return "func1"
|
||||||
|
|
||||||
def func2(a, b, c, d):
|
def func2(a, b, c, d):
|
||||||
print('Callback function 2 called : {}, {}, {}, {}'.format(a, b, c, d))
|
return "func2", a, b, c, d
|
||||||
return d
|
|
||||||
|
|
||||||
def func3(a):
|
def func3(a):
|
||||||
print('Callback function 3 called : {}'.format(a))
|
return "func3({})".format(a)
|
||||||
|
|
||||||
with capture:
|
assert test_callback1(func1) == "func1"
|
||||||
assert test_callback1(func1) is False
|
assert test_callback2(func2) == ("func2", "Hello", "x", True, 5)
|
||||||
assert capture == "Callback function 1 called!"
|
assert test_callback1(partial(func2, 1, 2, 3, 4)) == ("func2", 1, 2, 3, 4)
|
||||||
with capture:
|
assert test_callback1(partial(func3, "partial")) == "func3(partial)"
|
||||||
assert test_callback2(func2) == 5
|
assert test_callback3(lambda i: i + 1) == "func(43) = 44"
|
||||||
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"
|
|
||||||
|
|
||||||
f = test_callback4()
|
f = test_callback4()
|
||||||
assert f(43) == 44
|
assert f(43) == 44
|
||||||
@ -82,49 +63,27 @@ def test_lambda_closure_cleanup():
|
|||||||
assert cstats.move_constructions >= 1
|
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"""
|
"""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
|
from pybind11_tests import dummy_function, dummy_function2, test_dummy_function, roundtrip
|
||||||
|
|
||||||
with capture:
|
assert test_dummy_function(dummy_function) == "matches dummy_function: eval(1) = 2"
|
||||||
test_dummy_function(dummy_function)
|
assert test_dummy_function(roundtrip(dummy_function)) == "matches dummy_function: eval(1) = 2"
|
||||||
assert capture == """
|
assert roundtrip(None, expect_none=True) is None
|
||||||
argument matches dummy_function
|
assert test_dummy_function(lambda x: x + 2) == "can't convert to function pointer: eval(1) = 3"
|
||||||
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
|
|
||||||
"""
|
|
||||||
|
|
||||||
with capture:
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
test_dummy_function(dummy_function2)
|
test_dummy_function(dummy_function2)
|
||||||
assert "Incompatible function arguments" in str(excinfo.value)
|
assert "Incompatible function arguments" in str(excinfo.value)
|
||||||
assert capture == "could not convert to a function pointer."
|
|
||||||
|
|
||||||
with capture:
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
test_dummy_function(lambda x, y: x + y)
|
test_dummy_function(lambda x, y: x + y)
|
||||||
assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument",
|
assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument",
|
||||||
"takes exactly 2 arguments"))
|
"takes exactly 2 arguments"))
|
||||||
assert capture == "could not convert to a function pointer."
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_signatures(doc):
|
def test_function_signatures(doc):
|
||||||
from pybind11_tests import test_callback3, test_callback4
|
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]"
|
assert doc(test_callback4) == "test_callback4() -> Callable[[int], int]"
|
||||||
|
@ -27,27 +27,24 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static EMode test_function(EMode mode) {
|
static EMode test_function(EMode mode) {
|
||||||
std::cout << "ExampleWithEnum::test_function(enum=" << mode << ")" << std::endl;
|
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool test_function1() {
|
std::string test_function1() {
|
||||||
std::cout << "test_function()" << std::endl;
|
return "test_function()";
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_function2(EMyEnumeration k) {
|
std::string test_function2(EMyEnumeration k) {
|
||||||
std::cout << "test_function(enum=" << k << ")" << std::endl;
|
return "test_function(enum=" + std::to_string(k) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float test_function3(int i) {
|
std::string test_function3(int i) {
|
||||||
std::cout << "test_function(" << i << ")" << std::endl;
|
return "test_function(" + std::to_string(i) + ")";
|
||||||
return (float) i / 2.f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_ecenum(ECMyEnum z) {
|
std::string test_ecenum(ECMyEnum z) {
|
||||||
std::cout << "test_ecenum(ECMyEnum::" << (z == ECMyEnum::Two ? "Two" : "Three") << ")" << std::endl;
|
return "test_ecenum(ECMyEnum::" + std::string(z == ECMyEnum::Two ? "Two" : "Three") + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
py::bytes return_bytes() {
|
py::bytes return_bytes() {
|
||||||
@ -55,10 +52,14 @@ py::bytes return_bytes() {
|
|||||||
return std::string(data, 4);
|
return std::string(data, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_bytes(py::bytes bytes) {
|
std::string print_bytes(py::bytes bytes) {
|
||||||
std::string value = (std::string) bytes;
|
std::string ret = "bytes[";
|
||||||
for (size_t i = 0; i < value.length(); ++i)
|
const auto value = static_cast<std::string>(bytes);
|
||||||
std::cout << "bytes[" << i << "]=" << (int) value[i] << std::endl;
|
for (size_t i = 0; i < value.length(); ++i) {
|
||||||
|
ret += std::to_string(static_cast<int>(value[i])) + " ";
|
||||||
|
}
|
||||||
|
ret.back() = ']';
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_ex_constants_and_functions(py::module &m) {
|
void init_ex_constants_and_functions(py::module &m) {
|
||||||
|
@ -7,20 +7,13 @@ def test_constants():
|
|||||||
assert some_constant == 14
|
assert some_constant == 14
|
||||||
|
|
||||||
|
|
||||||
def test_function_overloading(capture):
|
def test_function_overloading():
|
||||||
from pybind11_tests import EMyEnumeration, test_function
|
from pybind11_tests import EMyEnumeration, test_function
|
||||||
|
|
||||||
with capture:
|
assert test_function() == "test_function()"
|
||||||
assert test_function() is False
|
assert test_function(7) == "test_function(7)"
|
||||||
assert test_function(7) == 3.5
|
assert test_function(EMyEnumeration.EFirstEntry) == "test_function(enum=1)"
|
||||||
assert test_function(EMyEnumeration.EFirstEntry) is None
|
assert test_function(EMyEnumeration.ESecondEntry) == "test_function(enum=2)"
|
||||||
assert test_function(EMyEnumeration.ESecondEntry) is None
|
|
||||||
assert capture == """
|
|
||||||
test_function()
|
|
||||||
test_function(7)
|
|
||||||
test_function(enum=1)
|
|
||||||
test_function(enum=2)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def test_unscoped_enum():
|
def test_unscoped_enum():
|
||||||
@ -39,16 +32,12 @@ def test_unscoped_enum():
|
|||||||
assert str(EMyEnumeration(2)) == "EMyEnumeration.ESecondEntry"
|
assert str(EMyEnumeration(2)) == "EMyEnumeration.ESecondEntry"
|
||||||
|
|
||||||
|
|
||||||
def test_scoped_enum(capture):
|
def test_scoped_enum():
|
||||||
from pybind11_tests import ECMyEnum, test_ecenum
|
from pybind11_tests import ECMyEnum, test_ecenum
|
||||||
|
|
||||||
with capture:
|
assert test_ecenum(ECMyEnum.Three) == "test_ecenum(ECMyEnum::Three)"
|
||||||
test_ecenum(ECMyEnum.Three)
|
|
||||||
assert capture == "test_ecenum(ECMyEnum::Three)"
|
|
||||||
z = ECMyEnum.Two
|
z = ECMyEnum.Two
|
||||||
with capture:
|
assert test_ecenum(z) == "test_ecenum(ECMyEnum::Two)"
|
||||||
test_ecenum(z)
|
|
||||||
assert capture == "test_ecenum(ECMyEnum::Two)"
|
|
||||||
|
|
||||||
# expected TypeError exceptions for scoped enum ==/!= int comparisons
|
# expected TypeError exceptions for scoped enum ==/!= int comparisons
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
@ -57,7 +46,7 @@ def test_scoped_enum(capture):
|
|||||||
assert z != 3
|
assert z != 3
|
||||||
|
|
||||||
|
|
||||||
def test_implicit_conversion(capture):
|
def test_implicit_conversion():
|
||||||
from pybind11_tests import ExampleWithEnum
|
from pybind11_tests import ExampleWithEnum
|
||||||
|
|
||||||
assert str(ExampleWithEnum.EMode.EFirstMode) == "EMode.EFirstMode"
|
assert str(ExampleWithEnum.EMode.EFirstMode) == "EMode.EFirstMode"
|
||||||
@ -67,11 +56,8 @@ def test_implicit_conversion(capture):
|
|||||||
first = ExampleWithEnum.EFirstMode
|
first = ExampleWithEnum.EFirstMode
|
||||||
second = ExampleWithEnum.ESecondMode
|
second = ExampleWithEnum.ESecondMode
|
||||||
|
|
||||||
with capture:
|
assert f(first) == 1
|
||||||
f(first)
|
|
||||||
assert capture == "ExampleWithEnum::test_function(enum=1)"
|
|
||||||
|
|
||||||
with capture:
|
|
||||||
assert f(first) == f(first)
|
assert f(first) == f(first)
|
||||||
assert not f(first) != f(first)
|
assert not f(first) != f(first)
|
||||||
|
|
||||||
@ -83,48 +69,16 @@ def test_implicit_conversion(capture):
|
|||||||
|
|
||||||
assert f(first) != int(f(second))
|
assert f(first) != int(f(second))
|
||||||
assert not 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)
|
|
||||||
"""
|
|
||||||
|
|
||||||
with capture:
|
|
||||||
# noinspection PyDictCreation
|
# noinspection PyDictCreation
|
||||||
x = {f(first): 1, f(second): 2}
|
x = {f(first): 1, f(second): 2}
|
||||||
x[f(first)] = 3
|
x[f(first)] = 3
|
||||||
x[f(second)] = 4
|
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)
|
|
||||||
"""
|
|
||||||
# Hashing test
|
# Hashing test
|
||||||
assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}"
|
assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}"
|
||||||
|
|
||||||
|
|
||||||
def test_bytes(capture):
|
def test_bytes():
|
||||||
from pybind11_tests import return_bytes, print_bytes
|
from pybind11_tests import return_bytes, print_bytes
|
||||||
|
|
||||||
with capture:
|
assert print_bytes(return_bytes()) == "bytes[1 0 2 0]"
|
||||||
print_bytes(return_bytes())
|
|
||||||
assert capture == """
|
|
||||||
bytes[0]=1
|
|
||||||
bytes[1]=0
|
|
||||||
bytes[2]=2
|
|
||||||
bytes[3]=0
|
|
||||||
"""
|
|
||||||
|
@ -23,7 +23,7 @@ private:
|
|||||||
class Dog : public Pet {
|
class Dog : public Pet {
|
||||||
public:
|
public:
|
||||||
Dog(const std::string &name) : Pet(name, "dog") {}
|
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 {
|
class Rabbit : public Pet {
|
||||||
@ -31,12 +31,12 @@ public:
|
|||||||
Rabbit(const std::string &name) : Pet(name, "parrot") {}
|
Rabbit(const std::string &name) : Pet(name, "parrot") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void pet_print(const Pet &pet) {
|
std::string pet_name_species(const Pet &pet) {
|
||||||
std::cout << pet.name() + " is a " + pet.species() << std::endl;
|
return pet.name() + " is a " + pet.species();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dog_bark(const Dog &dog) {
|
std::string dog_bark(const Dog &dog) {
|
||||||
dog.bark();
|
return dog.bark();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ void init_ex_inheritance(py::module &m) {
|
|||||||
py::class_<Rabbit>(m, "Rabbit", py::base<Pet>())
|
py::class_<Rabbit>(m, "Rabbit", py::base<Pet>())
|
||||||
.def(py::init<std::string>());
|
.def(py::init<std::string>());
|
||||||
|
|
||||||
m.def("pet_print", pet_print);
|
m.def("pet_name_species", pet_name_species);
|
||||||
m.def("dog_bark", dog_bark);
|
m.def("dog_bark", dog_bark);
|
||||||
|
|
||||||
py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
|
py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
|
||||||
|
@ -34,19 +34,20 @@ void init_issues(py::module &m) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #137: const char* isn't handled properly
|
// #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
|
// #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
|
// #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 */
|
/* for some reason MSVC2015 can't compile this if the function is pure virtual */
|
||||||
|
return {};
|
||||||
}; };
|
}; };
|
||||||
|
|
||||||
struct DispatchIssue : Base {
|
struct DispatchIssue : Base {
|
||||||
virtual void dispatch(void) const {
|
virtual std::string dispatch() const {
|
||||||
PYBIND11_OVERLOAD_PURE(void, Base, dispatch, /* no arguments */);
|
PYBIND11_OVERLOAD_PURE(std::string, Base, dispatch, /* no arguments */);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ void init_issues(py::module &m) {
|
|||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def("dispatch", &Base::dispatch);
|
.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) { } };
|
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);
|
.def("as_base", [](NestA &a) -> NestABase& { return (NestABase&) a; }, py::return_value_policy::reference_internal);
|
||||||
py::class_<NestB>(m2, "NestB").def(py::init<>()).def(py::self -= int()).def_readwrite("a", &NestB::a);
|
py::class_<NestB>(m2, "NestB").def(py::init<>()).def(py::self -= int()).def_readwrite("a", &NestB::a);
|
||||||
py::class_<NestC>(m2, "NestC").def(py::init<>()).def(py::self *= int()).def_readwrite("b", &NestC::b);
|
py::class_<NestC>(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("get_NestA", [](const NestA &a) { return a.value; });
|
||||||
m2.def("print_NestB", [](const NestB &b) { std::cout << b.value << std::endl; });
|
m2.def("get_NestB", [](const NestB &b) { return b.value; });
|
||||||
m2.def("print_NestC", [](const NestC &c) { std::cout << c.value << std::endl; });
|
m2.def("get_NestC", [](const NestC &c) { return c.value; });
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,22 @@ import pytest
|
|||||||
import gc
|
import gc
|
||||||
|
|
||||||
|
|
||||||
def test_regressions(capture):
|
def test_regressions():
|
||||||
from pybind11_tests.issues import print_cchar, print_char
|
from pybind11_tests.issues import print_cchar, print_char
|
||||||
|
|
||||||
with capture:
|
# #137: const char* isn't handled properly
|
||||||
print_cchar("const char *") # #137: const char* isn't handled properly
|
assert print_cchar("const char *") == "const char *"
|
||||||
assert capture == "const char *"
|
# #150: char bindings broken
|
||||||
with capture:
|
assert print_char("c") == "c"
|
||||||
print_char("c") # #150: char bindings broken
|
|
||||||
assert capture == "c"
|
|
||||||
|
|
||||||
|
|
||||||
def test_dispatch_issue(capture, msg):
|
def test_dispatch_issue(msg):
|
||||||
"""#159: virtual function dispatch has problems with similar-named functions"""
|
"""#159: virtual function dispatch has problems with similar-named functions"""
|
||||||
from pybind11_tests.issues import DispatchIssue, dispatch_issue_go
|
from pybind11_tests.issues import DispatchIssue, dispatch_issue_go
|
||||||
|
|
||||||
class PyClass1(DispatchIssue):
|
class PyClass1(DispatchIssue):
|
||||||
def dispatch(self):
|
def dispatch(self):
|
||||||
print("Yay..")
|
return "Yay.."
|
||||||
|
|
||||||
class PyClass2(DispatchIssue):
|
class PyClass2(DispatchIssue):
|
||||||
def dispatch(self):
|
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"'
|
assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"'
|
||||||
|
|
||||||
p = PyClass1()
|
p = PyClass1()
|
||||||
dispatch_issue_go(p)
|
return dispatch_issue_go(p)
|
||||||
|
|
||||||
b = PyClass2()
|
b = PyClass2()
|
||||||
with capture:
|
assert dispatch_issue_go(b) == "Yay.."
|
||||||
dispatch_issue_go(b)
|
|
||||||
assert capture == "Yay.."
|
|
||||||
|
|
||||||
|
|
||||||
def test_reference_wrapper():
|
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"""
|
""" #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()
|
a = NestA()
|
||||||
b = NestB()
|
b = NestB()
|
||||||
c = NestC()
|
c = NestC()
|
||||||
|
|
||||||
a += 10
|
a += 10
|
||||||
|
assert get_NestA(a) == 13
|
||||||
b.a += 100
|
b.a += 100
|
||||||
|
assert get_NestA(b.a) == 103
|
||||||
c.b.a += 1000
|
c.b.a += 1000
|
||||||
|
assert get_NestA(c.b.a) == 1003
|
||||||
b -= 1
|
b -= 1
|
||||||
|
assert get_NestB(b) == 3
|
||||||
c.b -= 3
|
c.b -= 3
|
||||||
|
assert get_NestB(c.b) == 1
|
||||||
c *= 7
|
c *= 7
|
||||||
|
assert get_NestC(c) == 35
|
||||||
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
|
|
||||||
"""
|
|
||||||
|
|
||||||
abase = a.as_base()
|
abase = a.as_base()
|
||||||
assert abase.value == -2
|
assert abase.value == -2
|
||||||
|
@ -10,13 +10,14 @@
|
|||||||
#include "pybind11_tests.h"
|
#include "pybind11_tests.h"
|
||||||
#include <pybind11/stl.h>
|
#include <pybind11/stl.h>
|
||||||
|
|
||||||
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<int> &entries) {
|
std::string kw_func4(const std::vector<int> &entries) {
|
||||||
std::cout << "kw_func4: ";
|
std::string ret = "{";
|
||||||
for (int i : entries)
|
for (int i : entries)
|
||||||
std::cout << i << " ";
|
ret += std::to_string(i) + " ";
|
||||||
std::cout << endl;
|
ret.back() = '}';
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
py::object call_kw_func(py::function f) {
|
py::object call_kw_func(py::function f) {
|
||||||
|
@ -5,77 +5,51 @@ from pybind11_tests import (kw_func0, kw_func1, kw_func2, kw_func3, kw_func4, ca
|
|||||||
|
|
||||||
|
|
||||||
def test_function_signatures(doc):
|
def test_function_signatures(doc):
|
||||||
assert doc(kw_func0) == "kw_func0(arg0: int, arg1: int) -> None"
|
assert doc(kw_func0) == "kw_func0(arg0: int, arg1: int) -> str"
|
||||||
assert doc(kw_func1) == "kw_func1(x: int, y: int) -> None"
|
assert doc(kw_func1) == "kw_func1(x: int, y: int) -> str"
|
||||||
assert doc(kw_func2) == "kw_func2(x: int=100, y: int=200) -> None"
|
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_func3) == "kw_func3(data: str='Hello world!') -> None"
|
||||||
assert doc(kw_func4) == "kw_func4(myList: List[int]=[13, 17]) -> 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) -> None"
|
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) -> None"
|
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_function) == "args_function(*args) -> None"
|
||||||
assert doc(args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> 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.foo0) == "foo0(self: m.KWClass, arg0: int, arg1: float) -> None"
|
||||||
assert doc(KWClass.foo1) == "foo1(self: m.KWClass, x: int, y: float) -> None"
|
assert doc(KWClass.foo1) == "foo1(self: m.KWClass, x: int, y: float) -> None"
|
||||||
|
|
||||||
|
|
||||||
def test_named_arguments(capture, msg):
|
def test_named_arguments(msg):
|
||||||
with capture:
|
assert kw_func0(5, 10) == "x=5, y=10"
|
||||||
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)"
|
|
||||||
|
|
||||||
with capture:
|
assert kw_func1(5, 10) == "x=5, y=10"
|
||||||
kw_func2()
|
assert kw_func1(5, y=10) == "x=5, y=10"
|
||||||
assert capture == "kw_func(x=100, y=200)"
|
assert kw_func1(y=10, x=5) == "x=5, y=10"
|
||||||
with capture:
|
|
||||||
kw_func2(5)
|
assert kw_func2() == "x=100, y=200"
|
||||||
assert capture == "kw_func(x=5, y=200)"
|
assert kw_func2(5) == "x=5, y=200"
|
||||||
with capture:
|
assert kw_func2(x=5) == "x=5, y=200"
|
||||||
kw_func2(x=5)
|
assert kw_func2(y=10) == "x=100, y=10"
|
||||||
assert capture == "kw_func(x=5, y=200)"
|
assert kw_func2(5, 10) == "x=5, y=10"
|
||||||
with capture:
|
assert kw_func2(x=5, y=10) == "x=5, y=10"
|
||||||
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)"
|
|
||||||
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
kw_func2(x=5, y=10, z=12)
|
kw_func2(x=5, y=10, z=12)
|
||||||
assert msg(excinfo.value) == """
|
assert msg(excinfo.value) == """
|
||||||
Incompatible function arguments. The following argument types are supported:
|
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:
|
Invoked with:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with capture:
|
assert kw_func4() == "{13 17}"
|
||||||
kw_func4()
|
assert kw_func4(myList=[1, 2, 3]) == "{1 2 3}"
|
||||||
assert capture == "kw_func4: 13 17"
|
|
||||||
with capture:
|
|
||||||
kw_func4(myList=[1, 2, 3])
|
|
||||||
assert capture == "kw_func4: 1 2 3"
|
|
||||||
|
|
||||||
with capture:
|
assert kw_func_udl(x=5, y=10) == "x=5, y=10"
|
||||||
kw_func_udl(x=5, y=10)
|
assert kw_func_udl_z(x=5) == "x=5, y=0"
|
||||||
assert capture == "kw_func(x=5, y=10)"
|
|
||||||
with capture:
|
|
||||||
kw_func_udl_z(x=5)
|
|
||||||
assert capture == "kw_func(x=5, y=0)"
|
|
||||||
|
|
||||||
|
|
||||||
def test_arg_and_kwargs(capture):
|
def test_arg_and_kwargs(capture):
|
||||||
with capture:
|
assert call_kw_func(kw_func2) == "x=1234, y=5678"
|
||||||
call_kw_func(kw_func2)
|
|
||||||
assert capture == "kw_func(x=1234, y=5678)"
|
|
||||||
with capture:
|
with capture:
|
||||||
args_function('arg1_value', 'arg2_value', 3)
|
args_function('arg1_value', 'arg2_value', 3)
|
||||||
assert capture.unordered == """
|
assert capture.unordered == """
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
#include "pybind11_tests.h"
|
#include "pybind11_tests.h"
|
||||||
#include "constructor_stats.h"
|
#include "constructor_stats.h"
|
||||||
|
|
||||||
void submodule_func() {
|
std::string submodule_func() {
|
||||||
std::cout << "submodule_func()" << std::endl;
|
return "submodule_func()";
|
||||||
}
|
}
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
|
|
||||||
def test_nested_modules(capture):
|
def test_nested_modules():
|
||||||
import pybind11_tests
|
import pybind11_tests
|
||||||
from pybind11_tests.submodule import submodule_func
|
from pybind11_tests.submodule import submodule_func
|
||||||
|
|
||||||
assert pybind11_tests.__name__ == "pybind11_tests"
|
assert pybind11_tests.__name__ == "pybind11_tests"
|
||||||
assert pybind11_tests.submodule.__name__ == "pybind11_tests.submodule"
|
assert pybind11_tests.submodule.__name__ == "pybind11_tests.submodule"
|
||||||
|
|
||||||
with capture:
|
assert submodule_func() == "submodule_func()"
|
||||||
submodule_func()
|
|
||||||
assert capture == "submodule_func()"
|
|
||||||
|
|
||||||
|
|
||||||
def test_reference_internal():
|
def test_reference_internal():
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pybind11_tests.h"
|
#include "pybind11_tests.h"
|
||||||
|
|
||||||
#include <pybind11/numpy.h>
|
#include <pybind11/numpy.h>
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
@ -139,29 +138,48 @@ py::array_t<StringStruct, 0> create_string_array(bool non_empty) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void print_recarray(py::array_t<S, 0> arr) {
|
py::list print_recarray(py::array_t<S, 0> arr) {
|
||||||
auto req = arr.request();
|
const auto req = arr.request();
|
||||||
auto ptr = static_cast<S*>(req.ptr);
|
const auto ptr = static_cast<S*>(req.ptr);
|
||||||
for (size_t i = 0; i < req.size; i++)
|
auto l = py::list();
|
||||||
std::cout << ptr[i] << std::endl;
|
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() {
|
py::list print_format_descriptors() {
|
||||||
std::cout << py::format_descriptor<SimpleStruct>::format() << std::endl;
|
const auto fmts = {
|
||||||
std::cout << py::format_descriptor<PackedStruct>::format() << std::endl;
|
py::format_descriptor<SimpleStruct>::format(),
|
||||||
std::cout << py::format_descriptor<NestedStruct>::format() << std::endl;
|
py::format_descriptor<PackedStruct>::format(),
|
||||||
std::cout << py::format_descriptor<PartialStruct>::format() << std::endl;
|
py::format_descriptor<NestedStruct>::format(),
|
||||||
std::cout << py::format_descriptor<PartialNestedStruct>::format() << std::endl;
|
py::format_descriptor<PartialStruct>::format(),
|
||||||
std::cout << py::format_descriptor<StringStruct>::format() << std::endl;
|
py::format_descriptor<PartialNestedStruct>::format(),
|
||||||
|
py::format_descriptor<StringStruct>::format()
|
||||||
|
};
|
||||||
|
auto l = py::list();
|
||||||
|
for (const auto &fmt : fmts) {
|
||||||
|
l.append(py::cast(fmt));
|
||||||
|
}
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_dtypes() {
|
py::list print_dtypes() {
|
||||||
std::cout << (std::string) py::dtype::of<SimpleStruct>().str() << std::endl;
|
const auto dtypes = {
|
||||||
std::cout << (std::string) py::dtype::of<PackedStruct>().str() << std::endl;
|
py::dtype::of<SimpleStruct>().str(),
|
||||||
std::cout << (std::string) py::dtype::of<NestedStruct>().str() << std::endl;
|
py::dtype::of<PackedStruct>().str(),
|
||||||
std::cout << (std::string) py::dtype::of<PartialStruct>().str() << std::endl;
|
py::dtype::of<NestedStruct>().str(),
|
||||||
std::cout << (std::string) py::dtype::of<PartialNestedStruct>().str() << std::endl;
|
py::dtype::of<PartialStruct>().str(),
|
||||||
std::cout << (std::string) py::dtype::of<StringStruct>().str() << std::endl;
|
py::dtype::of<PartialNestedStruct>().str(),
|
||||||
|
py::dtype::of<StringStruct>().str()
|
||||||
|
};
|
||||||
|
auto l = py::list();
|
||||||
|
for (const auto &s : dtypes) {
|
||||||
|
l.append(s);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
py::array_t<int32_t, 0> test_array_ctors(int i) {
|
py::array_t<int32_t, 0> test_array_ctors(int i) {
|
||||||
|
@ -13,39 +13,35 @@ packed_dtype = np.dtype([('x', '?'), ('y', 'u4'), ('z', 'f4')])
|
|||||||
|
|
||||||
|
|
||||||
@pytest.requires_numpy
|
@pytest.requires_numpy
|
||||||
def test_format_descriptors(capture):
|
def test_format_descriptors():
|
||||||
from pybind11_tests import get_format_unbound, print_format_descriptors
|
from pybind11_tests import get_format_unbound, print_format_descriptors
|
||||||
|
|
||||||
with pytest.raises(RuntimeError) as excinfo:
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
get_format_unbound()
|
get_format_unbound()
|
||||||
assert 'unsupported buffer format' in str(excinfo.value)
|
assert 'unsupported buffer format' in str(excinfo.value)
|
||||||
|
|
||||||
with capture:
|
assert print_format_descriptors() == [
|
||||||
print_format_descriptors()
|
"T{=?:x:3x=I:y:=f:z:}",
|
||||||
assert capture == """
|
"T{=?:x:=I:y:=f:z:}",
|
||||||
T{=?:x:3x=I:y:=f:z:}
|
"T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:}",
|
||||||
T{=?:x:=I:y:=f:z:}
|
"T{=?:x:3x=I:y:=f:z:12x}",
|
||||||
T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:}
|
"T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x}",
|
||||||
T{=?:x:3x=I:y:=f:z:12x}
|
"T{=3s:a:=3s:b:}"
|
||||||
T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x}
|
]
|
||||||
T{=3s:a:=3s:b:}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.requires_numpy
|
@pytest.requires_numpy
|
||||||
def test_dtype(capture):
|
def test_dtype():
|
||||||
from pybind11_tests import print_dtypes, test_dtype_ctors, test_dtype_methods
|
from pybind11_tests import print_dtypes, test_dtype_ctors, test_dtype_methods
|
||||||
|
|
||||||
with capture:
|
assert print_dtypes() == [
|
||||||
print_dtypes()
|
"{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}",
|
||||||
assert capture == """
|
"[('x', '?'), ('y', '<u4'), ('z', '<f4')]",
|
||||||
{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}
|
"[('a', {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}), ('b', [('x', '?'), ('y', '<u4'), ('z', '<f4')])]",
|
||||||
[('x', '?'), ('y', '<u4'), ('z', '<f4')]
|
"{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}",
|
||||||
[('a', {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}), ('b', [('x', '?'), ('y', '<u4'), ('z', '<f4')])]
|
"{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}",
|
||||||
{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}
|
"[('a', 'S3'), ('b', 'S3')]"
|
||||||
{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}
|
]
|
||||||
[('a', 'S3'), ('b', 'S3')]
|
|
||||||
"""
|
|
||||||
|
|
||||||
d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
|
d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
|
||||||
'offsets': [1, 10], 'itemsize': 20})
|
'offsets': [1, 10], 'itemsize': 20})
|
||||||
@ -58,7 +54,7 @@ def test_dtype(capture):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.requires_numpy
|
@pytest.requires_numpy
|
||||||
def test_recarray(capture):
|
def test_recarray():
|
||||||
from pybind11_tests import (create_rec_simple, create_rec_packed, create_rec_nested,
|
from pybind11_tests import (create_rec_simple, create_rec_packed, create_rec_nested,
|
||||||
print_rec_simple, print_rec_packed, print_rec_nested,
|
print_rec_simple, print_rec_packed, print_rec_nested,
|
||||||
create_rec_partial, create_rec_partial_nested)
|
create_rec_partial, create_rec_partial_nested)
|
||||||
@ -77,21 +73,17 @@ def test_recarray(capture):
|
|||||||
assert_equal(arr, elements, packed_dtype)
|
assert_equal(arr, elements, packed_dtype)
|
||||||
|
|
||||||
if dtype == simple_dtype:
|
if dtype == simple_dtype:
|
||||||
with capture:
|
assert print_rec_simple(arr) == [
|
||||||
print_rec_simple(arr)
|
"s:0,0,0",
|
||||||
assert capture == """
|
"s:1,1,1.5",
|
||||||
s:0,0,0
|
"s:0,2,3"
|
||||||
s:1,1,1.5
|
]
|
||||||
s:0,2,3
|
|
||||||
"""
|
|
||||||
else:
|
else:
|
||||||
with capture:
|
assert print_rec_packed(arr) == [
|
||||||
print_rec_packed(arr)
|
"p:0,0,0",
|
||||||
assert capture == """
|
"p:1,1,1.5",
|
||||||
p:0,0,0
|
"p:0,2,3"
|
||||||
p:1,1,1.5
|
]
|
||||||
p:0,2,3
|
|
||||||
"""
|
|
||||||
|
|
||||||
nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)])
|
nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)])
|
||||||
|
|
||||||
@ -104,13 +96,11 @@ def test_recarray(capture):
|
|||||||
assert_equal(arr, [((False, 0, 0.0), (True, 1, 1.5)),
|
assert_equal(arr, [((False, 0, 0.0), (True, 1, 1.5)),
|
||||||
((True, 1, 1.5), (False, 2, 3.0)),
|
((True, 1, 1.5), (False, 2, 3.0)),
|
||||||
((False, 2, 3.0), (True, 3, 4.5))], nested_dtype)
|
((False, 2, 3.0), (True, 3, 4.5))], nested_dtype)
|
||||||
with capture:
|
assert print_rec_nested(arr) == [
|
||||||
print_rec_nested(arr)
|
"n:a=s:0,0,0;b=p:1,1,1.5",
|
||||||
assert capture == """
|
"n:a=s:1,1,1.5;b=p:0,2,3",
|
||||||
n:a=s:0,0,0;b=p:1,1,1.5
|
"n:a=s:0,2,3;b=p:1,3,4.5"
|
||||||
n:a=s:1,1,1.5;b=p:0,2,3
|
]
|
||||||
n:a=s:0,2,3;b=p:1,3,4.5
|
|
||||||
"""
|
|
||||||
|
|
||||||
arr = create_rec_partial(3)
|
arr = create_rec_partial(3)
|
||||||
assert str(arr.dtype) == "{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}"
|
assert str(arr.dtype) == "{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}"
|
||||||
@ -142,19 +132,17 @@ def test_array_constructors():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.requires_numpy
|
@pytest.requires_numpy
|
||||||
def test_string_array(capture):
|
def test_string_array():
|
||||||
from pybind11_tests import create_string_array, print_string_array
|
from pybind11_tests import create_string_array, print_string_array
|
||||||
|
|
||||||
arr = create_string_array(True)
|
arr = create_string_array(True)
|
||||||
assert str(arr.dtype) == "[('a', 'S3'), ('b', 'S3')]"
|
assert str(arr.dtype) == "[('a', 'S3'), ('b', 'S3')]"
|
||||||
with capture:
|
assert print_string_array(arr) == [
|
||||||
print_string_array(arr)
|
"a='',b=''",
|
||||||
assert capture == """
|
"a='a',b='a'",
|
||||||
a='',b=''
|
"a='ab',b='ab'",
|
||||||
a='a',b='a'
|
"a='abc',b='abc'"
|
||||||
a='ab',b='ab'
|
]
|
||||||
a='abc',b='abc'
|
|
||||||
"""
|
|
||||||
dtype = arr.dtype
|
dtype = arr.dtype
|
||||||
assert arr['a'].tolist() == [b'', b'a', b'ab', b'abc']
|
assert arr['a'].tolist() == [b'', b'a', b'ab', b'abc']
|
||||||
assert arr['b'].tolist() == [b'', b'a', b'ab', b'abc']
|
assert arr['b'].tolist() == [b'', b'a', b'ab', b'abc']
|
||||||
|
@ -35,7 +35,7 @@ void init_ex_numpy_vectorize(py::module &m) {
|
|||||||
m.def("vectorized_func3", py::vectorize(my_func3));
|
m.def("vectorized_func3", py::vectorize(my_func3));
|
||||||
|
|
||||||
/// Numpy function which only accepts specific data types
|
/// Numpy function which only accepts specific data types
|
||||||
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { std::cout << "Int branch taken." << std::endl; });
|
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { return "Int branch taken."; });
|
||||||
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { std::cout << "Float branch taken." << std::endl; });
|
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { return "Float branch taken."; });
|
||||||
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { std::cout << "Complex float branch taken." << std::endl; });
|
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { return "Complex float branch taken."; });
|
||||||
}
|
}
|
||||||
|
@ -59,18 +59,12 @@ def test_vectorize(capture):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.requires_numpy
|
@pytest.requires_numpy
|
||||||
def test_type_selection(capture):
|
def test_type_selection():
|
||||||
from pybind11_tests import selective_func
|
from pybind11_tests import selective_func
|
||||||
|
|
||||||
with capture:
|
assert selective_func(np.array([1], dtype=np.int32)) == "Int branch taken."
|
||||||
selective_func(np.array([1], dtype=np.int32))
|
assert selective_func(np.array([1.0], dtype=np.float32)) == "Float branch taken."
|
||||||
selective_func(np.array([1.0], dtype=np.float32))
|
assert selective_func(np.array([1.0j], dtype=np.complex64)) == "Complex float branch taken."
|
||||||
selective_func(np.array([1.0j], dtype=np.complex64))
|
|
||||||
assert capture == """
|
|
||||||
Int branch taken.
|
|
||||||
Float branch taken.
|
|
||||||
Complex float branch taken.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.requires_numpy
|
@pytest.requires_numpy
|
||||||
|
@ -38,21 +38,21 @@ void init_ex_opaque_types(py::module &m) {
|
|||||||
.def_readwrite("stringList", &ClassWithSTLVecProperty::stringList);
|
.def_readwrite("stringList", &ClassWithSTLVecProperty::stringList);
|
||||||
|
|
||||||
m.def("print_opaque_list", [](const StringList &l) {
|
m.def("print_opaque_list", [](const StringList &l) {
|
||||||
std::cout << "Opaque list: [";
|
std::string ret = "Opaque list: [";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto entry : l) {
|
for (auto entry : l) {
|
||||||
if (!first)
|
if (!first)
|
||||||
std::cout << ", ";
|
ret += ", ";
|
||||||
std::cout << entry;
|
ret += entry;
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
std::cout << "]" << std::endl;
|
return ret + "]";
|
||||||
});
|
});
|
||||||
|
|
||||||
m.def("return_void_ptr", []() { return (void *) 0x1234; });
|
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<std::intptr_t>(ptr); });
|
||||||
m.def("return_null_str", []() { return (char *) nullptr; });
|
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<std::intptr_t>(ptr); });
|
||||||
|
|
||||||
m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
|
m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
|
||||||
StringList *result = new StringList();
|
StringList *result = new StringList();
|
||||||
|
@ -1,64 +1,48 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_string_list(capture):
|
def test_string_list():
|
||||||
from pybind11_tests import StringList, ClassWithSTLVecProperty, print_opaque_list
|
from pybind11_tests import StringList, ClassWithSTLVecProperty, print_opaque_list
|
||||||
|
|
||||||
l = StringList()
|
l = StringList()
|
||||||
l.push_back("Element 1")
|
l.push_back("Element 1")
|
||||||
l.push_back("Element 2")
|
l.push_back("Element 2")
|
||||||
with capture:
|
assert print_opaque_list(l) == "Opaque list: [Element 1, Element 2]"
|
||||||
print_opaque_list(l)
|
|
||||||
assert capture == "Opaque list: [Element 1, Element 2]"
|
|
||||||
assert l.back() == "Element 2"
|
assert l.back() == "Element 2"
|
||||||
|
|
||||||
for i, k in enumerate(l, start=1):
|
for i, k in enumerate(l, start=1):
|
||||||
assert k == "Element {}".format(i)
|
assert k == "Element {}".format(i)
|
||||||
l.pop_back()
|
l.pop_back()
|
||||||
with capture:
|
assert print_opaque_list(l) == "Opaque list: [Element 1]"
|
||||||
print_opaque_list(l)
|
|
||||||
assert capture == "Opaque list: [Element 1]"
|
|
||||||
|
|
||||||
cvp = ClassWithSTLVecProperty()
|
cvp = ClassWithSTLVecProperty()
|
||||||
with capture:
|
assert print_opaque_list(cvp.stringList) == "Opaque list: []"
|
||||||
print_opaque_list(cvp.stringList)
|
|
||||||
assert capture == "Opaque list: []"
|
|
||||||
|
|
||||||
cvp.stringList = l
|
cvp.stringList = l
|
||||||
cvp.stringList.push_back("Element 3")
|
cvp.stringList.push_back("Element 3")
|
||||||
with capture:
|
assert print_opaque_list(cvp.stringList) == "Opaque list: [Element 1, Element 3]"
|
||||||
print_opaque_list(cvp.stringList)
|
|
||||||
assert capture == "Opaque list: [Element 1, Element 3]"
|
|
||||||
|
|
||||||
|
|
||||||
def test_pointers(capture, msg):
|
def test_pointers(msg):
|
||||||
from pybind11_tests import (return_void_ptr, print_void_ptr, ExampleMandA,
|
from pybind11_tests import (return_void_ptr, get_void_ptr_value, ExampleMandA,
|
||||||
print_opaque_list, return_null_str, print_null_str,
|
print_opaque_list, return_null_str, get_null_str_value,
|
||||||
return_unique_ptr, ConstructorStats)
|
return_unique_ptr, ConstructorStats)
|
||||||
|
|
||||||
with capture:
|
assert get_void_ptr_value(return_void_ptr()) == 0x1234
|
||||||
print_void_ptr(return_void_ptr())
|
assert get_void_ptr_value(ExampleMandA()) # Should also work for other C++ types
|
||||||
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 ConstructorStats.get(ExampleMandA).alive() == 0
|
assert ConstructorStats.get(ExampleMandA).alive() == 0
|
||||||
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
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) == """
|
assert msg(excinfo.value) == """
|
||||||
Incompatible function arguments. The following argument types are supported:
|
Incompatible function arguments. The following argument types are supported:
|
||||||
1. (arg0: capsule) -> None
|
1. (arg0: capsule) -> int
|
||||||
Invoked with: [1, 2, 3]
|
Invoked with: [1, 2, 3]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert return_null_str() is None
|
assert return_null_str() is None
|
||||||
with capture:
|
assert get_null_str_value(return_null_str()) is not None
|
||||||
print_null_str(return_null_str())
|
|
||||||
assert capture == "Got null str : 0x0"
|
|
||||||
|
|
||||||
ptr = return_unique_ptr()
|
ptr = return_unique_ptr()
|
||||||
assert "StringList" in repr(ptr)
|
assert "StringList" in repr(ptr)
|
||||||
with capture:
|
assert print_opaque_list(ptr) == "Opaque list: [some value]"
|
||||||
print_opaque_list(ptr)
|
|
||||||
assert capture == "Opaque list: [some value]"
|
|
||||||
|
@ -173,7 +173,7 @@ def test_inheriting_repeat(capture):
|
|||||||
assert obj.lucky_number() == -4.25
|
assert obj.lucky_number() == -4.25
|
||||||
|
|
||||||
|
|
||||||
def test_move_support(capture, msg):
|
def test_move_support(capture):
|
||||||
from pybind11_tests import NCVirt, NonCopyable, Movable
|
from pybind11_tests import NCVirt, NonCopyable, Movable
|
||||||
|
|
||||||
class NCVirtExt(NCVirt):
|
class NCVirtExt(NCVirt):
|
||||||
|
Loading…
Reference in New Issue
Block a user