Skip to content

Commit 07c7c7d

Browse files
committed
test: add docstring tests for generated dunder methods
1 parent 14ef500 commit 07c7c7d

File tree

4 files changed

+102
-5
lines changed

4 files changed

+102
-5
lines changed

include/pybind11/pybind11.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,6 +2481,7 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&...extra) {
24812481
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
24822482
},
24832483
std::forward<Extra>(extra)...,
2484+
pos_only(),
24842485
Policy);
24852486
}
24862487

tests/test_enum.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# ruff: noqa: SIM201 SIM300 SIM202
22
from __future__ import annotations
33

4+
import re
5+
46
import pytest
57

68
import env # noqa: F401
@@ -271,3 +273,61 @@ def test_docstring_signatures():
271273
def test_str_signature():
272274
for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
273275
assert enum_type.__str__.__doc__.startswith("__str__")
276+
277+
278+
def test_generated_dunder_methods_pos_only():
279+
for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
280+
for binary_op in [
281+
"__eq__",
282+
"__ne__",
283+
"__ge__",
284+
"__gt__",
285+
"__lt__",
286+
"__le__",
287+
"__and__",
288+
"__rand__",
289+
"__or__",
290+
"__ror__",
291+
"__xor__",
292+
"__rxor__",
293+
"__rxor__",
294+
]:
295+
method = getattr(enum_type, binary_op, None)
296+
if method is not None:
297+
assert (
298+
re.match(
299+
rf"^{binary_op}\(self: [\w\.]+, other: [\w\.]+, /\)",
300+
method.__doc__,
301+
)
302+
is not None
303+
)
304+
for unary_op in [
305+
"__int__",
306+
"__index__",
307+
"__hash__",
308+
"__str__",
309+
"__repr__",
310+
]:
311+
method = getattr(enum_type, unary_op, None)
312+
if method is not None:
313+
assert (
314+
re.match(
315+
rf"^{unary_op}\(self: [\w\.]+, /\)",
316+
method.__doc__,
317+
)
318+
is not None
319+
)
320+
assert (
321+
re.match(
322+
r"^__getstate__\(self: [\w\.]+, /\)",
323+
enum_type.__getstate__.__doc__,
324+
)
325+
is not None
326+
)
327+
assert (
328+
re.match(
329+
r"^__setstate__\(self: [\w\.]+, state: [\w\.]+, /\)",
330+
enum_type.__getstate__.__doc__,
331+
)
332+
is not None
333+
)

tests/test_pickling.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,19 @@ def test_roundtrip_simple_cpp_derived():
9393
# Issue #3062: pickleable base C++ classes can incur object slicing
9494
# if derived typeid is not registered with pybind11
9595
assert not m.check_dynamic_cast_SimpleCppDerived(p2)
96+
97+
98+
def test_new_style_pickle_getstate_pos_only():
99+
assert (
100+
re.match(
101+
r"^__getstate__\(self: [\w\.]+, /\)", m.PickleableNew.__getstate__.__doc__
102+
)
103+
is not None
104+
)
105+
assert (
106+
re.match(
107+
r"^__getstate__\(self: [\w\.]+, /\)",
108+
m.PickleableWithDictNew.__getstate__.__doc__,
109+
)
110+
is not None
111+
)

tests/test_sequences_and_iterators.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import re
4+
35
import pytest
46
from pytest import approx # noqa: PT013
57

@@ -253,16 +255,12 @@ def bad_next_call():
253255

254256
def test_iterator_passthrough():
255257
"""#181: iterator passthrough did not compile"""
256-
from pybind11_tests.sequences_and_iterators import iterator_passthrough
257-
258258
values = [3, 5, 7, 9, 11, 13, 15]
259-
assert list(iterator_passthrough(iter(values))) == values
259+
assert list(m.iterator_passthrough(iter(values))) == values
260260

261261

262262
def test_iterator_rvp():
263263
"""#388: Can't make iterators via make_iterator() with different r/v policies"""
264-
import pybind11_tests.sequences_and_iterators as m
265-
266264
assert list(m.make_iterator_1()) == [1, 2, 3]
267265
assert list(m.make_iterator_2()) == [1, 2, 3]
268266
assert not isinstance(m.make_iterator_1(), type(m.make_iterator_2()))
@@ -274,3 +272,25 @@ def test_carray_iterator():
274272
arr_h = m.CArrayHolder(*args_gt)
275273
args = list(arr_h)
276274
assert args_gt == args
275+
276+
277+
def test_generated_dunder_methods_pos_only():
278+
string_map = m.StringMap({"hi": "bye", "black": "white"})
279+
for it in (
280+
m.make_iterator_1(),
281+
m.make_iterator_2(),
282+
m.iterator_passthrough(iter([3, 5, 7])),
283+
iter(m.Sequence(5)),
284+
iter(string_map),
285+
string_map.items(),
286+
string_map.values(),
287+
iter(m.CArrayHolder(*[float(i) for i in range(3)])),
288+
):
289+
assert (
290+
re.match(r"^__iter__\(self: [\w\.]+, /\)", type(it).__iter__.__doc__)
291+
is not None
292+
)
293+
assert (
294+
re.match(r"^__next__\(self: [\w\.]+, /\)", type(it).__next__.__doc__)
295+
is not None
296+
)

0 commit comments

Comments
 (0)