Skip to content

Commit 7fc253b

Browse files
committed
refactor: kwonly -> kw_only
1 parent b42e9b9 commit 7fc253b

File tree

7 files changed

+61
-60
lines changed

7 files changed

+61
-60
lines changed

docs/advanced/functions.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,14 +378,14 @@ argument in a function definition:
378378
f(1, b=2) # good
379379
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
380380
381-
Pybind11 provides a ``py::kwonly`` object that allows you to implement
381+
Pybind11 provides a ``py::kw_only`` object that allows you to implement
382382
the same behaviour by specifying the object between positional and keyword-only
383383
argument annotations when registering the function:
384384

385385
.. code-block:: cpp
386386
387387
m.def("f", [](int a, int b) { /* ... */ },
388-
py::arg("a"), py::kwonly(), py::arg("b"));
388+
py::arg("a"), py::kw_only(), py::arg("b"));
389389
390390
Note that you currently cannot combine this with a ``py::args`` argument. This
391391
feature does *not* require Python 3 to work.

docs/changelog.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ v2.6.0 (IN PROGRESS)
1111

1212
See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
1313

14-
* Keyword-only argument supported in Python 2 or 3 with ``py::kwonly()``.
14+
* Keyword-only argument supported in Python 2 or 3 with ``py::kw_only()``.
1515
`#2100 <https://github.com/pybind/pybind11/pull/2100>`_
1616

1717
* Positional-only argument supported in Python 2 or 3 with ``py::pos_only()``.

include/pybind11/attr.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ struct function_record {
138138
function_record()
139139
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
140140
is_operator(false), is_method(false),
141-
has_args(false), has_kwargs(false), has_kwonly_args(false) { }
141+
has_args(false), has_kwargs(false), has_kw_only_args(false) { }
142142

143143
/// Function name
144144
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
@@ -185,14 +185,14 @@ struct function_record {
185185
/// True if the function has a '**kwargs' argument
186186
bool has_kwargs : 1;
187187

188-
/// True once a 'py::kwonly' is encountered (any following args are keyword-only)
189-
bool has_kwonly_args : 1;
188+
/// True once a 'py::kw_only' is encountered (any following args are keyword-only)
189+
bool has_kw_only_args : 1;
190190

191191
/// Number of arguments (including py::args and/or py::kwargs, if present)
192192
std::uint16_t nargs;
193193

194194
/// Number of trailing arguments (counted in `nargs`) that are keyword-only
195-
std::uint16_t nargs_kwonly = 0;
195+
std::uint16_t nargs_kw_only = 0;
196196

197197
/// Number of leading arguments (counted in `nargs`) that are positional-only
198198
std::uint16_t nargs_pos_only = 0;
@@ -369,10 +369,10 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
369369
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
370370
};
371371

372-
inline void process_kwonly_arg(const arg &a, function_record *r) {
372+
inline void process_kw_only_arg(const arg &a, function_record *r) {
373373
if (!a.name || strlen(a.name) == 0)
374-
pybind11_fail("arg(): cannot specify an unnamed argument after an kwonly() annotation");
375-
++r->nargs_kwonly;
374+
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
375+
++r->nargs_kw_only;
376376
}
377377

378378
/// Process a keyword argument attribute (*without* a default value)
@@ -382,7 +382,7 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
382382
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
383383
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
384384

385-
if (r->has_kwonly_args) process_kwonly_arg(a, r);
385+
if (r->has_kw_only_args) process_kw_only_arg(a, r);
386386
}
387387
};
388388

@@ -415,14 +415,14 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
415415
}
416416
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
417417

418-
if (r->has_kwonly_args) process_kwonly_arg(a, r);
418+
if (r->has_kw_only_args) process_kw_only_arg(a, r);
419419
}
420420
};
421421

