mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
rename args_kw_only to kwonly
This commit is contained in:
parent
be0d804523
commit
a86ac538f5
@ -378,14 +378,14 @@ argument in a function definition:
|
|||||||
f(1, b=2) # good
|
f(1, b=2) # good
|
||||||
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
|
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
|
||||||
|
|
||||||
Pybind11 provides a ``py::args_kw_only`` object that allows you to implement
|
Pybind11 provides a ``py::kwonly`` object that allows you to implement
|
||||||
the same behaviour by specifying the object between positional and keyword-only
|
the same behaviour by specifying the object between positional and keyword-only
|
||||||
argument annotations when registering the function:
|
argument annotations when registering the function:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
m.def("f", [](int a, int b) { /* ... */ },
|
m.def("f", [](int a, int b) { /* ... */ },
|
||||||
py::arg("a"), py::args_kw_only(), py::arg("b"));
|
py::arg("a"), py::kwonly(), py::arg("b"));
|
||||||
|
|
||||||
Note that, as in Python, you cannot combine this with a ``py::args`` argument.
|
Note that, as in Python, you cannot combine this with a ``py::args`` argument.
|
||||||
This feature does *not* require Python 3 to work.
|
This feature does *not* require Python 3 to work.
|
||||||
|
@ -138,7 +138,7 @@ struct function_record {
|
|||||||
function_record()
|
function_record()
|
||||||
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
|
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
|
||||||
is_operator(false), is_method(false),
|
is_operator(false), is_method(false),
|
||||||
has_args(false), has_kwargs(false), has_kw_only_args(false) { }
|
has_args(false), has_kwargs(false), has_kwonly_args(false) { }
|
||||||
|
|
||||||
/// Function name
|
/// Function name
|
||||||
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
||||||
@ -185,8 +185,8 @@ struct function_record {
|
|||||||
/// True if the function has a '**kwargs' argument
|
/// True if the function has a '**kwargs' argument
|
||||||
bool has_kwargs : 1;
|
bool has_kwargs : 1;
|
||||||
|
|
||||||
/// True once a 'py::args_kw_only' is encountered (any following args are keyword-only)
|
/// True once a 'py::kwonly' is encountered (any following args are keyword-only)
|
||||||
bool has_kw_only_args : 1;
|
bool has_kwonly_args : 1;
|
||||||
|
|
||||||
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
||||||
std::uint16_t nargs;
|
std::uint16_t nargs;
|
||||||
@ -368,7 +368,7 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
|
|||||||
|
|
||||||
inline void process_kwonly_arg(const arg &a, function_record *r) {
|
inline void process_kwonly_arg(const arg &a, function_record *r) {
|
||||||
if (!a.name || strlen(a.name) == 0)
|
if (!a.name || strlen(a.name) == 0)
|
||||||
pybind11_fail("arg(): cannot specify an unnamed argument after an args_kw_only() annotation");
|
pybind11_fail("arg(): cannot specify an unnamed argument after an kwonly() annotation");
|
||||||
++r->nargs_kwonly;
|
++r->nargs_kwonly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
|||||||
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
|
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
|
||||||
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
|
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
|
||||||
|
|
||||||
if (r->has_kw_only_args) process_kwonly_arg(a, r);
|
if (r->has_kwonly_args) process_kwonly_arg(a, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -412,14 +412,14 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
|||||||
}
|
}
|
||||||
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
|
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
|
||||||
|
|
||||||
if (r->has_kw_only_args) process_kwonly_arg(a, r);
|
if (r->has_kwonly_args) process_kwonly_arg(a, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Process a keyword-only-arguments-follow pseudo argument
|
/// Process a keyword-only-arguments-follow pseudo argument
|
||||||
template <> struct process_attribute<args_kw_only> : process_attribute_default<args_kw_only> {
|
template <> struct process_attribute<kwonly> : process_attribute_default<kwonly> {
|
||||||
static void init(const args_kw_only &, function_record *r) {
|
static void init(const kwonly &, function_record *r) {
|
||||||
r->has_kw_only_args = true;
|
r->has_kwonly_args = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1890,7 +1890,7 @@ public:
|
|||||||
/// \ingroup annotations
|
/// \ingroup annotations
|
||||||
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of an
|
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of an
|
||||||
/// unnamed '*' argument (in Python 3)
|
/// unnamed '*' argument (in Python 3)
|
||||||
struct args_kw_only {};
|
struct kwonly {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
arg_v arg::operator=(T &&value) const { return {std::move(*this), std::forward<T>(value)}; }
|
arg_v arg::operator=(T &&value) const { return {std::move(*this), std::forward<T>(value)}; }
|
||||||
|
@ -169,11 +169,11 @@ protected:
|
|||||||
process_attributes<Extra...>::init(extra..., rec);
|
process_attributes<Extra...>::init(extra..., rec);
|
||||||
|
|
||||||
{
|
{
|
||||||
constexpr bool has_kw_only_args = any_of<std::is_same<args_kw_only, Extra>...>::value,
|
constexpr bool has_kwonly_args = any_of<std::is_same<kwonly, Extra>...>::value,
|
||||||
has_args = any_of<std::is_same<args, Args>...>::value,
|
has_args = any_of<std::is_same<args, Args>...>::value,
|
||||||
has_arg_annotations = any_of<is_keyword<Extra>...>::value;
|
has_arg_annotations = any_of<is_keyword<Extra>...>::value;
|
||||||
static_assert(has_arg_annotations || !has_kw_only_args, "py::args_kw_only requires the use of argument annotations");
|
static_assert(has_arg_annotations || !has_kwonly_args, "py::kwonly requires the use of argument annotations");
|
||||||
static_assert(!(has_args && has_kw_only_args), "py::args_kw_only cannot be combined with a py::args argument");
|
static_assert(!(has_args && has_kwonly_args), "py::kwonly cannot be combined with a py::args argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a readable signature describing the function's arguments and return value types */
|
/* Generate a readable signature describing the function's arguments and return value types */
|
||||||
|
@ -96,27 +96,27 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
|||||||
|
|
||||||
// test_keyword_only_args
|
// test_keyword_only_args
|
||||||
m.def("kwonly_all", [](int i, int j) { return py::make_tuple(i, j); },
|
m.def("kwonly_all", [](int i, int j) { return py::make_tuple(i, j); },
|
||||||
py::args_kw_only(), py::arg("i"), py::arg("j"));
|
py::kwonly(), py::arg("i"), py::arg("j"));
|
||||||
m.def("kwonly_some", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
|
m.def("kwonly_some", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
|
||||||
py::arg(), py::args_kw_only(), py::arg("j"), py::arg("k"));
|
py::arg(), py::kwonly(), py::arg("j"), py::arg("k"));
|
||||||
m.def("kwonly_with_defaults", [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
|
m.def("kwonly_with_defaults", [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
|
||||||
py::arg() = 3, "j"_a = 4, py::args_kw_only(), "k"_a = 5, "z"_a);
|
py::arg() = 3, "j"_a = 4, py::kwonly(), "k"_a = 5, "z"_a);
|
||||||
m.def("kwonly_mixed", [](int i, int j) { return py::make_tuple(i, j); },
|
m.def("kwonly_mixed", [](int i, int j) { return py::make_tuple(i, j); },
|
||||||
"i"_a, py::args_kw_only(), "j"_a);
|
"i"_a, py::kwonly(), "j"_a);
|
||||||
m.def("kwonly_plus_more", [](int i, int j, int k, py::kwargs kwargs) {
|
m.def("kwonly_plus_more", [](int i, int j, int k, py::kwargs kwargs) {
|
||||||
return py::make_tuple(i, j, k, kwargs); },
|
return py::make_tuple(i, j, k, kwargs); },
|
||||||
py::arg() /* positional */, py::arg("j") = -1 /* both */, py::args_kw_only(), py::arg("k") /* kw-only */);
|
py::arg() /* positional */, py::arg("j") = -1 /* both */, py::kwonly(), py::arg("k") /* kw-only */);
|
||||||
|
|
||||||
m.def("register_invalid_kwonly", [](py::module m) {
|
m.def("register_invalid_kwonly", [](py::module m) {
|
||||||
m.def("bad_kwonly", [](int i, int j) { return py::make_tuple(i, j); },
|
m.def("bad_kwonly", [](int i, int j) { return py::make_tuple(i, j); },
|
||||||
py::args_kw_only(), py::arg() /* invalid unnamed argument */, "j"_a);
|
py::kwonly(), py::arg() /* invalid unnamed argument */, "j"_a);
|
||||||
});
|
});
|
||||||
|
|
||||||
// These should fail to compile:
|
// These should fail to compile:
|
||||||
// argument annotations are required when using args_kw_only
|
// argument annotations are required when using kwonly
|
||||||
// m.def("bad_kwonly1", [](int) {}, py::args_kw_only());
|
// m.def("bad_kwonly1", [](int) {}, py::kwonly());
|
||||||
// can't specify both `py::args_kw_only` and a `py::args` argument
|
// can't specify both `py::kwonly` and a `py::args` argument
|
||||||
// m.def("bad_kwonly2", [](int i, py::args) {}, py::args_kw_only(), "i"_a);
|
// m.def("bad_kwonly2", [](int i, py::args) {}, py::kwonly(), "i"_a);
|
||||||
|
|
||||||
// test_function_signatures (along with most of the above)
|
// test_function_signatures (along with most of the above)
|
||||||
struct KWClass { void foo(int, float) {} };
|
struct KWClass { void foo(int, float) {} };
|
||||||
|
@ -141,7 +141,7 @@ def test_keyword_only_args(msg):
|
|||||||
with pytest.raises(RuntimeError) as excinfo:
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
m.register_invalid_kwonly(m)
|
m.register_invalid_kwonly(m)
|
||||||
assert msg(excinfo.value) == """
|
assert msg(excinfo.value) == """
|
||||||
arg(): cannot specify an unnamed argument after an args_kw_only() annotation
|
arg(): cannot specify an unnamed argument after an kwonly() annotation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user