Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
a86ac538
Commit
a86ac538
authored
Apr 14, 2020
by
Sebastian Koslowski
Committed by
Wenzel Jakob
Apr 26, 2020
Browse files
rename args_kw_only to kwonly
parent
be0d8045
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
26 additions
and
26 deletions
+26
-26
docs/advanced/functions.rst
docs/advanced/functions.rst
+2
-2
include/pybind11/attr.h
include/pybind11/attr.h
+9
-9
include/pybind11/cast.h
include/pybind11/cast.h
+1
-1
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+3
-3
tests/test_kwargs_and_defaults.cpp
tests/test_kwargs_and_defaults.cpp
+10
-10
tests/test_kwargs_and_defaults.py
tests/test_kwargs_and_defaults.py
+1
-1
No files found.
docs/advanced/functions.rst
View file @
a86ac538
...
...
@@ -378,14 +378,14 @@ argument in a function definition:
f(1, b=2) # good
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
argument annotations when registering the function:
.. code-block:: cpp
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.
This feature does *not* require Python 3 to work.
...
...
include/pybind11/attr.h
View file @
a86ac538
...
...
@@ -138,7 +138,7 @@ struct function_record {
function_record
()
:
is_constructor
(
false
),
is_new_style_constructor
(
false
),
is_stateless
(
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
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
bool
has_kwargs
:
1
;
/// True once a 'py::
args_
kw
_
only' is encountered (any following args are keyword-only)
bool
has_kw
_
only_args
:
1
;
/// True once a 'py::kwonly' is encountered (any following args are keyword-only)
bool
has_kwonly_args
:
1
;
/// Number of arguments (including py::args and/or py::kwargs, if present)
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
)
{
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
;
}
...
...
@@ -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
(
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
);
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
template
<
>
struct
process_attribute
<
args_
kw
_
only
>
:
process_attribute_default
<
args_
kw
_
only
>
{
static
void
init
(
const
args_
kw
_
only
&
,
function_record
*
r
)
{
r
->
has_kw
_
only_args
=
true
;
template
<
>
struct
process_attribute
<
kwonly
>
:
process_attribute_default
<
kwonly
>
{
static
void
init
(
const
kwonly
&
,
function_record
*
r
)
{
r
->
has_kwonly_args
=
true
;
}
};
...
...
include/pybind11/cast.h
View file @
a86ac538
...
...
@@ -1890,7 +1890,7 @@ public:
/// \ingroup annotations
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of an
/// unnamed '*' argument (in Python 3)
struct
args_
kw
_
only
{};
struct
kwonly
{};
template
<
typename
T
>
arg_v
arg
::
operator
=
(
T
&&
value
)
const
{
return
{
std
::
move
(
*
this
),
std
::
forward
<
T
>
(
value
)};
}
...
...
include/pybind11/pybind11.h
View file @
a86ac538
...
...
@@ -169,11 +169,11 @@ protected:
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_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_args
&&
has_kw
_
only_args
),
"py::
args_
kw
_
only cannot be combined with a py::args argument"
);
static_assert
(
has_arg_annotations
||
!
has_kwonly_args
,
"py::kwonly requires the use of argument annotations"
);
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 */
...
...
tests/test_kwargs_and_defaults.cpp
View file @
a86ac538
...
...
@@ -96,27 +96,27 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
// test_keyword_only_args
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
);
},
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
);
},
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
);
},
"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
)
{
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
(
"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:
// argument annotations are required when using
args_
kw
_
only
// m.def("bad_kwonly1", [](int) {}, py::
args_
kw
_
only());
// can't specify both `py::
args_
kw
_
only` and a `py::args` argument
// m.def("bad_kwonly2", [](int i, py::args) {}, py::
args_
kw
_
only(), "i"_a);
// argument annotations are required when using kwonly
// m.def("bad_kwonly1", [](int) {}, py::kwonly());
// can't specify both `py::kwonly` and a `py::args` argument
// m.def("bad_kwonly2", [](int i, py::args) {}, py::kwonly(), "i"_a);
// test_function_signatures (along with most of the above)
struct
KWClass
{
void
foo
(
int
,
float
)
{}
};
...
...
tests/test_kwargs_and_defaults.py
View file @
a86ac538
...
...
@@ -141,7 +141,7 @@ def test_keyword_only_args(msg):
with
pytest
.
raises
(
RuntimeError
)
as
excinfo
:
m
.
register_invalid_kwonly
(
m
)
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
"""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment