Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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