Skip to content

Commit

Permalink
Add test_cases_for_stubgen
Browse files Browse the repository at this point in the history
Material to inform python/mypy#16306
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Nov 14, 2023
1 parent 0b98433 commit 781304e
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ set(PYBIND11_TEST_FILES
test_builtin_casters
test_call_policies
test_callbacks
test_cases_for_stubgen
test_chrono
test_class
test_const_name
Expand Down
72 changes: 72 additions & 0 deletions tests/test_cases_for_stubgen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "pybind11/stl_bind.h"
#include "pybind11_tests.h"

#include <map>

namespace test_cases_for_stubgen {

struct user_type {
bool operator<(const user_type &) const { return false; }
};

struct minimal_caster {
static constexpr auto name = py::detail::const_name<user_type>();

static py::handle
cast(user_type const & /*src*/, py::return_value_policy /*policy*/, py::handle /*parent*/) {
return py::none().release();
}

// Maximizing simplicity. This will go terribly wrong for other arg types.
template <typename>
using cast_op_type = const user_type &;

// NOLINTNEXTLINE(google-explicit-constructor)
operator user_type const &() {
static user_type obj;
return obj;
}

bool load(py::handle /*src*/, bool /*convert*/) { return false; }
};

} // namespace test_cases_for_stubgen

namespace pybind11 {
namespace detail {

template <>
struct type_caster<test_cases_for_stubgen::user_type> : test_cases_for_stubgen::minimal_caster {};

} // namespace detail
} // namespace pybind11

TEST_SUBMODULE(cases_for_stubgen, m) {
using namespace test_cases_for_stubgen;

m.def("pass_user_type", [](const user_type &) {});
m.def("return_user_type", []() { return user_type(); });

py::bind_map<std::map<int, user_type>>(m, "MapIntUserType");
py::bind_map<std::map<user_type, int>>(m, "MapUserTypeInt");

#define MAP_TYPE(MapTypePythonName, ...) \
py::class_<__VA_ARGS__>(m, MapTypePythonName) \
.def( \
"keys", \
[](const __VA_ARGS__ &v) { return py::make_key_iterator(v); }, \
py::keep_alive<0, 1>()) \
.def( \
"values", \
[](const __VA_ARGS__ &v) { return py::make_value_iterator(v); }, \
py::keep_alive<0, 1>()) \
.def( \
"__iter__", \
[](const __VA_ARGS__ &v) { return py::make_iterator(v.begin(), v.end()); }, \
py::keep_alive<0, 1>())

MAP_TYPE("MapFloatUserType", std::map<float, user_type>);
MAP_TYPE("MapUserTypeFloat", std::map<user_type, float>);

#undef MAP_TYPE
}
68 changes: 68 additions & 0 deletions tests/test_cases_for_stubgen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import pytest

from pybind11_tests import cases_for_stubgen as m


@pytest.mark.parametrize(
("docstring", "expected"),
[
(
m.pass_user_type.__doc__,
'pass_user_type(arg0: Annotated[Any, "test_cases_for_stubgen::user_type"]) -> None\n',
),
(
m.return_user_type.__doc__,
'return_user_type() -> Annotated[Any, "test_cases_for_stubgen::user_type"]\n',
),
(
m.MapIntUserType.keys.__doc__,
"keys(self: pybind11_tests.cases_for_stubgen.MapIntUserType) -> pybind11_tests.cases_for_stubgen.KeysView[int]\n",
),
(
m.MapIntUserType.values.__doc__,
"values(self: pybind11_tests.cases_for_stubgen.MapIntUserType) -> pybind11_tests.cases_for_stubgen.ValuesView[test_cases_for_stubgen::user_type]\n",
),
(
m.MapIntUserType.items.__doc__,
"items(self: pybind11_tests.cases_for_stubgen.MapIntUserType) -> pybind11_tests.cases_for_stubgen.ItemsView[int, test_cases_for_stubgen::user_type]\n",
),
(
m.MapUserTypeInt.keys.__doc__,
"keys(self: pybind11_tests.cases_for_stubgen.MapUserTypeInt) -> pybind11_tests.cases_for_stubgen.KeysView[test_cases_for_stubgen::user_type]\n",
),
(
m.MapUserTypeInt.values.__doc__,
"values(self: pybind11_tests.cases_for_stubgen.MapUserTypeInt) -> pybind11_tests.cases_for_stubgen.ValuesView[int]\n",
),
(
m.MapUserTypeInt.items.__doc__,
"items(self: pybind11_tests.cases_for_stubgen.MapUserTypeInt) -> pybind11_tests.cases_for_stubgen.ItemsView[test_cases_for_stubgen::user_type, int]\n",
),
(
m.MapFloatUserType.keys.__doc__,
"keys(self: pybind11_tests.cases_for_stubgen.MapFloatUserType) -> Iterator[float]\n",
),
(
m.MapFloatUserType.values.__doc__,
'values(self: pybind11_tests.cases_for_stubgen.MapFloatUserType) -> Iterator[Annotated[Any, "test_cases_for_stubgen::user_type"]]\n',
),
(
m.MapFloatUserType.__iter__.__doc__,
'__iter__(self: pybind11_tests.cases_for_stubgen.MapFloatUserType) -> Iterator[tuple[float, Annotated[Any, "test_cases_for_stubgen::user_type"]]]\n',
),
(
m.MapUserTypeFloat.keys.__doc__,
'keys(self: pybind11_tests.cases_for_stubgen.MapUserTypeFloat) -> Iterator[Annotated[Any, "test_cases_for_stubgen::user_type"]]\n',
),
(
m.MapUserTypeFloat.values.__doc__,
"values(self: pybind11_tests.cases_for_stubgen.MapUserTypeFloat) -> Iterator[float]\n",
),
(
m.MapUserTypeFloat.__iter__.__doc__,
'__iter__(self: pybind11_tests.cases_for_stubgen.MapUserTypeFloat) -> Iterator[tuple[Annotated[Any, "test_cases_for_stubgen::user_type"], float]]\n',
),
],
)
def test_docstring(docstring, expected):
assert docstring == expected

0 comments on commit 781304e

Please sign in to comment.