Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:54

0001 /*
0002     tests/test_kwargs_and_defaults.cpp -- keyword arguments and default values
0003 
0004     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
0005 
0006     All rights reserved. Use of this source code is governed by a
0007     BSD-style license that can be found in the LICENSE file.
0008 */
0009 
0010 #include <pybind11/stl.h>
0011 
0012 #include "constructor_stats.h"
0013 #include "pybind11_tests.h"
0014 
0015 #include <utility>
0016 
0017 TEST_SUBMODULE(kwargs_and_defaults, m) {
0018     auto kw_func
0019         = [](int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); };
0020 
0021     // test_named_arguments
0022     m.def("kw_func0", kw_func);
0023     m.def("kw_func1", kw_func, py::arg("x"), py::arg("y"));
0024     m.def("kw_func2", kw_func, py::arg("x") = 100, py::arg("y") = 200);
0025     m.def(
0026         "kw_func3", [](const char *) {}, py::arg("data") = std::string("Hello world!"));
0027 
0028     /* A fancier default argument */
0029     std::vector<int> list{{13, 17}};
0030     m.def(
0031         "kw_func4",
0032         [](const std::vector<int> &entries) {
0033             std::string ret = "{";
0034             for (int i : entries) {
0035                 ret += std::to_string(i) + " ";
0036             }
0037             ret.back() = '}';
0038             return ret;
0039         },
0040         py::arg("myList") = list);
0041 
0042     m.def("kw_func_udl", kw_func, "x"_a, "y"_a = 300);
0043     m.def("kw_func_udl_z", kw_func, "x"_a, "y"_a = 0);
0044 
0045     // test_args_and_kwargs
0046     m.def("args_function", [](py::args args) -> py::tuple {
0047         PYBIND11_WARNING_PUSH
0048 
0049 #ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
0050         PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
0051 #endif
0052         return args;
0053         PYBIND11_WARNING_POP
0054     });
0055     m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) {
0056         return py::make_tuple(args, kwargs);
0057     });
0058 
0059     // test_mixed_args_and_kwargs
0060     m.def("mixed_plus_args",
0061           [](int i, double j, const py::args &args) { return py::make_tuple(i, j, args); });
0062     m.def("mixed_plus_kwargs",
0063           [](int i, double j, const py::kwargs &kwargs) { return py::make_tuple(i, j, kwargs); });
0064     auto mixed_plus_both = [](int i, double j, const py::args &args, const py::kwargs &kwargs) {
0065         return py::make_tuple(i, j, args, kwargs);
0066     };
0067     m.def("mixed_plus_args_kwargs", mixed_plus_both);
0068 
0069     m.def("mixed_plus_args_kwargs_defaults",
0070           mixed_plus_both,
0071           py::arg("i") = 1,
0072           py::arg("j") = 3.14159);
0073 
0074     m.def(
0075         "args_kwonly",
0076         [](int i, double j, const py::args &args, int z) { return py::make_tuple(i, j, args, z); },
0077         "i"_a,
0078         "j"_a,
0079         "z"_a);
0080     m.def(
0081         "args_kwonly_kwargs",
0082         [](int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
0083             return py::make_tuple(i, j, args, z, kwargs);
0084         },
0085         "i"_a,
0086         "j"_a,
0087         py::kw_only{},
0088         "z"_a);
0089     m.def(
0090         "args_kwonly_kwargs_defaults",
0091         [](int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
0092             return py::make_tuple(i, j, args, z, kwargs);
0093         },
0094         "i"_a = 1,
0095         "j"_a = 3.14159,
0096         "z"_a = 42);
0097     m.def(
0098         "args_kwonly_full_monty",
0099         [](int h, int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
0100             return py::make_tuple(h, i, j, args, z, kwargs);
0101         },
0102         py::arg() = 1,
0103         py::arg() = 2,
0104         py::pos_only{},
0105         "j"_a = 3.14159,
0106         "z"_a = 42);
0107 
0108 // test_args_refcount
0109 // PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
0110 #ifdef PYPY_VERSION
0111 #    define GC_IF_NEEDED ConstructorStats::gc()
0112 #else
0113 #    define GC_IF_NEEDED
0114 #endif
0115     m.def("arg_refcount_h", [](py::handle h) {
0116         GC_IF_NEEDED;
0117         return h.ref_count();
0118     });
0119     m.def("arg_refcount_h", [](py::handle h, py::handle, py::handle) {
0120         GC_IF_NEEDED;
0121         return h.ref_count();
0122     });
0123     m.def("arg_refcount_o", [](const py::object &o) {
0124         GC_IF_NEEDED;
0125         return o.ref_count();
0126     });
0127     m.def("args_refcount", [](py::args a) {
0128         GC_IF_NEEDED;
0129         py::tuple t(a.size());
0130         for (size_t i = 0; i < a.size(); i++) {
0131             // Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
0132             t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
0133         }
0134         return t;
0135     });
0136     m.def("mixed_args_refcount", [](const py::object &o, py::args a) {
0137         GC_IF_NEEDED;
0138         py::tuple t(a.size() + 1);
0139         t[0] = o.ref_count();
0140         for (size_t i = 0; i < a.size(); i++) {
0141             // Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
0142             t[i + 1] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
0143         }
0144         return t;
0145     });
0146 
0147     // pybind11 won't allow these to be bound: args and kwargs, if present, must be at the end.
0148     // Uncomment these to test that the static_assert is indeed working:
0149     //    m.def("bad_args1", [](py::args, int) {});
0150     //    m.def("bad_args2", [](py::kwargs, int) {});
0151     //    m.def("bad_args3", [](py::kwargs, py::args) {});
0152     //    m.def("bad_args4", [](py::args, int, py::kwargs) {});
0153     //    m.def("bad_args5", [](py::args, py::kwargs, int) {});
0154     //    m.def("bad_args6", [](py::args, py::args) {});
0155     //    m.def("bad_args7", [](py::kwargs, py::kwargs) {});
0156 
0157     // test_keyword_only_args
0158     m.def(
0159         "kw_only_all",
0160         [](int i, int j) { return py::make_tuple(i, j); },
0161         py::kw_only(),
0162         py::arg("i"),
0163         py::arg("j"));
0164     m.def(
0165         "kw_only_some",
0166         [](int i, int j, int k) { return py::make_tuple(i, j, k); },
0167         py::arg(),
0168         py::kw_only(),
0169         py::arg("j"),
0170         py::arg("k"));
0171     m.def(
0172         "kw_only_with_defaults",
0173         [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
0174         py::arg() = 3,
0175         "j"_a = 4,
0176         py::kw_only(),
0177         "k"_a = 5,
0178         "z"_a);
0179     m.def(
0180         "kw_only_mixed",
0181         [](int i, int j) { return py::make_tuple(i, j); },
0182         "i"_a,
0183         py::kw_only(),
0184         "j"_a);
0185     m.def(
0186         "kw_only_plus_more",
0187         [](int i, int j, int k, const py::kwargs &kwargs) {
0188             return py::make_tuple(i, j, k, kwargs);
0189         },
0190         py::arg() /* positional */,
0191         py::arg("j") = -1 /* both */,
0192         py::kw_only(),
0193         py::arg("k") /* kw-only */);
0194 
0195     m.def("register_invalid_kw_only", [](py::module_ m) {
0196         m.def(
0197             "bad_kw_only",
0198             [](int i, int j) { return py::make_tuple(i, j); },
0199             py::kw_only(),
0200             py::arg() /* invalid unnamed argument */,
0201             "j"_a);
0202     });
0203 
0204     // test_positional_only_args
0205     m.def(
0206         "pos_only_all",
0207         [](int i, int j) { return py::make_tuple(i, j); },
0208         py::arg("i"),
0209         py::arg("j"),
0210         py::pos_only());
0211     m.def(
0212         "pos_only_mix",
0213         [](int i, int j) { return py::make_tuple(i, j); },
0214         py::arg("i"),
0215         py::pos_only(),
0216         py::arg("j"));
0217     m.def(
0218         "pos_kw_only_mix",
0219         [](int i, int j, int k) { return py::make_tuple(i, j, k); },
0220         py::arg("i"),
0221         py::pos_only(),
0222         py::arg("j"),
0223         py::kw_only(),
0224         py::arg("k"));
0225     m.def(
0226         "pos_only_def_mix",
0227         [](int i, int j, int k) { return py::make_tuple(i, j, k); },
0228         py::arg("i"),
0229         py::arg("j") = 2,
0230         py::pos_only(),
0231         py::arg("k") = 3);
0232 
0233     // These should fail to compile:
0234 #ifdef PYBIND11_NEVER_DEFINED_EVER
0235     // argument annotations are required when using kw_only
0236     m.def(
0237         "bad_kw_only1", [](int) {}, py::kw_only());
0238     // can't specify both `py::kw_only` and a `py::args` argument
0239     m.def(
0240         "bad_kw_only2", [](int i, py::args) {}, py::kw_only(), "i"_a);
0241 #endif
0242 
0243     // test_function_signatures (along with most of the above)
0244     struct KWClass {
0245         void foo(int, float) {}
0246     };
0247     py::class_<KWClass>(m, "KWClass")
0248         .def("foo0", &KWClass::foo)
0249         .def("foo1", &KWClass::foo, "x"_a, "y"_a);
0250 
0251     // Make sure a class (not an instance) can be used as a default argument.
0252     // The return value doesn't matter, only that the module is importable.
0253     m.def(
0254         "class_default_argument",
0255         [](py::object a) { return py::repr(std::move(a)); },
0256         "a"_a = py::module_::import("decimal").attr("Decimal"));
0257 
0258     // Initial implementation of kw_only was broken when used on a method/constructor before any
0259     // other arguments
0260     // https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
0261 
0262     struct first_arg_kw_only {};
0263     py::class_<first_arg_kw_only>(m, "first_arg_kw_only")
0264         .def(py::init([](int) { return first_arg_kw_only(); }),
0265              py::kw_only(), // This being before any args was broken
0266              py::arg("i") = 0)
0267         .def(
0268             "method",
0269             [](first_arg_kw_only &, int, int) {},
0270             py::kw_only(), // and likewise here
0271             py::arg("i") = 1,
0272             py::arg("j") = 2)
0273         // Closely related: pos_only marker didn't show up properly when it was before any other
0274         // arguments (although that is fairly useless in practice).
0275         .def(
0276             "pos_only",
0277             [](first_arg_kw_only &, int, int) {},
0278             py::pos_only{},
0279             py::arg("i"),
0280             py::arg("j"));
0281 }