Skip to content

Commit 708118a

Browse files
committed
[lldb] Handle staticmethod/classmethod descriptors in ScriptedPythonInterface (llvm#170188)
Extract `__func__` attribute from staticmethod/classmethod descriptors before treating them as callables. Python's `@staticmethod` and `@classmethod` decorators wrap methods in descriptor objects that are not directly usable as PythonCallable, when calling PyCallable_Check. The actual callable function is stored in the `__func__` attribute of these descriptors, so we need to unwrap them to properly validate and invoke the decorated methods in scripted interfaces. Signed-off-by: Med Ismail Bennani <[email protected]> (cherry picked from commit 3ca85e7)
1 parent 7b2b018 commit 708118a

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
7474
if (!class_dict.HasKey(method_name))
7575
SET_CASE_AND_CONTINUE(method_name,
7676
AbstractMethodCheckerCases::eNotImplemented)
77-
auto callable_or_err = class_dict.GetItem(method_name);
77+
llvm::Expected<PythonObject> callable_or_err =
78+
class_dict.GetItem(method_name);
7879
if (!callable_or_err) {
7980
llvm::consumeError(callable_or_err.takeError());
8081
SET_CASE_AND_CONTINUE(method_name,

lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,17 @@ bool PythonCallable::Check(PyObject *py_obj) {
805805
if (!py_obj)
806806
return false;
807807

808+
PythonObject python_obj(PyRefType::Borrowed, py_obj);
809+
810+
// Handle staticmethod/classmethod descriptors by extracting the
811+
// `__func__` attribute.
812+
if (python_obj.HasAttribute("__func__")) {
813+
PythonObject function_obj = python_obj.GetAttributeValue("__func__");
814+
if (!function_obj.IsAllocated())
815+
return false;
816+
return PyCallable_Check(function_obj.release());
817+
}
818+
808819
return PyCallable_Check(py_obj);
809820
}
810821

0 commit comments

Comments
 (0)