test_kwargs_and_defaults.cpp
Go to the documentation of this file.
1 /*
2  tests/test_kwargs_and_defaults.cpp -- keyword arguments and default values
3 
4  Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #include <pybind11/stl.h>
11 
12 #include "constructor_stats.h"
13 #include "pybind11_tests.h"
14 
15 #include <utility>
16 
17 TEST_SUBMODULE(kwargs_and_defaults, m) {
18  auto kw_func
19  = [](int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); };
20 
21  // test_named_arguments
22  m.def("kw_func0", kw_func);
23  m.def("kw_func1", kw_func, py::arg("x"), py::arg("y"));
24  m.def("kw_func2", kw_func, py::arg("x") = 100, py::arg("y") = 200);
25  m.def("kw_func3", [](const char *) {}, py::arg("data") = std::string("Hello world!"));
26 
27  /* A fancier default argument */
28  std::vector<int> list{{13, 17}};
29  m.def(
30  "kw_func4",
31  [](const std::vector<int> &entries) {
32  std::string ret = "{";
33  for (int i : entries) {
34  ret += std::to_string(i) + " ";
35  }
36  ret.back() = '}';
37  return ret;
38  },
39  py::arg("myList") = list);
40 
41  m.def("kw_func_udl", kw_func, "x"_a, "y"_a = 300);
42  m.def("kw_func_udl_z", kw_func, "x"_a, "y"_a = 0);
43 
44  // test line breaks in default argument representation
45  struct CustomRepr {
46  std::string repr_string;
47 
48  explicit CustomRepr(const std::string &repr) : repr_string(repr) {}
49 
50  std::string __repr__() const { return repr_string; }
51  };
52 
53  py::class_<CustomRepr>(m, "CustomRepr")
54  .def(py::init<const std::string &>())
55  .def("__repr__", &CustomRepr::__repr__);
56 
57  m.def(
58  "kw_lb_func0",
59  [](const CustomRepr &) {},
60  py::arg("custom") = CustomRepr(" array([[A, B], [C, D]]) "));
61  m.def(
62  "kw_lb_func1",
63  [](const CustomRepr &) {},
64  py::arg("custom") = CustomRepr(" array([[A, B],\n[C, D]]) "));
65  m.def(
66  "kw_lb_func2",
67  [](const CustomRepr &) {},
68  py::arg("custom") = CustomRepr("\v\n array([[A, B], [C, D]])"));
69  m.def(
70  "kw_lb_func3",
71  [](const CustomRepr &) {},
72  py::arg("custom") = CustomRepr("array([[A, B], [C, D]]) \f\n"));
73  m.def(
74  "kw_lb_func4",
75  [](const CustomRepr &) {},
76  py::arg("custom") = CustomRepr("array([[A, B],\n\f\n[C, D]])"));
77  m.def(
78  "kw_lb_func5",
79  [](const CustomRepr &) {},
80  py::arg("custom") = CustomRepr("array([[A, B],\r [C, D]])"));
81  m.def("kw_lb_func6", [](const CustomRepr &) {}, py::arg("custom") = CustomRepr(" \v\t "));
82  m.def(
83  "kw_lb_func7",
84  [](const std::string &) {},
85  py::arg("str_arg") = "First line.\n Second line.");
86  m.def("kw_lb_func8", [](const CustomRepr &) {}, py::arg("custom") = CustomRepr(""));
87 
88  // test_args_and_kwargs
89  m.def("args_function", [](py::args args) -> py::tuple {
90  PYBIND11_WARNING_PUSH
91 
92 #ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
93  PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
94 #endif
95  return args;
97  });
98  m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) {
99  return py::make_tuple(args, kwargs);
100  });
101 
102  // test_mixed_args_and_kwargs
103  m.def("mixed_plus_args",
104  [](int i, double j, const py::args &args) { return py::make_tuple(i, j, args); });
105  m.def("mixed_plus_kwargs",
106  [](int i, double j, const py::kwargs &kwargs) { return py::make_tuple(i, j, kwargs); });
107  auto mixed_plus_both = [](int i, double j, const py::args &args, const py::kwargs &kwargs) {
108  return py::make_tuple(i, j, args, kwargs);
109  };
110  m.def("mixed_plus_args_kwargs", mixed_plus_both);
111 
112  m.def("mixed_plus_args_kwargs_defaults",
113  mixed_plus_both,
114  py::arg("i") = 1,
115  py::arg("j") = 3.14159);
116 
117  m.def(
118  "args_kwonly",
119  [](int i, double j, const py::args &args, int z) { return py::make_tuple(i, j, args, z); },
120  "i"_a,
121  "j"_a,
122  "z"_a);
123  m.def(
124  "args_kwonly_kwargs",
125  [](int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
126  return py::make_tuple(i, j, args, z, kwargs);
127  },
128  "i"_a,
129  "j"_a,
130  py::kw_only{},
131  "z"_a);
132  m.def(
133  "args_kwonly_kwargs_defaults",
134  [](int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
135  return py::make_tuple(i, j, args, z, kwargs);
136  },
137  "i"_a = 1,
138  "j"_a = 3.14159,
139  "z"_a = 42);
140  m.def(
141  "args_kwonly_full_monty",
142  [](int h, int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
143  return py::make_tuple(h, i, j, args, z, kwargs);
144  },
145  py::arg() = 1,
146  py::arg() = 2,
147  py::pos_only{},
148  "j"_a = 3.14159,
149  "z"_a = 42);
150 
151 // test_args_refcount
152 // PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
153 // PyPy uses the top few bits for REFCNT_FROM_PYPY & REFCNT_FROM_PYPY_LIGHT, so truncate
154 #ifdef PYPY_VERSION
155 # define GC_IF_NEEDED ConstructorStats::gc()
156 # define REFCNT(x) (int) Py_REFCNT(x)
157 #else
158 # define GC_IF_NEEDED
159 # define REFCNT(x) Py_REFCNT(x)
160 #endif
161  m.def("arg_refcount_h", [](py::handle h) {
162  GC_IF_NEEDED;
163  return h.ref_count();
164  });
165  m.def("arg_refcount_h", [](py::handle h, py::handle, py::handle) {
166  GC_IF_NEEDED;
167  return h.ref_count();
168  });
169  m.def("arg_refcount_o", [](const py::object &o) {
170  GC_IF_NEEDED;
171  return o.ref_count();
172  });
173  m.def("args_refcount", [](py::args a) {
174  GC_IF_NEEDED;
175  py::tuple t(a.size());
176  for (size_t i = 0; i < a.size(); i++) {
177  // Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
178  t[i] = REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
179  }
180  return t;
181  });
182  m.def("mixed_args_refcount", [](const py::object &o, py::args a) {
183  GC_IF_NEEDED;
184  py::tuple t(a.size() + 1);
185  t[0] = o.ref_count();
186  for (size_t i = 0; i < a.size(); i++) {
187  // Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
188  t[i + 1] = REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
189  }
190  return t;
191  });
192 
193  // pybind11 won't allow these to be bound: args and kwargs, if present, must be at the end.
194  // Uncomment these to test that the static_assert is indeed working:
195  // m.def("bad_args1", [](py::args, int) {});
196  // m.def("bad_args2", [](py::kwargs, int) {});
197  // m.def("bad_args3", [](py::kwargs, py::args) {});
198  // m.def("bad_args4", [](py::args, int, py::kwargs) {});
199  // m.def("bad_args5", [](py::args, py::kwargs, int) {});
200  // m.def("bad_args6", [](py::args, py::args) {});
201  // m.def("bad_args7", [](py::kwargs, py::kwargs) {});
202 
203  // test_keyword_only_args
204  m.def(
205  "kw_only_all",
206  [](int i, int j) { return py::make_tuple(i, j); },
207  py::kw_only(),
208  py::arg("i"),
209  py::arg("j"));
210  m.def(
211  "kw_only_some",
212  [](int i, int j, int k) { return py::make_tuple(i, j, k); },
213  py::arg(),
214  py::kw_only(),
215  py::arg("j"),
216  py::arg("k"));
217  m.def(
218  "kw_only_with_defaults",
219  [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
220  py::arg() = 3,
221  "j"_a = 4,
222  py::kw_only(),
223  "k"_a = 5,
224  "z"_a);
225  m.def(
226  "kw_only_mixed",
227  [](int i, int j) { return py::make_tuple(i, j); },
228  "i"_a,
229  py::kw_only(),
230  "j"_a);
231  m.def(
232  "kw_only_plus_more",
233  [](int i, int j, int k, const py::kwargs &kwargs) {
234  return py::make_tuple(i, j, k, kwargs);
235  },
236  py::arg() /* positional */,
237  py::arg("j") = -1 /* both */,
238  py::kw_only(),
239  py::arg("k") /* kw-only */);
240 
241  m.def("register_invalid_kw_only", [](py::module_ m) {
242  m.def(
243  "bad_kw_only",
244  [](int i, int j) { return py::make_tuple(i, j); },
245  py::kw_only(),
246  py::arg() /* invalid unnamed argument */,
247  "j"_a);
248  });
249 
250  // test_positional_only_args
251  m.def(
252  "pos_only_all",
253  [](int i, int j) { return py::make_tuple(i, j); },
254  py::arg("i"),
255  py::arg("j"),
256  py::pos_only());
257  m.def(
258  "pos_only_mix",
259  [](int i, int j) { return py::make_tuple(i, j); },
260  py::arg("i"),
261  py::pos_only(),
262  py::arg("j"));
263  m.def(
264  "pos_kw_only_mix",
265  [](int i, int j, int k) { return py::make_tuple(i, j, k); },
266  py::arg("i"),
267  py::pos_only(),
268  py::arg("j"),
269  py::kw_only(),
270  py::arg("k"));
271  m.def(
272  "pos_only_def_mix",
273  [](int i, int j, int k) { return py::make_tuple(i, j, k); },
274  py::arg("i"),
275  py::arg("j") = 2,
276  py::pos_only(),
277  py::arg("k") = 3);
278 
279  // These should fail to compile:
280 #ifdef PYBIND11_NEVER_DEFINED_EVER
281  // argument annotations are required when using kw_only
282  m.def("bad_kw_only1", [](int) {}, py::kw_only());
283  // can't specify both `py::kw_only` and a `py::args` argument
284  m.def("bad_kw_only2", [](int i, py::args) {}, py::kw_only(), "i"_a);
285 #endif
286 
287  // test_function_signatures (along with most of the above)
288  struct KWClass {
289  void foo(int, float) {}
290  };
291  py::class_<KWClass>(m, "KWClass")
292  .def("foo0", &KWClass::foo)
293  .def("foo1", &KWClass::foo, "x"_a, "y"_a);
294 
295  // Make sure a class (not an instance) can be used as a default argument.
296  // The return value doesn't matter, only that the module is importable.
297  m.def(
298  "class_default_argument",
299  [](py::object a) { return py::repr(std::move(a)); },
300  "a"_a = py::module_::import("decimal").attr("Decimal"));
301 
302  // Initial implementation of kw_only was broken when used on a method/constructor before any
303  // other arguments
304  // https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
305 
306  struct first_arg_kw_only {};
307  py::class_<first_arg_kw_only>(m, "first_arg_kw_only")
308  .def(py::init([](int) { return first_arg_kw_only(); }),
309  py::kw_only(), // This being before any args was broken
310  py::arg("i") = 0)
311  .def(
312  "method",
313  [](first_arg_kw_only &, int, int) {},
314  py::kw_only(), // and likewise here
315  py::arg("i") = 1,
316  py::arg("j") = 2)
317  // Closely related: pos_only marker didn't show up properly when it was before any other
318  // arguments (although that is fairly useless in practice).
319  .def(
320  "pos_only",
321  [](first_arg_kw_only &, int, int) {},
322  py::pos_only{},
323  py::arg("i"),
324  py::arg("j"));
325 }
ssize_t
Py_ssize_t ssize_t
Definition: wrap/pybind11/include/pybind11/detail/common.h:489
kwargs
Definition: pytypes.h:2213
x
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Definition: gnuplot_common_settings.hh:12
ret
DenseIndex ret
Definition: level1_cplx_impl.h:44
stl.h
PYBIND11_WARNING_POP
PYBIND11_WARNING_PUSH PYBIND11_WARNING_POP
Definition: tensor.h:30
h
const double h
Definition: testSimpleHelicopter.cpp:19
constructor_stats.h
process_shonan_timing_results.args
args
Definition: process_shonan_timing_results.py:163
gtwrap.interface_parser.function.__repr__
str __repr__(self)
Definition: interface_parser/function.py:53
j
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2
make_tuple
tuple make_tuple()
Definition: cast.h:1383
GC_IF_NEEDED
#define GC_IF_NEEDED
foo
void foo(CV_QUALIFIER Matrix3d &m)
Definition: block_nonconst_ctor_on_const_xpr_0.cpp:11
pybind_wrapper_test_script.z
z
Definition: pybind_wrapper_test_script.py:61
m
Matrix3f m
Definition: AngleAxis_mimic_euler.cpp:1
arg
EIGEN_DEVICE_FUNC const EIGEN_STRONG_INLINE ArgReturnType arg() const
Definition: ArrayCwiseUnaryOps.h:66
REFCNT
#define REFCNT(x)
init
detail::initimpl::constructor< Args... > init()
Binds an existing constructor taking arguments Args...
Definition: pybind11.h:2006
y
Scalar * y
Definition: level1_cplx_impl.h:124
a
ArrayXXi a
Definition: Array_initializer_list_23_cxx11.cpp:1
pybind11_tests.h
args
Definition: pytypes.h:2210
TEST_SUBMODULE
TEST_SUBMODULE(kwargs_and_defaults, m)
Definition: test_kwargs_and_defaults.cpp:17
align_3::t
Point2 t(10, 10)
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
PYBIND11_WARNING_DISABLE_CLANG
#define PYBIND11_WARNING_DISABLE_CLANG(name)
Definition: wrap/pybind11/include/pybind11/detail/common.h:61
repr
str repr(handle h)
Definition: pytypes.h:2467


gtsam
Author(s):
autogenerated on Thu Jul 4 2024 03:06:01