mirror of
https://github.com/RYDE-WORK/pybind11.git
synced 2026-01-21 22:33:24 +08:00
This commit adds support for forcing alias type initialization by defining constructors with `py::init_alias<arg1, arg2>()` instead of `py::init<arg1, arg2>()`. Currently py::init<> only results in Alias initialization if the type is extended in python, or the given arguments can't be used to construct the base type, but can be used to construct the alias. py::init_alias<>, in contrast, always invokes the constructor of the alias type. It looks like this was already the intention of `py::detail::init_alias`, which was forward-declared in 86d825f3302701d81414ddd3d38bcd09433076bc, but was apparently never finished: despite the existance of a .def method accepting it, the `detail::init_alias` class isn't actually defined anywhere. This commit completes the feature (or possibly repurposes it), allowing declaration of classes that will always initialize the trampoline which is (as I argued in #397) sometimes useful.
160 lines
4.5 KiB
Python
160 lines
4.5 KiB
Python
import pytest
|
|
import gc
|
|
|
|
|
|
def test_regressions():
|
|
from pybind11_tests.issues import print_cchar, print_char
|
|
|
|
# #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(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):
|
|
return "Yay.."
|
|
|
|
class PyClass2(DispatchIssue):
|
|
def dispatch(self):
|
|
with pytest.raises(RuntimeError) as excinfo:
|
|
super(PyClass2, self).dispatch()
|
|
assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"'
|
|
|
|
p = PyClass1()
|
|
return dispatch_issue_go(p)
|
|
|
|
b = PyClass2()
|
|
assert dispatch_issue_go(b) == "Yay.."
|
|
|
|
|
|
def test_reference_wrapper():
|
|
"""#171: Can't return reference wrappers (or STL data structures containing them)"""
|
|
from pybind11_tests.issues import Placeholder, return_vec_of_reference_wrapper
|
|
|
|
assert str(return_vec_of_reference_wrapper(Placeholder(4))) == \
|
|
"[Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]]"
|
|
|
|
|
|
def test_iterator_passthrough():
|
|
"""#181: iterator passthrough did not compile"""
|
|
from pybind11_tests.issues import iterator_passthrough
|
|
|
|
assert list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15]))) == [3, 5, 7, 9, 11, 13, 15]
|
|
|
|
|
|
def test_shared_ptr_gc():
|
|
"""// #187: issue involving std::shared_ptr<> return value policy & garbage collection"""
|
|
from pybind11_tests.issues import ElementList, ElementA
|
|
|
|
el = ElementList()
|
|
for i in range(10):
|
|
el.add(ElementA(i))
|
|
gc.collect()
|
|
for i, v in enumerate(el.get()):
|
|
assert i == v.value()
|
|
|
|
|
|
def test_no_id(capture, msg):
|
|
from pybind11_tests.issues import get_element, expect_float, expect_int
|
|
|
|
with pytest.raises(TypeError) as excinfo:
|
|
get_element(None)
|
|
assert msg(excinfo.value) == """
|
|
Incompatible function arguments. The following argument types are supported:
|
|
1. (arg0: m.issues.ElementA) -> int
|
|
Invoked with: None
|
|
"""
|
|
|
|
with pytest.raises(TypeError) as excinfo:
|
|
expect_int(5.2)
|
|
assert msg(excinfo.value) == """
|
|
Incompatible function arguments. The following argument types are supported:
|
|
1. (arg0: int) -> int
|
|
Invoked with: 5.2
|
|
"""
|
|
assert expect_float(12) == 12
|
|
|
|
|
|
|
|
def test_str_issue(msg):
|
|
"""Issue #283: __str__ called on uninitialized instance when constructor arguments invalid"""
|
|
from pybind11_tests.issues import StrIssue
|
|
|
|
assert str(StrIssue(3)) == "StrIssue[3]"
|
|
|
|
with pytest.raises(TypeError) as excinfo:
|
|
str(StrIssue("no", "such", "constructor"))
|
|
assert msg(excinfo.value) == """
|
|
Incompatible constructor arguments. The following argument types are supported:
|
|
1. m.issues.StrIssue(arg0: int)
|
|
2. m.issues.StrIssue()
|
|
Invoked with: no, such, constructor
|
|
"""
|
|
|
|
|
|
def test_nested():
|
|
""" #328: first member in a class can't be used in operators"""
|
|
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
|
|
assert get_NestC(c) == 35
|
|
|
|
abase = a.as_base()
|
|
assert abase.value == -2
|
|
a.as_base().value += 44
|
|
assert abase.value == 42
|
|
assert c.b.a.as_base().value == -2
|
|
c.b.a.as_base().value += 44
|
|
assert c.b.a.as_base().value == 42
|
|
|
|
del c
|
|
gc.collect()
|
|
del a # Should't delete while abase is still alive
|
|
gc.collect()
|
|
|
|
assert abase.value == 42
|
|
del abase, b
|
|
gc.collect()
|
|
|
|
|
|
def test_move_fallback():
|
|
from pybind11_tests.issues import get_moveissue1, get_moveissue2
|
|
m2 = get_moveissue2(2)
|
|
assert m2.value == 2
|
|
m1 = get_moveissue1(1)
|
|
assert m1.value == 1
|
|
|
|
def test_override_ref():
|
|
from pybind11_tests.issues import OverrideTest
|
|
o = OverrideTest("asdf")
|
|
|
|
# Not allowed (see associated .cpp comment)
|
|
#i = o.str_ref()
|
|
#assert o.str_ref() == "asdf"
|
|
assert o.str_value() == "asdf"
|
|
|
|
assert o.A_value().value == "hi"
|
|
a = o.A_ref()
|
|
assert a.value == "hi"
|
|
a.value = "bye"
|
|
assert a.value == "bye"
|