Skip to content

Commit

Permalink
Copying files as-is from pybind/pybind11#2834
Browse files Browse the repository at this point in the history
The PR will be closed. Using this repo as attic.

Original git log:

```
commit 7fe7c96ad47f1e289f23a779566ec9ad3207a0af
Author: Ralf W. Grosse-Kunstleve <[email protected]>
Date:   Mon Mar 8 11:38:40 2021 -0800

    Tracing CpCtor, MvCtor, removing smart-pointer casters, renaming, more comments.

commit 64abe68d7236725825a545f15891e8ee683e45a9
Author: Ralf W. Grosse-Kunstleve <[email protected]>
Date:   Fri Jan 29 14:00:26 2021 -0800

    Adding comment, simplifying naming, cmake addition.

commit 7c1471ea612ed9a72c6559ba515c86ba6255f28f
Author: Ralf W. Grosse-Kunstleve <[email protected]>
Date:   Fri Jan 29 13:42:52 2021 -0800

    Copying files as-is from branch test_unique_ptr_member (PR #2672).
```
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Jul 2, 2021
1 parent 6afa5a2 commit faec6cb
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
128 changes: 128 additions & 0 deletions test_type_caster_bare_interface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copied as-is from https://github.com/pybind/pybind11/pull/2834

// Systematically exercises the detail::type_caster<> interface. This is going a step in the
// direction of an integration test, to ensure multiple components of pybind11 work together
// correctly. It is also useful to show the type_caster<> interface virtually clutter-free.

// The entire type_caster load logic is intentionally omitted. The only purpose of this test is to
// trace the behavior of the `static handle cast()` functions and the type_caster `operator`s.
// Variable names are intentionally terse, to not distract from the more important function
// signatures: valu(e), ref(erence), ptr (pointer), r = rvalue, m = mutable, c = const.

#include "pybind11_tests.h"

#include <string>

namespace pybind11_tests {
namespace type_caster_bare_interface {

struct atyp { // Short for "any type".
std::string trace;
atyp() : trace("default") {}
atyp(atyp const &other) { trace = other.trace + "_CpCtor"; }
atyp(atyp &&other) { trace = other.trace + "_MvCtor"; }
};

// clang-format off

atyp rtrn_valu() { static atyp obj; obj.trace = "valu"; return obj; }
atyp&& rtrn_rref() { static atyp obj; obj.trace = "rref"; return std::move(obj); }
atyp const& rtrn_cref() { static atyp obj; obj.trace = "cref"; return obj; }
atyp& rtrn_mref() { static atyp obj; obj.trace = "mref"; return obj; }
atyp const* rtrn_cptr() { static atyp obj; obj.trace = "cptr"; return &obj; }
atyp* rtrn_mptr() { static atyp obj; obj.trace = "mptr"; return &obj; }

std::string pass_valu(atyp obj) { return "pass_valu:" + obj.trace; }
std::string pass_rref(atyp&& obj) { return "pass_rref:" + obj.trace; }
std::string pass_cref(atyp const& obj) { return "pass_cref:" + obj.trace; }
std::string pass_mref(atyp& obj) { return "pass_mref:" + obj.trace; }
std::string pass_cptr(atyp const* obj) { return "pass_cptr:" + obj->trace; }
std::string pass_mptr(atyp* obj) { return "pass_mptr:" + obj->trace; }

// clang-format on

} // namespace type_caster_bare_interface
} // namespace pybind11_tests

namespace pybind11 {
namespace detail {

using namespace pybind11_tests::type_caster_bare_interface;

template <>
struct type_caster<atyp> {
static constexpr auto name = _<atyp>();

// static handle cast(atyp, ...)
// is redundant (leads to ambiguous overloads).

static handle cast(atyp &&src, return_value_policy /*policy*/, handle /*parent*/) {
return str("cast_rref:" + src.trace).release();
}

static handle cast(atyp const &src, return_value_policy /*policy*/, handle /*parent*/) {
return str("cast_cref:" + src.trace).release();
}

static handle cast(atyp &src, return_value_policy /*policy*/, handle /*parent*/) {
return str("cast_mref:" + src.trace).release();
}

static handle cast(atyp const *src, return_value_policy /*policy*/, handle /*parent*/) {
return str("cast_cptr:" + src->trace).release();
}

static handle cast(atyp *src, return_value_policy /*policy*/, handle /*parent*/) {
return str("cast_mptr:" + src->trace).release();
}

template <typename T_>
using cast_op_type = conditional_t<
std::is_same<remove_reference_t<T_>, atyp const *>::value,
atyp const *,
conditional_t<
std::is_same<remove_reference_t<T_>, atyp *>::value,
atyp *,
conditional_t<
std::is_same<T_, atyp const &>::value,
atyp const &,
conditional_t<std::is_same<T_, atyp &>::value,
atyp &,
conditional_t<std::is_same<T_, atyp &&>::value, atyp &&, atyp>>>>>;

// clang-format off

operator atyp() { static atyp obj; obj.trace = "valu"; return obj; }
operator atyp&&() { static atyp obj; obj.trace = "rref"; return std::move(obj); }
operator atyp const&() { static atyp obj; obj.trace = "cref"; return obj; }
operator atyp&() { static atyp obj; obj.trace = "mref"; return obj; }
operator atyp const*() { static atyp obj; obj.trace = "cptr"; return &obj; }
operator atyp*() { static atyp obj; obj.trace = "mptr"; return &obj; }

// clang-format on

// The entire load logic is intentionally omitted.
bool load(handle /*src*/, bool /*convert*/) { return true; }
};

} // namespace detail
} // namespace pybind11

TEST_SUBMODULE(type_caster_bare_interface, m) {
namespace py = pybind11;
using namespace pybind11_tests::type_caster_bare_interface;

m.def("rtrn_valu", rtrn_valu);
m.def("rtrn_rref", rtrn_rref);
m.def("rtrn_cref", rtrn_cref);
m.def("rtrn_mref", rtrn_mref);
m.def("rtrn_cptr", rtrn_cptr);
m.def("rtrn_mptr", rtrn_mptr);

m.def("pass_valu", pass_valu);
m.def("pass_rref", pass_rref);
m.def("pass_cref", pass_cref);
m.def("pass_mref", pass_mref);
m.def("pass_cptr", pass_cptr);
m.def("pass_mptr", pass_mptr);
}
37 changes: 37 additions & 0 deletions test_type_caster_bare_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Copied as-is from https://github.com/pybind/pybind11/pull/2834
import re

import pytest

from pybind11_tests import type_caster_bare_interface as m


@pytest.mark.parametrize(
"rtrn_f, expected",
[
(m.rtrn_valu, "cast_rref:valu_CpCtor"),
(m.rtrn_rref, "cast_rref:rref"),
(m.rtrn_cref, "cast_cref:cref"),
(m.rtrn_mref, "cast_mref:mref"),
(m.rtrn_cptr, "cast_cptr:cptr"),
(m.rtrn_mptr, "cast_mptr:mptr"),
],
)
def test_cast(rtrn_f, expected):
assert re.match(expected, rtrn_f())


@pytest.mark.parametrize(
"pass_f, expected",
[
(m.pass_valu, "pass_valu:rref_MvCtor"),
(m.pass_rref, "pass_rref:rref"),
(m.pass_cref, "pass_cref:cref"),
(m.pass_mref, "pass_mref:mref"),
(m.pass_cptr, "pass_cptr:cptr"),
(m.pass_mptr, "pass_mptr:mptr"),
],
)
def test_operator(pass_f, expected):
assert re.match(expected, pass_f(None))

0 comments on commit faec6cb

Please sign in to comment.