mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 21:25:13 +00:00
Don't allow mixed static/non-static overloads
We currently fail at runtime when trying to call a method that is overloaded with both static and non-static methods. This is something python won't allow: the object is either a function or an instance, and can't be both.
This commit is contained in:
parent
90bac96321
commit
d355f2fcca
@ -318,6 +318,15 @@ protected:
|
|||||||
m_ptr = rec->sibling.ptr();
|
m_ptr = rec->sibling.ptr();
|
||||||
inc_ref();
|
inc_ref();
|
||||||
chain_start = chain;
|
chain_start = chain;
|
||||||
|
if (chain->is_method != rec->is_method)
|
||||||
|
pybind11_fail("overloading a method with both static and instance methods is not supported; "
|
||||||
|
#if defined(NDEBUG)
|
||||||
|
"compile in debug mode for more details"
|
||||||
|
#else
|
||||||
|
"error while attempting to bind " + std::string(rec->is_method ? "instance" : "static") + " method " +
|
||||||
|
std::string(pybind11::str(rec->scope.attr("__name__"))) + "." + std::string(rec->name) + signature
|
||||||
|
#endif
|
||||||
|
);
|
||||||
while (chain->next)
|
while (chain->next)
|
||||||
chain = chain->next;
|
chain = chain->next;
|
||||||
chain->next = rec;
|
chain->next = rec;
|
||||||
|
@ -59,6 +59,8 @@ public:
|
|||||||
py::str overloaded(int, int) const { return "(int, int) const"; }
|
py::str overloaded(int, int) const { return "(int, int) const"; }
|
||||||
py::str overloaded(float, float) const { return "(float, float) const"; }
|
py::str overloaded(float, float) const { return "(float, float) const"; }
|
||||||
|
|
||||||
|
static py::str overloaded() { return "static"; }
|
||||||
|
|
||||||
int value = 0;
|
int value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -206,6 +208,17 @@ test_initializer methods_and_attributes([](py::module &m) {
|
|||||||
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int, 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))
|
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, float) const>(&ExampleMandA::overloaded))
|
||||||
#endif
|
#endif
|
||||||
|
// 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));
|
||||||
|
})
|
||||||
.def("__str__", &ExampleMandA::toString)
|
.def("__str__", &ExampleMandA::toString)
|
||||||
.def_readwrite("value", &ExampleMandA::value);
|
.def_readwrite("value", &ExampleMandA::value);
|
||||||
|
|
||||||
|
@ -148,6 +148,28 @@ def test_metaclass_override():
|
|||||||
assert isinstance(MetaclassOverride.__dict__["readonly"], int)
|
assert isinstance(MetaclassOverride.__dict__["readonly"], int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_mixed_overloads():
|
||||||
|
from pybind11_tests import debug_enabled
|
||||||
|
|
||||||
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
|
ExampleMandA.add_mixed_overloads1()
|
||||||
|
assert (str(excinfo.value) ==
|
||||||
|
"overloading a method with both static and instance methods is not supported; " +
|
||||||
|
("compile in debug mode for more details" if not debug_enabled else
|
||||||
|
"error while attempting to bind static method ExampleMandA.overload_mixed1"
|
||||||
|
"() -> str")
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
|
ExampleMandA.add_mixed_overloads2()
|
||||||
|
assert (str(excinfo.value) ==
|
||||||
|
"overloading a method with both static and instance methods is not supported; " +
|
||||||
|
("compile in debug mode for more details" if not debug_enabled else
|
||||||
|
"error while attempting to bind instance method ExampleMandA.overload_mixed2"
|
||||||
|
"(self: pybind11_tests.ExampleMandA, arg0: int, arg1: int) -> str")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
|
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
|
||||||
def test_property_return_value_policies(access):
|
def test_property_return_value_policies(access):
|
||||||
from pybind11_tests import TestPropRVP
|
from pybind11_tests import TestPropRVP
|
||||||
|
Loading…
Reference in New Issue
Block a user