mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
Ignore deprecation warnings about old-style __init__/__setstate__ constructors in the tests (originally done in #2746) (#2759)
* Ignore old-style __init__ warnings * Simplify ignoreOldStyleInitWarnings with py::exec * Only wrap single class_::defs to ignore DeprecationWarnings about old-style __init__
This commit is contained in:
parent
e57dd4717e
commit
98f1bbb800
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/eval.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||||
// We get some really long type names here which causes MSVC 2015 to emit warnings
|
// We get some really long type names here which causes MSVC 2015 to emit warnings
|
||||||
@ -69,3 +70,15 @@ public:
|
|||||||
};
|
};
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
PYBIND11_NAMESPACE_END(pybind11)
|
PYBIND11_NAMESPACE_END(pybind11)
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
void ignoreOldStyleInitWarnings(F &&body) {
|
||||||
|
py::exec(R"(
|
||||||
|
message = "pybind11-bound class '.+' is using an old-style placement-new '(?:__init__|__setstate__)' which has been deprecated"
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.filterwarnings("ignore", message=message, category=FutureWarning)
|
||||||
|
body()
|
||||||
|
)", py::dict(py::arg("body") = py::cpp_function(body)));
|
||||||
|
}
|
||||||
|
@ -183,11 +183,14 @@ TEST_SUBMODULE(factory_constructors, m) {
|
|||||||
auto c4a = [c](pointer_tag, TF4_tag, int a) { (void) c; return new TestFactory4(a);};
|
auto c4a = [c](pointer_tag, TF4_tag, int a) { (void) c; return new TestFactory4(a);};
|
||||||
|
|
||||||
// test_init_factory_basic, test_init_factory_casting
|
// test_init_factory_basic, test_init_factory_casting
|
||||||
py::class_<TestFactory3, std::shared_ptr<TestFactory3>>(m, "TestFactory3")
|
py::class_<TestFactory3, std::shared_ptr<TestFactory3>> pyTestFactory3(m, "TestFactory3");
|
||||||
|
pyTestFactory3
|
||||||
.def(py::init([](pointer_tag, int v) { return TestFactoryHelper::construct3(v); }))
|
.def(py::init([](pointer_tag, int v) { return TestFactoryHelper::construct3(v); }))
|
||||||
.def(py::init([](shared_ptr_tag) { return TestFactoryHelper::construct3(); }))
|
.def(py::init([](shared_ptr_tag) { return TestFactoryHelper::construct3(); }));
|
||||||
.def("__init__", [](TestFactory3 &self, std::string v) { new (&self) TestFactory3(v); }) // placement-new ctor
|
ignoreOldStyleInitWarnings([&pyTestFactory3]() {
|
||||||
|
pyTestFactory3.def("__init__", [](TestFactory3 &self, std::string v) { new (&self) TestFactory3(v); }); // placement-new ctor
|
||||||
|
});
|
||||||
|
pyTestFactory3
|
||||||
// factories returning a derived type:
|
// factories returning a derived type:
|
||||||
.def(py::init(c4a)) // derived ptr
|
.def(py::init(c4a)) // derived ptr
|
||||||
.def(py::init([](pointer_tag, TF5_tag, int a) { return new TestFactory5(a); }))
|
.def(py::init([](pointer_tag, TF5_tag, int a) { return new TestFactory5(a); }))
|
||||||
@ -304,24 +307,32 @@ TEST_SUBMODULE(factory_constructors, m) {
|
|||||||
static void operator delete(void *p) { py::print("noisy delete"); ::operator delete(p); }
|
static void operator delete(void *p) { py::print("noisy delete"); ::operator delete(p); }
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
py::class_<NoisyAlloc>(m, "NoisyAlloc")
|
|
||||||
|
|
||||||
|
py::class_<NoisyAlloc> pyNoisyAlloc(m, "NoisyAlloc");
|
||||||
// Since these overloads have the same number of arguments, the dispatcher will try each of
|
// Since these overloads have the same number of arguments, the dispatcher will try each of
|
||||||
// them until the arguments convert. Thus we can get a pre-allocation here when passing a
|
// them until the arguments convert. Thus we can get a pre-allocation here when passing a
|
||||||
// single non-integer:
|
// single non-integer:
|
||||||
.def("__init__", [](NoisyAlloc *a, int i) { new (a) NoisyAlloc(i); }) // Regular constructor, runs first, requires preallocation
|
ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
|
||||||
.def(py::init([](double d) { return new NoisyAlloc(d); }))
|
pyNoisyAlloc.def("__init__", [](NoisyAlloc *a, int i) { new (a) NoisyAlloc(i); }); // Regular constructor, runs first, requires preallocation
|
||||||
|
});
|
||||||
|
|
||||||
// The two-argument version: first the factory pointer overload.
|
pyNoisyAlloc.def(py::init([](double d) { return new NoisyAlloc(d); }));
|
||||||
.def(py::init([](int i, int) { return new NoisyAlloc(i); }))
|
|
||||||
// Return-by-value:
|
// The two-argument version: first the factory pointer overload.
|
||||||
.def(py::init([](double d, int) { return NoisyAlloc(d); }))
|
pyNoisyAlloc.def(py::init([](int i, int) { return new NoisyAlloc(i); }));
|
||||||
// Old-style placement new init; requires preallocation
|
// Return-by-value:
|
||||||
.def("__init__", [](NoisyAlloc &a, double d, double) { new (&a) NoisyAlloc(d); })
|
pyNoisyAlloc.def(py::init([](double d, int) { return NoisyAlloc(d); }));
|
||||||
// Requires deallocation of previous overload preallocated value:
|
// Old-style placement new init; requires preallocation
|
||||||
.def(py::init([](int i, double) { return new NoisyAlloc(i); }))
|
ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
|
||||||
// Regular again: requires yet another preallocation
|
pyNoisyAlloc.def("__init__", [](NoisyAlloc &a, double d, double) { new (&a) NoisyAlloc(d); });
|
||||||
.def("__init__", [](NoisyAlloc &a, int i, std::string) { new (&a) NoisyAlloc(i); })
|
});
|
||||||
;
|
// Requires deallocation of previous overload preallocated value:
|
||||||
|
pyNoisyAlloc.def(py::init([](int i, double) { return new NoisyAlloc(i); }));
|
||||||
|
// Regular again: requires yet another preallocation
|
||||||
|
ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
|
||||||
|
pyNoisyAlloc.def("__init__", [](NoisyAlloc &a, int i, std::string) { new (&a) NoisyAlloc(i); });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@ TEST_SUBMODULE(pickling, m) {
|
|||||||
using Pickleable::Pickleable;
|
using Pickleable::Pickleable;
|
||||||
};
|
};
|
||||||
|
|
||||||
py::class_<Pickleable>(m, "Pickleable")
|
py::class_<Pickleable> pyPickleable(m, "Pickleable");
|
||||||
|
pyPickleable
|
||||||
.def(py::init<std::string>())
|
.def(py::init<std::string>())
|
||||||
.def("value", &Pickleable::value)
|
.def("value", &Pickleable::value)
|
||||||
.def("extra1", &Pickleable::extra1)
|
.def("extra1", &Pickleable::extra1)
|
||||||
@ -43,17 +44,20 @@ TEST_SUBMODULE(pickling, m) {
|
|||||||
.def("__getstate__", [](const Pickleable &p) {
|
.def("__getstate__", [](const Pickleable &p) {
|
||||||
/* Return a tuple that fully encodes the state of the object */
|
/* Return a tuple that fully encodes the state of the object */
|
||||||
return py::make_tuple(p.value(), p.extra1(), p.extra2());
|
return py::make_tuple(p.value(), p.extra1(), p.extra2());
|
||||||
})
|
|
||||||
.def("__setstate__", [](Pickleable &p, py::tuple t) {
|
|
||||||
if (t.size() != 3)
|
|
||||||
throw std::runtime_error("Invalid state!");
|
|
||||||
/* Invoke the constructor (need to use in-place version) */
|
|
||||||
new (&p) Pickleable(t[0].cast<std::string>());
|
|
||||||
|
|
||||||
/* Assign any additional state */
|
|
||||||
p.setExtra1(t[1].cast<int>());
|
|
||||||
p.setExtra2(t[2].cast<int>());
|
|
||||||
});
|
});
|
||||||
|
ignoreOldStyleInitWarnings([&pyPickleable]() {
|
||||||
|
pyPickleable
|
||||||
|
.def("__setstate__", [](Pickleable &p, py::tuple t) {
|
||||||
|
if (t.size() != 3)
|
||||||
|
throw std::runtime_error("Invalid state!");
|
||||||
|
/* Invoke the constructor (need to use in-place version) */
|
||||||
|
new (&p) Pickleable(t[0].cast<std::string>());
|
||||||
|
|
||||||
|
/* Assign any additional state */
|
||||||
|
p.setExtra1(t[1].cast<int>());
|
||||||
|
p.setExtra2(t[2].cast<int>());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
py::class_<PickleableNew, Pickleable>(m, "PickleableNew")
|
py::class_<PickleableNew, Pickleable>(m, "PickleableNew")
|
||||||
.def(py::init<std::string>())
|
.def(py::init<std::string>())
|
||||||
@ -87,27 +91,31 @@ TEST_SUBMODULE(pickling, m) {
|
|||||||
using PickleableWithDict::PickleableWithDict;
|
using PickleableWithDict::PickleableWithDict;
|
||||||
};
|
};
|
||||||
|
|
||||||
py::class_<PickleableWithDict>(m, "PickleableWithDict", py::dynamic_attr())
|
py::class_<PickleableWithDict> pyPickleableWithDict(m, "PickleableWithDict", py::dynamic_attr());
|
||||||
|
pyPickleableWithDict
|
||||||
.def(py::init<std::string>())
|
.def(py::init<std::string>())
|
||||||
.def_readwrite("value", &PickleableWithDict::value)
|
.def_readwrite("value", &PickleableWithDict::value)
|
||||||
.def_readwrite("extra", &PickleableWithDict::extra)
|
.def_readwrite("extra", &PickleableWithDict::extra)
|
||||||
.def("__getstate__", [](py::object self) {
|
.def("__getstate__", [](py::object self) {
|
||||||
/* Also include __dict__ in state */
|
/* Also include __dict__ in state */
|
||||||
return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
|
return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
|
||||||
})
|
|
||||||
.def("__setstate__", [](py::object self, py::tuple t) {
|
|
||||||
if (t.size() != 3)
|
|
||||||
throw std::runtime_error("Invalid state!");
|
|
||||||
/* Cast and construct */
|
|
||||||
auto& p = self.cast<PickleableWithDict&>();
|
|
||||||
new (&p) PickleableWithDict(t[0].cast<std::string>());
|
|
||||||
|
|
||||||
/* Assign C++ state */
|
|
||||||
p.extra = t[1].cast<int>();
|
|
||||||
|
|
||||||
/* Assign Python state */
|
|
||||||
self.attr("__dict__") = t[2];
|
|
||||||
});
|
});
|
||||||
|
ignoreOldStyleInitWarnings([&pyPickleableWithDict]() {
|
||||||
|
pyPickleableWithDict
|
||||||
|
.def("__setstate__", [](py::object self, py::tuple t) {
|
||||||
|
if (t.size() != 3)
|
||||||
|
throw std::runtime_error("Invalid state!");
|
||||||
|
/* Cast and construct */
|
||||||
|
auto& p = self.cast<PickleableWithDict&>();
|
||||||
|
new (&p) PickleableWithDict(t[0].cast<std::string>());
|
||||||
|
|
||||||
|
/* Assign C++ state */
|
||||||
|
p.extra = t[1].cast<int>();
|
||||||
|
|
||||||
|
/* Assign Python state */
|
||||||
|
self.attr("__dict__") = t[2];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
py::class_<PickleableWithDictNew, PickleableWithDict>(m, "PickleableWithDictNew")
|
py::class_<PickleableWithDictNew, PickleableWithDict>(m, "PickleableWithDictNew")
|
||||||
.def(py::init<std::string>())
|
.def(py::init<std::string>())
|
||||||
|
Loading…
Reference in New Issue
Block a user