Okay, here is my working example. I actually couldn't figure out to call the imported python function with a Python C Type, so I just went straight to the C API, which should perform better anyway
struct Foobar {
Foobar() {}
void foo(int32_t art) {}
};
PYBIND11_MODULE(example, m) {
pybind11::class_<Foobar>(m, "PyFoobar")
.def(py::init<>())
.def("old_foo",
[](pybind11::object &self, int arg_to_foo)
{
PyErr_WarnEx(PyExc_DeprecationWarning,
"old_foo() is deprecated, use new_foo() instead.",
1);
return self.attr("new_foo")(arg_to_foo);
})
.def("new_foo", &Foobar::foo);
}
You can pass any of the warning types from here as the first argument:
https://docs.python.org/3/c-api/exceptions.html#standard-warning-categories
The final int is the level of the stack that you want to be flagged as being deprecated.
So looking at this python code
import example
import warnings
warnings.simplefilter("default")
def mary():
f = example.PyFoobar()
f.old_foo(1)
mary()
If you set the stack level to 1
you'll get
test.py:9: DeprecationWarning: old_foo() is deprecated, use new_foo() instead.
f.old_foo(1)
You might want 2
which will give you the actual calling context, but depends on what your use case is
test.py:11: DeprecationWarning: old_foo() is deprecated, use new_foo() instead.
mary()
It is also important to note that by default, many versions of python have Deprecation warnings turned off. You can check this by checking the value of
warnings.filters
. That is why in my example I have the call to warnings.simplefilter("default")
which enables all types of warnings, but only the first time they are hit. There are other ways you can control this as well, including using the -W
flag when running python or an environment variable.
https://docs.python.org/3/library/warnings.html#describing-warning-filters