Skip to content

Commit 58c7f07

Browse files
committed
Merge branch 'master' into sh_merge_master
2 parents 22bf704 + 01f938e commit 58c7f07

12 files changed

+220
-52
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ repos:
4545

4646
# Black, the code formatter, natively supports pre-commit
4747
- repo: https://github.com/psf/black
48-
rev: 21.9b0 # Keep in sync with blacken-docs
48+
rev: 21.10b0 # Keep in sync with blacken-docs
4949
hooks:
5050
- id: black
5151

@@ -54,7 +54,7 @@ repos:
5454
hooks:
5555
- id: blacken-docs
5656
additional_dependencies:
57-
- black==21.9b0 # keep in sync with black hook
57+
- black==21.10b0 # keep in sync with black hook
5858

5959
# Changes tabs to spaces
6060
- repo: https://github.com/Lucas-C/pre-commit-hooks

docs/advanced/functions.rst

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,9 @@ The class ``py::args`` derives from ``py::tuple`` and ``py::kwargs`` derives
306306
from ``py::dict``.
307307

308308
You may also use just one or the other, and may combine these with other
309-
arguments as long as the ``py::args`` and ``py::kwargs`` arguments are the last
310-
arguments accepted by the function.
309+
arguments. Note, however, that ``py::kwargs`` must always be the last argument
310+
of the function, and ``py::args`` implies that any further arguments are
311+
keyword-only (see :ref:`keyword_only_arguments`).
311312

312313
Please refer to the other examples for details on how to iterate over these,
313314
and on how to cast their entries into C++ objects. A demonstration is also
@@ -366,6 +367,8 @@ like so:
366367
py::class_<MyClass>("MyClass")
367368
.def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));
368369
370+
.. _keyword_only_arguments:
371+
369372
Keyword-only arguments
370373
======================
371374

@@ -397,6 +400,15 @@ feature does *not* require Python 3 to work.
397400

398401
.. versionadded:: 2.6
399402

403+
As of pybind11 2.9, a ``py::args`` argument implies that any following arguments
404+
are keyword-only, as if ``py::kw_only()`` had been specified in the same
405+
relative location of the argument list as the ``py::args`` argument. The
406+
``py::kw_only()`` may be included to be explicit about this, but is not
407+
required. (Prior to 2.9 ``py::args`` may only occur at the end of the argument
408+
list, or immediately before a ``py::kwargs`` argument at the end).
409+
410+
.. versionadded:: 2.9
411+
400412
Positional-only arguments
401413
=========================
402414

