Skip to content

Commit 781304e

Browse files
committed
Add test_cases_for_stubgen
Material to inform python/mypy#16306
1 parent 0b98433 commit 781304e

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ set(PYBIND11_TEST_FILES
117117
test_builtin_casters
118118
test_call_policies
119119
test_callbacks
120+
test_cases_for_stubgen
120121
test_chrono
121122
test_class
122123
test_const_name

tests/test_cases_for_stubgen.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "pybind11/stl_bind.h"
2+
#include "pybind11_tests.h"
3+
4+
#include <map>
5+
6+
namespace test_cases_for_stubgen {
7+
8+
struct user_type {
9+
bool operator<(const user_type &) const { return false; }
10+
};
11+
12+
struct minimal_caster {
13+
static constexpr auto name = py::detail::const_name<user_type>();
14+
15+
static py::handle
16+
cast(user_type const & /*src*/, py::return_value_policy /*policy*/, py::handle /*parent*/) {
17+
return py::none().release();
18+
}
19+
20+
// Maximizing simplicity. This will go terribly wrong for other arg types.
21+
template <typename>
22+
using cast_op_type = const user_type &;
23+
24+
// NOLINTNEXTLINE(google-explicit-constructor)
25+
operator user_type const &() {
26+
static user_type obj;
27+
return obj;
28+
}
29+
30+
bool load(py::handle /*src*/, bool /*convert*/) { return false; }
31+
};
32+
33+
} // namespace test_cases_for_stubgen
34+
35+
namespace pybind11 {
36+
namespace detail {
37+
38+
template <>
39+
struct type_caster<test_cases_for_stubgen::user_type> : test_cases_for_stubgen::minimal_caster {};
40+
41+
} // namespace detail
42+
} // namespace pybind11
43+
44+
TEST_SUBMODULE(cases_for_stubgen, m) {
45+
using namespace test_cases_for_stubgen;
46+
47+
m.def("pass_user_type", [](const user_type &) {});
48+
m.def("return_user_type", []() { return user_type(); });
49+
50+
py::bind_map<std::map<int, user_type>>(m, "MapIntUserType");
51+
py::bind_map<std::map<user_type, int>>(m, "MapUserTypeInt");
52+
53+
#define MAP_TYPE(MapTypePythonName, ...) \
54+
py::class_<__VA_ARGS__>(m, MapTypePythonName) \
55+
.def( \
56+
"keys", \
57+
[](const __VA_ARGS__ &v) { return py::make_key_iterator(v); }, \
58+
py::keep_alive<0, 1>()) \
59+
.def( \
60+
"values", \
61+
[](const __VA_ARGS__ &v) { return py::make_value_iterator(v); }, \
62+
py::keep_alive<0, 1>()) \
63+
.def( \
64+
"__iter__", \
65+
[](const __VA_ARGS__ &v) { return py::make_iterator(v.begin(), v.end()); }, \
66+
py::keep_alive<0, 1>())
67+
68+
MAP_TYPE("MapFloatUserType", std::map<float, user_type>);
69+
MAP_TYPE("MapUserTypeFloat", std::map<user_type, float>);
70+
71+
#undef MAP_TYPE
72+
}

tests/test_cases_for_stubgen.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import pytest
2+
3+
from pybind11_tests import cases_for_stubgen as m
4+
5+
6+
@pytest.mark.parametrize(
7+
("docstring", "expected"),
8+
[
9+
(
10+
m.pass_user_type.__doc__,
11+
'pass_user_type(arg0: Annotated[Any, "test_cases_for_stubgen::user_type"]) -> None\n',
12+
),
13+
(
14+
m.return_user_type.__doc__,
15+
'return_user_type() -> Annotated[Any, "test_cases_for_stubgen::user_type"]\n',
16+
),
17+
(
18+
m.MapIntUserType.keys.__doc__,
19+
"keys(self: pybind11_tests.cases_for_stubgen.MapIntUserType) -> pybind11_tests.cases_for_stubgen.KeysView[int]\n",
20+
),
21+
(
22+
m.MapIntUserType.values.__doc__,
23+
"values(self: pybind11_tests.cases_for_stubgen.MapIntUserType) -> pybind11_tests.cases_for_stubgen.ValuesView[test_cases_for_stubgen::user_type]\n",
24+
),
25+
(
26+
m.MapIntUserType.items.__doc__,
27+
"items(self: pybind11_tests.cases_for_stubgen.MapIntUserType) -> pybind11_tests.cases_for_stubgen.ItemsView[int, test_cases_for_stubgen::user_type]\n",
28+
),
29+
(
30+
m.MapUserTypeInt.keys.__doc__,
31+
"keys(self: pybind11_tests.cases_for_stubgen.MapUserTypeInt) -> pybind11_tests.cases_for_stubgen.KeysView[test_cases_for_stubgen::user_type]\n",
32+
),
33+
(
34+
m.MapUserTypeInt.values.__doc__,
35+
"values(self: pybind11_tests.cases_for_stubgen.MapUserTypeInt) -> pybind11_tests.cases_for_stubgen.ValuesView[int]\n",
36+
),
37+
(
38+
m.MapUserTypeInt.items.__doc__,
39+
"items(self: pybind11_tests.cases_for_stubgen.MapUserTypeInt) -> pybind11_tests.cases_for_stubgen.ItemsView[test_cases_for_stubgen::user_type, int]\n",
40+
),
41+
(
42+
m.MapFloatUserType.keys.__doc__,
43+
"keys(self: pybind11_tests.cases_for_stubgen.MapFloatUserType) -> Iterator[float]\n",
44+
),
45+
(
46+
m.MapFloatUserType.values.__doc__,
47+
'values(self: pybind11_tests.cases_for_stubgen.MapFloatUserType) -> Iterator[Annotated[Any, "test_cases_for_stubgen::user_type"]]\n',
48+
),
49+
(
50+
m.MapFloatUserType.__iter__.__doc__,
51+
'__iter__(self: pybind11_tests.cases_for_stubgen.MapFloatUserType) -> Iterator[tuple[float, Annotated[Any, "test_cases_for_stubgen::user_type"]]]\n',
52+
),
53+
(
54+
m.MapUserTypeFloat.keys.__doc__,
55+
'keys(self: pybind11_tests.cases_for_stubgen.MapUserTypeFloat) -> Iterator[Annotated[Any, "test_cases_for_stubgen::user_type"]]\n',
56+
),
57+
(
58+
m.MapUserTypeFloat.values.__doc__,
59+
"values(self: pybind11_tests.cases_for_stubgen.MapUserTypeFloat) -> Iterator[float]\n",
60+
),
61+
(
62+
m.MapUserTypeFloat.__iter__.__doc__,
63+
'__iter__(self: pybind11_tests.cases_for_stubgen.MapUserTypeFloat) -> Iterator[tuple[Annotated[Any, "test_cases_for_stubgen::user_type"], float]]\n',
64+
),
65+
],
66+
)
67+
def test_docstring(docstring, expected):
68+
assert docstring == expected

0 commit comments

Comments
 (0)