| # -*- coding: utf-8 -*- |
| import pytest |
| |
| from pybind11_tests import custom_type_casters as m |
| |
| |
| def test_noconvert_args(msg): |
| a = m.ArgInspector() |
| assert ( |
| msg(a.f("hi")) |
| == """ |
| loading ArgInspector1 argument WITH conversion allowed. Argument value = hi |
| """ |
| ) |
| assert ( |
| msg(a.g("this is a", "this is b")) |
| == """ |
| loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a |
| loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b |
| 13 |
| loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2) |
| """ # noqa: E501 line too long |
| ) |
| assert ( |
| msg(a.g("this is a", "this is b", 42)) |
| == """ |
| loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a |
| loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b |
| 42 |
| loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2) |
| """ # noqa: E501 line too long |
| ) |
| assert ( |
| msg(a.g("this is a", "this is b", 42, "this is d")) |
| == """ |
| loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a |
| loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b |
| 42 |
| loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d |
| """ |
| ) |
| assert ( |
| a.h("arg 1") |
| == "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1" |
| ) |
| assert ( |
| msg(m.arg_inspect_func("A1", "A2")) |
| == """ |
| loading ArgInspector2 argument WITH conversion allowed. Argument value = A1 |
| loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2 |
| """ |
| ) |
| |
| assert m.floats_preferred(4) == 2.0 |
| assert m.floats_only(4.0) == 2.0 |
| with pytest.raises(TypeError) as excinfo: |
| m.floats_only(4) |
| assert ( |
| msg(excinfo.value) |
| == """ |
| floats_only(): incompatible function arguments. The following argument types are supported: |
| 1. (f: float) -> float |
| |
| Invoked with: 4 |
| """ |
| ) |
| |
| assert m.ints_preferred(4) == 2 |
| assert m.ints_preferred(True) == 0 |
| with pytest.raises(TypeError) as excinfo: |
| m.ints_preferred(4.0) |
| assert ( |
| msg(excinfo.value) |
| == """ |
| ints_preferred(): incompatible function arguments. The following argument types are supported: |
| 1. (i: int) -> int |
| |
| Invoked with: 4.0 |
| """ # noqa: E501 line too long |
| ) |
| |
| assert m.ints_only(4) == 2 |
| with pytest.raises(TypeError) as excinfo: |
| m.ints_only(4.0) |
| assert ( |
| msg(excinfo.value) |
| == """ |
| ints_only(): incompatible function arguments. The following argument types are supported: |
| 1. (i: int) -> int |
| |
| Invoked with: 4.0 |
| """ |
| ) |
| |
| |
| def test_custom_caster_destruction(): |
| """Tests that returning a pointer to a type that gets converted with a custom type caster gets |
| destroyed when the function has py::return_value_policy::take_ownership policy applied.""" |
| |
| cstats = m.destruction_tester_cstats() |
| # This one *doesn't* have take_ownership: the pointer should be used but not destroyed: |
| z = m.custom_caster_no_destroy() |
| assert cstats.alive() == 1 and cstats.default_constructions == 1 |
| assert z |
| |
| # take_ownership applied: this constructs a new object, casts it, then destroys it: |
| z = m.custom_caster_destroy() |
| assert z |
| assert cstats.default_constructions == 2 |
| |
| # Same, but with a const pointer return (which should *not* inhibit destruction): |
| z = m.custom_caster_destroy_const() |
| assert z |
| assert cstats.default_constructions == 3 |
| |
| # Make sure we still only have the original object (from ..._no_destroy()) alive: |
| assert cstats.alive() == 1 |