docs/basics.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ a file named :file:`example.cpp` with the following contents:
109109
PYBIND11_MODULE(example, m) {
110110
m.doc() = "pybind11 example plugin"; // optional module docstring
111111
112-
m.def("add", &add, "A function which adds two numbers");
112+
m.def("add", &add, "A function that adds two numbers");
113113
}
114114
115115
.. [#f1] In practice, implementation and binding code will generally be located

docs/release.rst

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ the version just below.
2222
To release a new version of pybind11:
2323
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424

25+
If you don't have nox, you should either use ``pipx run nox`` instead, or use
26+
``pipx install nox`` or ``brew install nox`` (Unix).
27+
2528
- Update the version number
2629
- Update ``PYBIND11_VERSION_MAJOR`` etc. in
2730
``include/pybind11/detail/common.h``. PATCH should be a simple integer.
@@ -51,14 +54,12 @@ To release a new version of pybind11:
5154
notifications to users watching releases, and also uploads PyPI packages).
5255
(Note: if you do not use an existing tag, this creates a new lightweight tag
5356
for you, so you could skip the above step.)
54-
5557
- GUI method: Under `releases <https://github.com/pybind/pybind11/releases>`_
5658
click "Draft a new release" on the far right, fill in the tag name
5759
(if you didn't tag above, it will be made here), fill in a release name
5860
like "Version X.Y.Z", and copy-and-paste the markdown-formatted (!) changelog
5961
into the description (usually ``cat docs/changelog.rst | pandoc -f rst -t gfm``).
6062
Check "pre-release" if this is a beta/RC.
61-
6263
- CLI method: with ``gh`` installed, run ``gh release create vX.Y.Z -t "Version X.Y.Z"``
6364
If this is a pre-release, add ``-p``.
6465

@@ -90,9 +91,7 @@ If you need to manually upload releases, you can download the releases from the
9091

9192
.. code-block:: bash
9293
93-
python3 -m pip install build
94-
python3 -m build
95-
PYBIND11_SDIST_GLOBAL=1 python3 -m build
94+
nox -s build
9695
twine upload dist/*
9796
9897
This makes SDists and wheels, and the final line uploads them.

include/pybind11/attr.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ struct function_record {
174174
function_record()
175175
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
176176
is_operator(false), is_method(false), has_args(false),
177-
has_kwargs(false), has_kw_only_args(false), prepend(false) { }
177+
has_kwargs(false), prepend(false) { }
178178

179179
/// Function name
180180
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
@@ -221,17 +221,15 @@ struct function_record {
221221
/// True if the function has a '**kwargs' argument
222222
bool has_kwargs : 1;
223223

224-
/// True once a 'py::kw_only' is encountered (any following args are keyword-only)
225-
bool has_kw_only_args : 1;
226-
227224
/// True if this function is to be inserted at the beginning of the overload resolution chain
228225
bool prepend : 1;
229226

230227
/// Number of arguments (including py::args and/or py::kwargs, if present)
231228
std::uint16_t nargs;
232229

233-
/// Number of trailing arguments (counted in `nargs`) that are keyword-only
234-
std::uint16_t nargs_kw_only = 0;
230+
/// Number of leading positional arguments, which are terminated by a py::args or py::kwargs
231+
/// argument or by a py::kw_only annotation.
232+
std::uint16_t nargs_pos = 0;
235233

236234
/// Number of leading arguments (counted in `nargs`) that are positional-only
237235
std::uint16_t nargs_pos_only = 0;
@@ -411,10 +409,9 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
411409
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
412410
};
413411

414-
inline void process_kw_only_arg(const arg &a, function_record *r) {
415-
if (!a.name || a.name[0] == '\0')
416-
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
417-
++r->nargs_kw_only;
412+
inline void check_kw_only_arg(const arg &a, function_record *r) {
413+
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0'))
414+
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or args() argument");
418415
}
419416

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

427-
if (r->has_kw_only_args) process_kw_only_arg(a, r);
424+
check_kw_only_arg(a, r);
428425
}
429426
};
430427

@@ -457,21 +454,26 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
457454
}
458455
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
459456

460-
if (r->has_kw_only_args) process_kw_only_arg(a, r);
457+
check_kw_only_arg(a, r);
461458
}
462459
};
463460

464461
/// Process a keyword-only-arguments-follow pseudo argument
465462
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
466463
static void init(const kw_only &, function_record *r) {
467-
r->has_kw_only_args = true;
464+
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size()))
465+
pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative argument location (or omit kw_only() entirely)");
466+
r->nargs_pos = static_cast<std::uint16_t>(r->args.size());
468467
}
469468
};
470469

471470
/// Process a positional-only-argument maker
472471
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
473472
static void init(const pos_only &, function_record *r) {
474473
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
474+
if (r->nargs_pos_only > r->nargs_pos)
475+
pybind11_fail("pos_only(): cannot follow a py::args() argument");
476+
// It also can't follow a kw_only, but a static_assert in pybind11.h checks that
475477
}
476478
};
477479

include/pybind11/cast.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,9 @@ constexpr arg operator"" _a(const char *name, size_t) { return arg(name); }
11591159

11601160
PYBIND11_NAMESPACE_BEGIN(detail)
11611161

1162+
template <typename T> using is_kw_only = std::is_same<intrinsic_t<T>, kw_only>;
1163+
template <typename T> using is_pos_only = std::is_same<intrinsic_t<T>, pos_only>;
1164+
11621165
// forward declaration (definition in attr.h)
11631166
struct function_record;
11641167

@@ -1194,17 +1197,18 @@ class argument_loader {
11941197

11951198
template <typename Arg> using argument_is_args = std::is_same<intrinsic_t<Arg>, args>;
11961199
template <typename Arg> using argument_is_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
1197-
// Get args/kwargs argument positions relative to the end of the argument list:
1198-
static constexpr auto args_pos = constexpr_first<argument_is_args, Args...>() - (int) sizeof...(Args),
1199-
kwargs_pos = constexpr_first<argument_is_kwargs, Args...>() - (int) sizeof...(Args);
1200-
1201-
static constexpr bool args_kwargs_are_last = kwargs_pos >= - 1 && args_pos >= kwargs_pos - 1;
1200+
// Get kwargs argument position, or -1 if not present:
1201+
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
12021202

1203-
static_assert(args_kwargs_are_last, "py::args/py::kwargs are only permitted as the last argument(s) of a function");
1203+
static_assert(kwargs_pos == -1 || kwargs_pos == (int) sizeof...(Args) - 1, "py::kwargs is only permitted as the last argument of a function");
12041204

12051205
public:
1206-
static constexpr bool has_kwargs = kwargs_pos < 0;
1207-
static constexpr bool has_args = args_pos < 0;
1206+
static constexpr bool has_kwargs = kwargs_pos != -1;
1207+
1208+
// py::args argument position; -1 if not present.
1209+
static constexpr int args_pos = constexpr_last<argument_is_args, Args...>();
1210+
1211+
static_assert(args_pos == -1 || args_pos == constexpr_first<argument_is_args, Args...>(), "py::args cannot be specified more than once");
12081212

12091213
static constexpr auto arg_names = concat(type_descr(make_caster<Args>::name)...);
12101214

0 commit comments

Comments
 (0)