test_methods_and_attributes.cpp 17.3 KB
Newer Older
1
/*
Dean Moldovan's avatar
Dean Moldovan committed
2
    tests/test_methods_and_attributes.cpp -- constructors, deconstructors, attribute access,
3
4
5
6
7
8
9
10
    __str__, argument and return value conventions

    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

Dean Moldovan's avatar
Dean Moldovan committed
11
12
#include "pybind11_tests.h"
#include "constructor_stats.h"
13
14
15

class ExampleMandA {
public:
16
17
18
19
20
21
    ExampleMandA() { print_default_created(this); }
    ExampleMandA(int value) : value(value) { print_created(this, value); }
    ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); }
    ExampleMandA(ExampleMandA &&e) : value(e.value) { print_move_created(this); }
    ~ExampleMandA() { print_destroyed(this); }

22
23
24
25
    std::string toString() {
        return "ExampleMandA[value=" + std::to_string(value) + "]";
    }

26
27
    void operator=(const ExampleMandA &e) { print_copy_assigned(this); value = e.value; }
    void operator=(ExampleMandA &&e) { print_move_assigned(this); value = e.value; }
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

    void add1(ExampleMandA other) { value += other.value; }           // passing by value
    void add2(ExampleMandA &other) { value += other.value; }          // passing by reference
    void add3(const ExampleMandA &other) { value += other.value; }    // passing by const reference
    void add4(ExampleMandA *other) { value += other->value; }         // passing by pointer
    void add5(const ExampleMandA *other) { value += other->value; }   // passing by const pointer

    void add6(int other) { value += other; }                      // passing by value
    void add7(int &other) { value += other; }                     // passing by reference
    void add8(const int &other) { value += other; }               // passing by const reference
    void add9(int *other) { value += *other; }                    // passing by pointer
    void add10(const int *other) { value += *other; }             // passing by const pointer

    ExampleMandA self1() { return *this; }                            // return by value
    ExampleMandA &self2() { return *this; }                           // return by reference
    const ExampleMandA &self3() { return *this; }                     // return by const reference
    ExampleMandA *self4() { return this; }                            // return by pointer
    const ExampleMandA *self5() { return this; }                      // return by const pointer

    int internal1() { return value; }                             // return by value
    int &internal2() { return value; }                            // return by reference
    const int &internal3() { return value; }                      // return by const reference
    int *internal4() { return &value; }                           // return by pointer
    const int *internal5() { return &value; }                     // return by const pointer

53
54
55
56
57
58
59
60
    py::str overloaded(int, float)   { return "(int, float)"; }
    py::str overloaded(float, int)   { return "(float, int)"; }
    py::str overloaded(int, int)     { return "(int, int)"; }
    py::str overloaded(float, float) { return "(float, float)"; }
    py::str overloaded(int, float)   const { return "(int, float) const"; }
    py::str overloaded(float, int)   const { return "(float, int) const"; }
    py::str overloaded(int, int)     const { return "(int, int) const"; }
    py::str overloaded(float, float) const { return "(float, float) const"; }
61

62
63
    static py::str overloaded() { return "static"; }

64
65
66
    int value = 0;
};

67
68
69
70
71
72
73
74
75
76
77
78
79
struct TestProperties {
    int value = 1;
    static int static_value;

    int get() const { return value; }
    void set(int v) { value = v; }

    static int static_get() { return static_value; }
    static void static_set(int v) { static_value = v; }
};

int TestProperties::static_value = 1;

80
81
82
83
84
85
86
struct TestPropertiesOverride : TestProperties {
    int value = 99;
    static int static_value;
};

int TestPropertiesOverride::static_value = 99;

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
struct SimpleValue { int value = 1; };

struct TestPropRVP {
    SimpleValue v1;
    SimpleValue v2;
    static SimpleValue sv1;
    static SimpleValue sv2;

    const SimpleValue &get1() const { return v1; }
    const SimpleValue &get2() const { return v2; }
    SimpleValue get_rvalue() const { return v2; }
    void set1(int v) { v1.value = v; }
    void set2(int v) { v2.value = v; }
};

SimpleValue TestPropRVP::sv1{};
SimpleValue TestPropRVP::sv2{};

Dean Moldovan's avatar
Dean Moldovan committed
105
106
107
108
109
110
class DynamicClass {
public:
    DynamicClass() { print_default_created(this); }
    ~DynamicClass() { print_destroyed(this); }
};

111
112
class CppDerivedDynamicClass : public DynamicClass { };

113
114
115
// py::arg/py::arg_v testing: these arguments just record their argument when invoked
class ArgInspector1 { public: std::string arg = "(default arg inspector 1)"; };
class ArgInspector2 { public: std::string arg = "(default arg inspector 2)"; };
116
class ArgAlwaysConverts { };
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
namespace pybind11 { namespace detail {
template <> struct type_caster<ArgInspector1> {
public:
    PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));

    bool load(handle src, bool convert) {
        value.arg = "loading ArgInspector1 argument " +
            std::string(convert ? "WITH" : "WITHOUT") + " conversion allowed.  "
            "Argument value = " + (std::string) str(src);
        return true;
    }

    static handle cast(const ArgInspector1 &src, return_value_policy, handle) {
        return str(src.arg).release();
    }
};
template <> struct type_caster<ArgInspector2> {
public:
    PYBIND11_TYPE_CASTER(ArgInspector2, _("ArgInspector2"));

    bool load(handle src, bool convert) {
        value.arg = "loading ArgInspector2 argument " +
            std::string(convert ? "WITH" : "WITHOUT") + " conversion allowed.  "
            "Argument value = " + (std::string) str(src);
        return true;
    }

    static handle cast(const ArgInspector2 &src, return_value_policy, handle) {
        return str(src.arg).release();
    }
};
148
149
150
151
152
153
154
155
156
157
158
159
template <> struct type_caster<ArgAlwaysConverts> {
public:
    PYBIND11_TYPE_CASTER(ArgAlwaysConverts, _("ArgAlwaysConverts"));

    bool load(handle, bool convert) {
        return convert;
    }

    static handle cast(const ArgAlwaysConverts &, return_value_policy, handle) {
        return py::none();
    }
};
160
161
}}

162
163
164
/// Issue/PR #648: bad arg default debugging output
class NotRegistered {};

165
166
167
168
169
170
171
172
// Test None-allowed py::arg argument policy
class NoneTester { public: int answer = 42; };
int none1(const NoneTester &obj) { return obj.answer; }
int none2(NoneTester *obj) { return obj ? obj->answer : -1; }
int none3(std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; }
int none4(std::shared_ptr<NoneTester> *obj) { return obj && *obj ? (*obj)->answer : -1; }
int none5(std::shared_ptr<NoneTester> obj) { return obj ? obj->answer : -1; }

173
174
175
176
177
178
179
struct StrIssue {
    int val = -1;

    StrIssue() = default;
    StrIssue(int i) : val{i} {}
};

180
test_initializer methods_and_attributes([](py::module &m) {
181
182
    py::class_<ExampleMandA> emna(m, "ExampleMandA");
    emna.def(py::init<>())
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
        .def(py::init<int>())
        .def(py::init<const ExampleMandA&>())
        .def("add1", &ExampleMandA::add1)
        .def("add2", &ExampleMandA::add2)
        .def("add3", &ExampleMandA::add3)
        .def("add4", &ExampleMandA::add4)
        .def("add5", &ExampleMandA::add5)
        .def("add6", &ExampleMandA::add6)
        .def("add7", &ExampleMandA::add7)
        .def("add8", &ExampleMandA::add8)
        .def("add9", &ExampleMandA::add9)
        .def("add10", &ExampleMandA::add10)
        .def("self1", &ExampleMandA::self1)
        .def("self2", &ExampleMandA::self2)
        .def("self3", &ExampleMandA::self3)
        .def("self4", &ExampleMandA::self4)
        .def("self5", &ExampleMandA::self5)
        .def("internal1", &ExampleMandA::internal1)
        .def("internal2", &ExampleMandA::internal2)
        .def("internal3", &ExampleMandA::internal3)
        .def("internal4", &ExampleMandA::internal4)
        .def("internal5", &ExampleMandA::internal5)
205
#if defined(PYBIND11_OVERLOAD_CAST)
206
207
208
209
210
211
212
213
214
        .def("overloaded", py::overload_cast<int,   float>(&ExampleMandA::overloaded))
        .def("overloaded", py::overload_cast<float,   int>(&ExampleMandA::overloaded))
        .def("overloaded", py::overload_cast<int,     int>(&ExampleMandA::overloaded))
        .def("overloaded", py::overload_cast<float, float>(&ExampleMandA::overloaded))
        .def("overloaded_float", py::overload_cast<float, float>(&ExampleMandA::overloaded))
        .def("overloaded_const", py::overload_cast<int,   float>(&ExampleMandA::overloaded, py::const_))
        .def("overloaded_const", py::overload_cast<float,   int>(&ExampleMandA::overloaded, py::const_))
        .def("overloaded_const", py::overload_cast<int,     int>(&ExampleMandA::overloaded, py::const_))
        .def("overloaded_const", py::overload_cast<float, float>(&ExampleMandA::overloaded, py::const_))
215
#else
216
217
218
219
220
221
222
223
224
        .def("overloaded", static_cast<py::str (ExampleMandA::*)(int,   float)>(&ExampleMandA::overloaded))
        .def("overloaded", static_cast<py::str (ExampleMandA::*)(float,   int)>(&ExampleMandA::overloaded))
        .def("overloaded", static_cast<py::str (ExampleMandA::*)(int,     int)>(&ExampleMandA::overloaded))
        .def("overloaded", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded))
        .def("overloaded_float", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded))
        .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int,   float) const>(&ExampleMandA::overloaded))
        .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float,   int) const>(&ExampleMandA::overloaded))
        .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int,     int) const>(&ExampleMandA::overloaded))
        .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, float) const>(&ExampleMandA::overloaded))
225
#endif
226
227
228
229
230
231
232
233
234
235
236
        // Raise error if trying to mix static/non-static overloads on the same name:
        .def_static("add_mixed_overloads1", []() {
            auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module::import("pybind11_tests").attr("ExampleMandA"));
            emna.def       ("overload_mixed1", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded))
                .def_static("overload_mixed1", static_cast<py::str (              *)(        )>(&ExampleMandA::overloaded));
        })
        .def_static("add_mixed_overloads2", []() {
            auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module::import("pybind11_tests").attr("ExampleMandA"));
            emna.def_static("overload_mixed2", static_cast<py::str (              *)(        )>(&ExampleMandA::overloaded))
                .def       ("overload_mixed2", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded));
        })
237
        .def("__str__", &ExampleMandA::toString)
Wenzel Jakob's avatar
Wenzel Jakob committed
238
        .def_readwrite("value", &ExampleMandA::value);
Dean Moldovan's avatar
Dean Moldovan committed
239

240
241
242
    // Issue #443: can't call copied methods in Python 3
    emna.attr("add2b") = emna.attr("add2");

243
    py::class_<TestProperties>(m, "TestProperties")
244
245
246
247
248
249
250
251
252
253
254
        .def(py::init<>())
        .def_readonly("def_readonly", &TestProperties::value)
        .def_readwrite("def_readwrite", &TestProperties::value)
        .def_property_readonly("def_property_readonly", &TestProperties::get)
        .def_property("def_property", &TestProperties::get, &TestProperties::set)
        .def_readonly_static("def_readonly_static", &TestProperties::static_value)
        .def_readwrite_static("def_readwrite_static", &TestProperties::static_value)
        .def_property_readonly_static("def_property_readonly_static",
                                      [](py::object) { return TestProperties::static_get(); })
        .def_property_static("def_property_static",
                             [](py::object) { return TestProperties::static_get(); },
255
256
257
258
                             [](py::object, int v) { TestProperties::static_set(v); })
        .def_property_static("static_cls",
                             [](py::object cls) { return cls; },
                             [](py::object cls, py::function f) { f(cls); });
259

260
261
262
263
264
    py::class_<TestPropertiesOverride, TestProperties>(m, "TestPropertiesOverride")
        .def(py::init<>())
        .def_readonly("def_readonly", &TestPropertiesOverride::value)
        .def_readonly_static("def_readonly_static", &TestPropertiesOverride::static_value);

265
266
267
268
269
270
271
272
273
    py::class_<SimpleValue>(m, "SimpleValue")
        .def_readwrite("value", &SimpleValue::value);

    auto static_get1 = [](py::object) -> const SimpleValue & { return TestPropRVP::sv1; };
    auto static_get2 = [](py::object) -> const SimpleValue & { return TestPropRVP::sv2; };
    auto static_set1 = [](py::object, int v) { TestPropRVP::sv1.value = v; };
    auto static_set2 = [](py::object, int v) { TestPropRVP::sv2.value = v; };
    auto rvp_copy = py::return_value_policy::copy;

274
    py::class_<TestPropRVP>(m, "TestPropRVP")
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
        .def(py::init<>())
        .def_property_readonly("ro_ref", &TestPropRVP::get1)
        .def_property_readonly("ro_copy", &TestPropRVP::get2, rvp_copy)
        .def_property_readonly("ro_func", py::cpp_function(&TestPropRVP::get2, rvp_copy))
        .def_property("rw_ref", &TestPropRVP::get1, &TestPropRVP::set1)
        .def_property("rw_copy", &TestPropRVP::get2, &TestPropRVP::set2, rvp_copy)
        .def_property("rw_func", py::cpp_function(&TestPropRVP::get2, rvp_copy), &TestPropRVP::set2)
        .def_property_readonly_static("static_ro_ref", static_get1)
        .def_property_readonly_static("static_ro_copy", static_get2, rvp_copy)
        .def_property_readonly_static("static_ro_func", py::cpp_function(static_get2, rvp_copy))
        .def_property_static("static_rw_ref", static_get1, static_set1)
        .def_property_static("static_rw_copy", static_get2, static_set2, rvp_copy)
        .def_property_static("static_rw_func", py::cpp_function(static_get2, rvp_copy), static_set2)
        .def_property_readonly("rvalue", &TestPropRVP::get_rvalue)
        .def_property_readonly_static("static_rvalue", [](py::object) { return SimpleValue(); });

291
292
293
294
    struct MetaclassOverride { };
    py::class_<MetaclassOverride>(m, "MetaclassOverride", py::metaclass((PyObject *) &PyType_Type))
        .def_property_readonly_static("readonly", [](py::object) { return 1; });

295
#if !defined(PYPY_VERSION)
Dean Moldovan's avatar
Dean Moldovan committed
296
297
    py::class_<DynamicClass>(m, "DynamicClass", py::dynamic_attr())
        .def(py::init());
298
299
300

    py::class_<CppDerivedDynamicClass, DynamicClass>(m, "CppDerivedDynamicClass")
        .def(py::init());
301
#endif
302

303
304
305
    // Test converting.  The ArgAlwaysConverts is just there to make the first no-conversion pass
    // fail so that our call always ends up happening via the second dispatch (the one that allows
    // some conversion).
306
307
    class ArgInspector {
    public:
308
309
        ArgInspector1 f(ArgInspector1 a, ArgAlwaysConverts) { return a; }
        std::string g(ArgInspector1 a, const ArgInspector1 &b, int c, ArgInspector2 *d, ArgAlwaysConverts) {
310
311
            return a.arg + "\n" + b.arg + "\n" + std::to_string(c) + "\n" + d->arg;
        }
312
        static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
313
314
315
    };
    py::class_<ArgInspector>(m, "ArgInspector")
        .def(py::init<>())
316
317
318
        .def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
        .def("g", &ArgInspector::g, "a"_a.noconvert(), "b"_a, "c"_a.noconvert()=13, "d"_a=ArgInspector2(), py::arg() = ArgAlwaysConverts())
        .def_static("h", &ArgInspector::h, py::arg().noconvert(), py::arg() = ArgAlwaysConverts())
319
        ;
320
321
    m.def("arg_inspect_func", [](ArgInspector2 a, ArgInspector1 b, ArgAlwaysConverts) { return a.arg + "\n" + b.arg; },
            py::arg().noconvert(false), py::arg_v(nullptr, ArgInspector1()).noconvert(true), py::arg() = ArgAlwaysConverts());
322
323
324

    m.def("floats_preferred", [](double f) { return 0.5 * f; }, py::arg("f"));
    m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());
325
326
    m.def("ints_preferred", [](int i) { return i / 2; }, py::arg("i"));
    m.def("ints_only", [](int i) { return i / 2; }, py::arg("i").noconvert());
327

328
329
330
331
332
333
334
    /// Issue/PR #648: bad arg default debugging output
#if !defined(NDEBUG)
    m.attr("debug_enabled") = true;
#else
    m.attr("debug_enabled") = false;
#endif
    m.def("bad_arg_def_named", []{
Jason Rhinelander's avatar
Jason Rhinelander committed
335
        auto m = py::module::import("pybind11_tests");
336
337
338
        m.def("should_fail", [](int, NotRegistered) {}, py::arg(), py::arg("a") = NotRegistered());
    });
    m.def("bad_arg_def_unnamed", []{
Jason Rhinelander's avatar
Jason Rhinelander committed
339
        auto m = py::module::import("pybind11_tests");
340
341
        m.def("should_fail", [](int, NotRegistered) {}, py::arg(), py::arg() = NotRegistered());
    });
342
343
344
345
346
347
348
349
350
351
352
353
354
355

    py::class_<NoneTester, std::shared_ptr<NoneTester>>(m, "NoneTester")
        .def(py::init<>());
    m.def("no_none1", &none1, py::arg().none(false));
    m.def("no_none2", &none2, py::arg().none(false));
    m.def("no_none3", &none3, py::arg().none(false));
    m.def("no_none4", &none4, py::arg().none(false));
    m.def("no_none5", &none5, py::arg().none(false));
    m.def("ok_none1", &none1);
    m.def("ok_none2", &none2, py::arg().none(true));
    m.def("ok_none3", &none3);
    m.def("ok_none4", &none4, py::arg().none(true));
    m.def("ok_none5", &none5);

356
357
358
359
360
361
362
    // Issue #283: __str__ called on uninitialized instance when constructor arguments invalid
    py::class_<StrIssue>(m, "StrIssue")
        .def(py::init<int>())
        .def(py::init<>())
        .def("__str__", [](const StrIssue &si) {
            return "StrIssue[" + std::to_string(si.val) + "]"; }
        );
363
});