Fix py::kw_only when used before the first arg of a method (#3488)

* Fix py::kw_only when used before the first arg of a method

The implicit space for the `self` argument isn't added until we hit the
first argument, but this wasn't being done for kw_only or pos_only, and
so a kw_only before the first argument would break.

This fixes it by properly checking whether we need to add the self arg.

(The pos_only issue here was extremely mild -- you didn't get the `/` in
the docstring, but AFAICT it has no other effect since there are no
meaningful arguments before it anyway).

* Style changes

- rename check_have_self_arg -> append_self_arg_if_needed

- move the argument name inline comments before the args instead of
  after
This commit is contained in:
Jason Rhinelander
2021-11-20 20:01:57 -04:00
committed by GitHub
parent 56322dafc9
commit 673b4be3d7
3 changed files with 47 additions and 3 deletions

View File

@@ -167,4 +167,21 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
"class_default_argument",
[](py::object a) { return py::repr(std::move(a)); },
"a"_a = py::module_::import("decimal").attr("Decimal"));
// Initial implementation of kw_only was broken when used on a method/constructor before any
// other arguments
// https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
struct first_arg_kw_only {};
py::class_<first_arg_kw_only>(m, "first_arg_kw_only")
.def(py::init([](int) { return first_arg_kw_only(); }),
py::kw_only(), // This being before any args was broken
py::arg("i") = 0)
.def("method", [](first_arg_kw_only&, int, int) {},
py::kw_only(), // and likewise here
py::arg("i") = 1, py::arg("j") = 2)
// Closely related: pos_only marker didn't show up properly when it was before any other
// arguments (although that is fairly useless in practice).
.def("pos_only", [](first_arg_kw_only&, int, int) {},
py::pos_only{}, py::arg("i"), py::arg("j"));
}