Skip to content

Commit 61c7699

Browse files
test it
1 parent 1e6b024 commit 61c7699

File tree

7 files changed

+36
-117
lines changed

7 files changed

+36
-117
lines changed

include/pybind11/detail/class.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,21 +165,6 @@ extern "C" inline int pybind11_meta_setattro(PyObject *obj, PyObject *name, PyOb
165165
}
166166
}
167167

168-
/**
169-
* Python 3's PyInstanceMethod_Type hides itself via its tp_descr_get, which prevents aliasing
170-
* methods via cls.attr("m2") = cls.attr("m1"): instead the tp_descr_get returns a plain function,
171-
* when called on a class, or a PyMethod, when called on an instance. Override that behaviour here
172-
* to do a special case bypass for PyInstanceMethod_Types.
173-
*/
174-
extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name) {
175-
PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
176-
if (descr && PyInstanceMethod_Check(descr)) {
177-
Py_INCREF(descr);
178-
return descr;
179-
}
180-
return PyType_Type.tp_getattro(obj, name);
181-
}
182-
183168
/// metaclass `__call__` function that is used to create all pybind11 objects.
184169
extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, PyObject *kwargs) {
185170

@@ -274,7 +259,6 @@ inline PyTypeObject *make_default_metaclass() {
274259
type->tp_call = pybind11_meta_call;
275260

276261
type->tp_setattro = pybind11_meta_setattro;
277-
type->tp_getattro = pybind11_meta_getattro;
278262

279263
type->tp_dealloc = pybind11_meta_dealloc;
280264

include/pybind11/detail/common.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,6 @@
274274
// behavior.
275275

276276
/// Compatibility macros for Python 2 / Python 3 versions TODO: remove
277-
#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
278-
#define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check
279-
#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION
280277
#define PYBIND11_BYTES_CHECK PyBytes_Check
281278
#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString
282279
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize

include/pybind11/detail/function_record.h

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -602,53 +602,22 @@ inline handle create_pybind_function_overload_set(handle existing_function) {
602602
return create_pybind_function<function_overload_set>(existing_function);
603603
}
604604

605-
inline handle
606-
combine_functions(handle existing_function, handle new_function, bool prepend, bool is_method) {
607-
// TODO: InstanceMethod here is very inefficient
605+
inline handle combine_functions(handle existing_function, handle new_function, bool prepend) {
608606
pybind_function *new_wrapper = (pybind_function *) new_function.ptr();
609607

610-
bool pulled_from_instance_method = false;
611-
if (PyInstanceMethod_Check(existing_function.ptr())) {
612-
pulled_from_instance_method = true;
613-
existing_function = PyInstanceMethod_GET_FUNCTION(existing_function.ptr());
614-
}
615-
616608
if (!PyObject_TypeCheck(existing_function.ptr(), pybind_function_type())) {
617609
if (!existing_function.is_none() && new_wrapper->name[0] != '_') {
618610
pybind11_fail(std::string("Found an existing object when trying to defined function ")
619611
+ new_wrapper->name);
620612
}
621613

622-
if (is_method) {
623-
return PyInstanceMethod_New(new_function.ptr());
624-
}
625614
return new_function.ptr();
626615
}
627616

628-
if (is_method != pulled_from_instance_method) {
629-
pybind11_fail(
630-
"overloading a method with both static and instance methods is not supported; "
631-
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
632-
"#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for more "
633-
"details"
634-
#else
635-
"error while attempting to bind "
636-
+ std::string(is_method ? "instance" : "static") + " method "
637-
+ std::string(pybind11::str(
638-
((handle) ((PyObject *) new_wrapper->current_scope)).attr("__name__")))
639-
+ "." + std::string(new_wrapper->name) + new_wrapper->signature
640-
#endif
641-
);
642-
}
643-
644617
pybind_function *wrapper = (pybind_function *) existing_function.ptr();
645618

646619
if (wrapper->current_scope != new_wrapper->current_scope) {
647-
if (is_method) {
648-
return PyInstanceMethod_New(new_function.ptr());
649-
} else {
650-
return new_function.ptr();
651-
}
620+
return new_function.ptr();
652621
}
653622

654623
if (!wrapper->is_overload_set) {
@@ -663,10 +632,6 @@ combine_functions(handle existing_function, handle new_function, bool prepend, b
663632

664633
wrapper->doc = wrapped->doc.c_str();
665634

666-
if (is_method) {
667-
return PyInstanceMethod_New(existing_function.ptr());
668-
}
669-
670635
return existing_function;
671636
}
672637

include/pybind11/detail/internal_pytypes.h

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "vendor/optional.h"
77

88
#include <array>
9+
#include <iostream>
910

1011
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1112
PYBIND11_NAMESPACE_BEGIN(detail)
@@ -207,11 +208,20 @@ struct pybind_function_type_data {
207208

208209
set_vectorcall_set_offset(type, offsetof(pybind_function, vectorcall));
209210

210-
type.tp_flags = Py_TPFLAGS_DEFAULT | pybind_vectorcall_flag;
211+
type.tp_flags = Py_TPFLAGS_METHOD_DESCRIPTOR | Py_TPFLAGS_DEFAULT | pybind_vectorcall_flag;
211212

212-
type.tp_descr_get = [](PyObject *, PyObject *, PyObject *) -> PyObject * {
213-
printf("Shouldn't be calling this\n");
214-
abort();
213+
type.tp_descr_get = [](PyObject *self, PyObject *obj, PyObject *) -> PyObject * {
214+
// std::cout << "Ideally shouldn't be calling tp_descr_get ... " << obj << std::endl;
215+
if (obj == nullptr) {
216+
Py_INCREF(self);
217+
return self;
218+
} else {
219+
PyObject *result_method = PyMethod_New(self, obj);
220+
if (result_method == nullptr) {
221+
pybind11_fail("Could not create method binder");
222+
}
223+
return result_method;
224+
}
215225
};
216226

217227
int ret = PyType_Ready(&type);
@@ -245,20 +255,6 @@ handle create_pybind_function(Args &&...args) {
245255
return (PyObject *) om;
246256
}
247257

248-
inline bool is_pybind_function(handle func) {
249-
if (!func) {
250-
return false;
251-
}
252-
if (PyMethod_Check(func.ptr())) {
253-
func = PyMethod_Function(func.ptr());
254-
}
255-
if (PyInstanceMethod_Check(func.ptr())) {
256-
func = PyInstanceMethod_GET_FUNCTION(func.ptr());
257-
}
258-
259-
return PyObject_TypeCheck(func.ptr(), pybind_function_type());
260-
}
261-
262258
inline void append_note_if_missing_header_is_suspected(std::string &msg) {
263259
if (msg.find("std::") != std::string::npos) {
264260
msg += "\n\n"

include/pybind11/pybind11.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,10 @@ class cpp_function : public function {
128128
sibling sib = std::get<sibling_index>(std::forward_as_tuple(extra..., sibling(none())));
129129

130130
bool has_prepend = detail::any_of<std::is_same<prepend, Extra>...>::value;
131-
bool has_is_method = detail::any_of<std::is_same<is_method, Extra>...>::value;
132131

133132
handle new_function
134133
= detail::create_pybind_function_wrapper(std::forward<Func>(f), a, extra...);
135-
m_ptr
136-
= detail::combine_functions(sib.value, new_function, has_prepend, has_is_method).ptr();
134+
m_ptr = detail::combine_functions(sib.value, new_function, has_prepend).ptr();
137135
}
138136
};
139137

@@ -1665,6 +1663,22 @@ inline const char *error_already_set::what() const noexcept {
16651663

16661664
PYBIND11_NAMESPACE_BEGIN(detail)
16671665

1666+
inline bool is_pybind11_function(const function &func) {
1667+
PyObject *ptr = func.ptr();
1668+
if (ptr == nullptr) {
1669+
return false;
1670+
}
1671+
1672+
if (PyMethod_Check(ptr)) {
1673+
ptr = PyMethod_GET_FUNCTION(ptr);
1674+
if (ptr == nullptr) {
1675+
return false;
1676+
}
1677+
}
1678+
1679+
return PyObject_TypeCheck(ptr, pybind_function_type());
1680+
}
1681+
16681682
inline function
16691683
get_type_override(const void *this_ptr, const type_info *this_type, const char *name) {
16701684
handle self = get_object_handle(this_ptr, this_type);
@@ -1683,14 +1697,14 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
16831697

16841698
function override = getattr(self, name, function());
16851699

1686-
if (detail::is_pybind_function(override)) {
1700+
if (is_pybind11_function(override)) {
16871701
// TODO: Fix this
16881702
cache.insert(std::move(key));
16891703
return function();
16901704
}
16911705

1692-
/* Don't call dispatch code if invoked from overridden function.
1693-
Unfortunately this doesn't work on PyPy. */
1706+
/* Don't call dispatch code if invoked from overridden function.
1707+
Unfortunately this doesn't work on PyPy. */
16941708
#if !defined(PYPY_VERSION)
16951709
# if PY_VERSION_HEX >= 0x03090000
16961710
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());

include/pybind11/pytypes.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -824,16 +824,6 @@ inline ssize_t hash(handle obj) {
824824
/// @} python_builtins
825825

826826
PYBIND11_NAMESPACE_BEGIN(detail)
827-
inline handle get_function(handle value) {
828-
if (value) {
829-
if (PyInstanceMethod_Check(value.ptr())) {
830-
value = PyInstanceMethod_GET_FUNCTION(value.ptr());
831-
} else if (PyMethod_Check(value.ptr())) {
832-
value = PyMethod_GET_FUNCTION(value.ptr());
833-
}
834-
}
835-
return value;
836-
}
837827

838828
// Reimplementation of python's dict helper functions to ensure that exceptions
839829
// aren't swallowed (see #2862)

tests/test_methods_and_attributes.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -227,33 +227,6 @@ def test_metaclass_override():
227227
assert isinstance(m.MetaclassOverride.__dict__["readonly"], int)
228228

229229

230-
def test_no_mixed_overloads():
231-
from pybind11_tests import detailed_error_messages_enabled
232-
233-
with pytest.raises(RuntimeError) as excinfo:
234-
m.ExampleMandA.add_mixed_overloads1()
235-
assert str(
236-
excinfo.value
237-
) == "overloading a method with both static and instance methods is not supported; " + (
238-
"#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for more details"
239-
if not detailed_error_messages_enabled
240-
else "error while attempting to bind static method ExampleMandA.overload_mixed1"
241-
"(arg0: float) -> str"
242-
)
243-
244-
with pytest.raises(RuntimeError) as excinfo:
245-
m.ExampleMandA.add_mixed_overloads2()
246-
assert str(
247-
excinfo.value
248-
) == "overloading a method with both static and instance methods is not supported; " + (
249-
"#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for more details"
250-
if not detailed_error_messages_enabled
251-
else "error while attempting to bind instance method ExampleMandA.overload_mixed2"
252-
"(self: pybind11_tests.methods_and_attributes.ExampleMandA, arg0: int, arg1: int)"
253-
" -> str"
254-
)
255-
256-
257230
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
258231
def test_property_return_value_policies(access):
259232
if not access.startswith("static"):

0 commit comments

Comments
 (0)