422422
/// Process a keyword-only-arguments-follow pseudo argument
423-
template <> struct process_attribute<kwonly> : process_attribute_default<kwonly> {
424-
static void init(const kwonly &, function_record *r) {
425-
r->has_kwonly_args = true;
423+
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
424+
static void init(const kw_only &, function_record *r) {
425+
r->has_kw_only_args = true;
426426
}
427427
};
428428

include/pybind11/cast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1910,7 +1910,7 @@ struct arg_v : arg {
19101910
/// \ingroup annotations
19111911
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of an
19121912
/// unnamed '*' argument (in Python 3)
1913-
struct kwonly {};
1913+
struct kw_only {};
19141914

19151915
/// \ingroup annotations
19161916
/// Annotation indicating that all previous arguments are positional-only; the is the equivalent of an

include/pybind11/pybind11.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,13 @@ class cpp_function : public function {
187187
process_attributes<Extra...>::init(extra..., rec);
188188

189189
{
190-
constexpr bool has_kwonly_args = any_of<std::is_same<kwonly, Extra>...>::value,
190+
constexpr bool has_kw_only_args = any_of<std::is_same<kw_only, Extra>...>::value,
191191
has_pos_only_args = any_of<std::is_same<pos_only, Extra>...>::value,
192192
has_args = any_of<std::is_same<args, Args>...>::value,
193193
has_arg_annotations = any_of<is_keyword<Extra>...>::value;
194-
static_assert(has_arg_annotations || !has_kwonly_args, "py::kwonly requires the use of argument annotations");
195-
static_assert(has_arg_annotations || !has_pos_only_args, "py::pos_only requires the use of argument annotations (for docstrings and aligning the annotations to the arguments)");
196-
static_assert(!(has_args && has_kwonly_args), "py::kwonly cannot be combined with a py::args argument");
194+
static_assert(has_arg_annotations || !has_kw_only_args, "py::kw_only requires the use of argument annotations");
195+
static_assert(has_arg_annotations || !has_pos_only_args, "py::pos_only requires the use of argument annotations (for docstrings and aligning the annotations to the argument)");
196+
static_assert(!(has_args && has_kw_only_args), "py::kw_only cannot be combined with a py::args argument");
197197
}
198198

199199
/* Generate a readable signature describing the function's arguments and return value types */
@@ -261,7 +261,7 @@ class cpp_function : public function {
261261
continue;
262262
// Separator for keyword-only arguments, placed before the kw
263263
// arguments start
264-
if (rec->nargs_kwonly > 0 && arg_index + rec->nargs_kwonly == args)
264+
if (rec->nargs_kw_only > 0 && arg_index + rec->nargs_kw_only == args)
265265
signature += "*, ";
266266
if (arg_index < rec->args.size() && rec->args[arg_index].name) {
267267
signature += rec->args[arg_index].name;
@@ -522,7 +522,7 @@ class cpp_function : public function {
522522
size_t num_args = func.nargs; // Number of positional arguments that we need
523523
if (func.has_args) --num_args; // (but don't count py::args
524524
if (func.has_kwargs) --num_args; // or py::kwargs)
525-
size_t pos_args = num_args - func.nargs_kwonly;
525+
size_t pos_args = num_args - func.nargs_kw_only;
526526

527527
if (!func.has_args && n_args_in > pos_args)
528528
continue; // Too many positional arguments for this overload

tests/test_kwargs_and_defaults.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,21 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
9595
// m.def("bad_args7", [](py::kwargs, py::kwargs) {});
9696

9797
// test_keyword_only_args
98-
m.def("kwonly_all", [](int i, int j) { return py::make_tuple(i, j); },
99-
py::kwonly(), py::arg("i"), py::arg("j"));
100-
m.def("kwonly_some", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
101-
py::arg(), py::kwonly(), py::arg("j"), py::arg("k"));
102-
m.def("kwonly_with_defaults", [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
103-
py::arg() = 3, "j"_a = 4, py::kwonly(), "k"_a = 5, "z"_a);
104-
m.def("kwonly_mixed", [](int i, int j) { return py::make_tuple(i, j); },
105-
"i"_a, py::kwonly(), "j"_a);
106-
m.def("kwonly_plus_more", [](int i, int j, int k, py::kwargs kwargs) {
98+
m.def("kw_only_all", [](int i, int j) { return py::make_tuple(i, j); },
99+
py::kw_only(), py::arg("i"), py::arg("j"));
100+
m.def("kw_only_some", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
101+
py::arg(), py::kw_only(), py::arg("j"), py::arg("k"));
102+
m.def("kw_only_with_defaults", [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
103+
py::arg() = 3, "j"_a = 4, py::kw_only(), "k"_a = 5, "z"_a);
104+
m.def("kw_only_mixed", [](int i, int j) { return py::make_tuple(i, j); },
105+
"i"_a, py::kw_only(), "j"_a);
106+
m.def("kw_only_plus_more", [](int i, int j, int k, py::kwargs kwargs) {
107107
return py::make_tuple(i, j, k, kwargs); },
108-
py::arg() /* positional */, py::arg("j") = -1 /* both */, py::kwonly(), py::arg("k") /* kw-only */);
108+
py::arg() /* positional */, py::arg("j") = -1 /* both */, py::kw_only(), py::arg("k") /* kw-only */);
109109

110-
m.def("register_invalid_kwonly", [](py::module m) {
111-
m.def("bad_kwonly", [](int i, int j) { return py::make_tuple(i, j); },
112-
py::kwonly(), py::arg() /* invalid unnamed argument */, "j"_a);
110+
m.def("register_invalid_kw_only", [](py::module m) {
111+
m.def("bad_kw_only", [](int i, int j) { return py::make_tuple(i, j); },
112+
py::kw_only(), py::arg() /* invalid unnamed argument */, "j"_a);
113113
});
114114

115115
// test_positional_only_args
@@ -118,15 +118,16 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
118118
m.def("pos_only_mix", [](int i, int j) { return py::make_tuple(i, j); },
119119
py::arg("i"), py::pos_only(), py::arg("j"));
120120
m.def("pos_kw_only_mix", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
121-
py::arg("i"), py::pos_only(), py::arg("j"), py::kwonly(), py::arg("k"));
121+
py::arg("i"), py::pos_only(), py::arg("j"), py::kw_only(), py::arg("k"));
122122
m.def("pos_only_def_mix", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
123123
py::arg("i"), py::arg("j") = 2, py::pos_only(), py::arg("k") = 3);
124124

125+
125126
// These should fail to compile:
126-
// argument annotations are required when using kwonly
127-
// m.def("bad_kwonly1", [](int) {}, py::kwonly());
128-
// can't specify both `py::kwonly` and a `py::args` argument
129-
// m.def("bad_kwonly2", [](int i, py::args) {}, py::kwonly(), "i"_a);
127+
// argument annotations are required when using kw_only
128+
// m.def("bad_kw_only1", [](int) {}, py::kw_only());
129+
// can't specify both `py::kw_only` and a `py::args` argument
130+
// m.def("bad_kw_only2", [](int i, py::args) {}, py::kw_only(), "i"_a);
130131

131132
// test_function_signatures (along with most of the above)
132133
struct KWClass { void foo(int, float) {} };

tests/test_kwargs_and_defaults.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -112,40 +112,40 @@ def test_mixed_args_and_kwargs(msg):
112112

113113

114114
def test_keyword_only_args(msg):
115-
assert m.kwonly_all(i=1, j=2) == (1, 2)
116-
assert m.kwonly_all(j=1, i=2) == (2, 1)
115+
assert m.kw_only_all(i=1, j=2) == (1, 2)
116+
assert m.kw_only_all(j=1, i=2) == (2, 1)
117117

118118
with pytest.raises(TypeError) as excinfo:
119-
assert m.kwonly_all(i=1) == (1,)
119+
assert m.kw_only_all(i=1) == (1,)
120120
assert "incompatible function arguments" in str(excinfo.value)
121121

122122
with pytest.raises(TypeError) as excinfo:
123-
assert m.kwonly_all(1, 2) == (1, 2)
123+
assert m.kw_only_all(1, 2) == (1, 2)
124124
assert "incompatible function arguments" in str(excinfo.value)
125125

126-
assert m.kwonly_some(1, k=3, j=2) == (1, 2, 3)
126+
assert m.kw_only_some(1, k=3, j=2) == (1, 2, 3)
127127

128-
assert m.kwonly_with_defaults(z=8) == (3, 4, 5, 8)
129-
assert m.kwonly_with_defaults(2, z=8) == (2, 4, 5, 8)
130-
assert m.kwonly_with_defaults(2, j=7, k=8, z=9) == (2, 7, 8, 9)
131-
assert m.kwonly_with_defaults(2, 7, z=9, k=8) == (2, 7, 8, 9)
128+
assert m.kw_only_with_defaults(z=8) == (3, 4, 5, 8)
129+
assert m.kw_only_with_defaults(2, z=8) == (2, 4, 5, 8)
130+
assert m.kw_only_with_defaults(2, j=7, k=8, z=9) == (2, 7, 8, 9)
131+
assert m.kw_only_with_defaults(2, 7, z=9, k=8) == (2, 7, 8, 9)
132132

133-
assert m.kwonly_mixed(1, j=2) == (1, 2)
134-
assert m.kwonly_mixed(j=2, i=3) == (3, 2)
135-
assert m.kwonly_mixed(i=2, j=3) == (2, 3)
133+
assert m.kw_only_mixed(1, j=2) == (1, 2)
134+
assert m.kw_only_mixed(j=2, i=3) == (3, 2)
135+
assert m.kw_only_mixed(i=2, j=3) == (2, 3)
136136

137-
assert m.kwonly_plus_more(4, 5, k=6, extra=7) == (4, 5, 6, {'extra': 7})
138-
assert m.kwonly_plus_more(3, k=5, j=4, extra=6) == (3, 4, 5, {'extra': 6})
139-
assert m.kwonly_plus_more(2, k=3, extra=4) == (2, -1, 3, {'extra': 4})
137+
assert m.kw_only_plus_more(4, 5, k=6, extra=7) == (4, 5, 6, {'extra': 7})
138+
assert m.kw_only_plus_more(3, k=5, j=4, extra=6) == (3, 4, 5, {'extra': 6})
139+
assert m.kw_only_plus_more(2, k=3, extra=4) == (2, -1, 3, {'extra': 4})
140140

141141
with pytest.raises(TypeError) as excinfo:
142-
assert m.kwonly_mixed(i=1) == (1,)
142+
assert m.kw_only_mixed(i=1) == (1,)
143143
assert "incompatible function arguments" in str(excinfo.value)
144144

145145
with pytest.raises(RuntimeError) as excinfo:
146-
m.register_invalid_kwonly(m)
146+
m.register_invalid_kw_only(m)
147147
assert msg(excinfo.value) == """
148-
arg(): cannot specify an unnamed argument after an kwonly() annotation
148+
arg(): cannot specify an unnamed argument after an kw_only() annotation
149149
"""
150150

151151

@@ -190,8 +190,8 @@ def test_positional_only_args(msg):
190190

191191

192192
def test_signatures():
193-
assert "kwonly_all(*, i: int, j: int) -> tuple\n" == m.kwonly_all.__doc__
194-
assert "kwonly_mixed(i: int, *, j: int) -> tuple\n" == m.kwonly_mixed.__doc__
193+
assert "kw_only_all(*, i: int, j: int) -> tuple\n" == m.kw_only_all.__doc__
194+
assert "kw_only_mixed(i: int, *, j: int) -> tuple\n" == m.kw_only_mixed.__doc__
195195
assert "pos_only_all(i: int, j: int, /) -> tuple\n" == m.pos_only_all.__doc__
196196
assert "pos_only_mix(i: int, /, j: int) -> tuple\n" == m.pos_only_mix.__doc__
197197
assert "pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple\n" == m.pos_kw_only_mix.__doc__

0 commit comments

Comments
 (0)