Begin converting uses of PyCallable to PythonCallable.

PyCallable is a class that exists solely within the swig wrapper
code.  PythonCallable is a more generic implementation of the same
idea that can be used by any Python-related interop code, and lives
in PythonDataObjects.h

The CL is mostly mechanical, and it doesn't cover every possible
user of PyCallable, because I want to minimize the impact of this
change (as well as making it easier to figure out what went wrong
in case this causes a failure).  I plan to finish up the rest of
the changes in a subsequent patch, culminating in the removal of
PyCallable entirely.

llvm-svn: 252906
This commit is contained in:
Zachary Turner 2015-11-12 16:23:16 +00:00
parent 183c010c9a
commit b58fb2f47a
3 changed files with 206 additions and 228 deletions

View File

@ -191,21 +191,19 @@ LLDBSwigPythonBreakpointCallbackFunction
bool stop_at_breakpoint = true; bool stop_at_breakpoint = true;
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PythonDictionary dict = PythonModule::MainModule().ResolveName(session_dictionary_name).AsType<PythonDictionary>(); auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,dict.get()); if (!pfunc.IsAllocated())
if (!pfunc)
return stop_at_breakpoint; return stop_at_breakpoint;
PyObject* pvalue = NULL; PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
pvalue = pfunc(sb_frame, sb_bp_loc, dict.get()); PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc));
PythonObject result = pfunc(frame_arg, bp_loc_arg, dict);
if (pvalue == Py_False) if (result.get() == Py_False)
stop_at_breakpoint = false; stop_at_breakpoint = false;
Py_XDECREF (pvalue);
return stop_at_breakpoint; return stop_at_breakpoint;
} }
@ -229,21 +227,19 @@ LLDBSwigPythonWatchpointCallbackFunction
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PythonDictionary dict = PythonModule::MainModule().ResolveName(session_dictionary_name).AsType<PythonDictionary>(); auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,dict.get()); if (!pfunc.IsAllocated())
if (!pfunc)
return stop_at_watchpoint; return stop_at_watchpoint;
PyObject* pvalue = NULL; PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
pvalue = pfunc(sb_frame, sb_wp, dict.get()); PythonObject wp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_wp));
PythonObject result = pfunc(frame_arg, wp_arg, dict);
if (pvalue == Py_False) if (result.get() == Py_False)
stop_at_watchpoint = false; stop_at_watchpoint = false;
Py_XDECREF (pvalue);
return stop_at_watchpoint; return stop_at_watchpoint;
} }
@ -294,7 +290,7 @@ LLDBSwigPythonCallTypeScript
if (!python_function_name || !session_dictionary) if (!python_function_name || !session_dictionary)
return false; return false;
PyObject *pfunc_impl = NULL, *pvalue = NULL; PyObject *pfunc_impl = nullptr;
if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper)) if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper))
{ {
@ -314,33 +310,33 @@ LLDBSwigPythonCallTypeScript
PyErr_Cleaner pyerr_cleanup(true); // show Python errors PyErr_Cleaner pyerr_cleanup(true); // show Python errors
if (!pfunc_impl) PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl);
if (!pfunc.IsAllocated())
{ {
pfunc_impl = PythonObject::ResolveNameWithDictionary(python_function_name, dict).release(); pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
if (!pfunc_impl || !PyCallable_Check (pfunc_impl)) if (!pfunc.IsAllocated())
return false; return false;
else
if (pyfunct_wrapper)
{ {
if (pyfunct_wrapper) *pyfunct_wrapper = pfunc.get();
*pyfunct_wrapper = pfunc_impl; Py_XINCREF(pfunc.get());
} }
} }
PyCallable pfunc = PyCallable::FindWithPythonObject(pfunc_impl); PythonObject result;
auto argc = pfunc.GetNumArguments();
if (!pfunc)
return false;
// if the third argument is supported, or varargs are allowed // if the third argument is supported, or varargs are allowed
PyCallable::argc argc = pfunc.GetNumArguments(); PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value));
if (argc.num_args == 3 || argc.varargs == true) PythonObject options_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_options));
pvalue = pfunc(sb_value,dict.get(),sb_options); if (argc.count == 3 || argc.has_varargs)
result = pfunc(value_arg,dict,options_arg);
else else
pvalue = pfunc(sb_value,dict.get()); result = pfunc(value_arg,dict);
PyObjectToString(pvalue,retval); PyObjectToString(result.get(), retval);
Py_XDECREF (pvalue);
return true; return true;
} }
@ -353,38 +349,33 @@ LLDBSwigPythonCreateSyntheticProvider
) )
{ {
using namespace lldb_private; using namespace lldb_private;
PyObject* retval = NULL;
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE; Py_RETURN_NONE;
PyErr_Cleaner py_err_cleaner(true);
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name,dict);
if (!pfunc.IsAllocated())
Py_RETURN_NONE;
// I do not want the SBValue to be deallocated when going out of scope because python // I do not want the SBValue to be deallocated when going out of scope because python
// has ownership of it and will manage memory for this object by itself // has ownership of it and will manage memory for this object by itself
lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp); lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp);
sb_value->SetPreferSyntheticValue(false); sb_value->SetPreferSyntheticValue(false);
PyObject *ValObj_PyObj = SBTypeToSWIGWrapper(sb_value);
if (ValObj_PyObj == NULL) PythonObject val_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value));
if (!val_arg.IsAllocated())
Py_RETURN_NONE; Py_RETURN_NONE;
PyErr_Cleaner py_err_cleaner(true); PythonObject result = pfunc(val_arg, dict);
PythonDictionary dict = PythonModule::MainModule().ResolveName(session_dictionary_name).AsType<PythonDictionary>(); if (result.IsAllocated())
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,dict.get()); return result.release();
if (!pfunc) Py_RETURN_NONE;
return retval;
Py_INCREF(ValObj_PyObj);
retval = pfunc(sb_value, dict.get());
Py_XINCREF(retval);
if (retval)
return retval;
else
Py_RETURN_NONE;
} }
SWIGEXPORT void* SWIGEXPORT void*
@ -396,28 +387,25 @@ LLDBSwigPythonCreateCommandObject
) )
{ {
using namespace lldb_private; using namespace lldb_private;
PyObject* retval = NULL;
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE; Py_RETURN_NONE;
lldb::SBDebugger debugger_sb(debugger_sp);
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PythonDictionary dict = PythonModule::MainModule().ResolveName(session_dictionary_name).AsType<PythonDictionary>(); auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,dict.get()); auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
if (!pfunc) if (!pfunc.IsAllocated())
return retval; return nullptr;
retval = pfunc(debugger_sb, dict.get()); lldb::SBDebugger debugger_sb(debugger_sp);
PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
PythonObject result = pfunc(debugger_arg, dict);
Py_XINCREF(retval); if (result.IsAllocated())
return result.release();
if (retval) Py_RETURN_NONE;
return retval;
else
Py_RETURN_NONE;
} }
SWIGEXPORT void* SWIGEXPORT void*
@ -429,7 +417,6 @@ LLDBSwigPythonCreateScriptedThreadPlan
) )
{ {
using namespace lldb_private; using namespace lldb_private;
PyObject* retval = NULL;
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE; Py_RETURN_NONE;
@ -438,32 +425,26 @@ LLDBSwigPythonCreateScriptedThreadPlan
// has ownership of it and will manage memory for this object by itself // has ownership of it and will manage memory for this object by itself
lldb::SBThreadPlan *tp_value = new lldb::SBThreadPlan(thread_plan_sp); lldb::SBThreadPlan *tp_value = new lldb::SBThreadPlan(thread_plan_sp);
PyObject *ThreadPlan_PyObj = SBTypeToSWIGWrapper(tp_value);
if (ThreadPlan_PyObj == NULL)
Py_RETURN_NONE;
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PythonDictionary dict = PythonModule::MainModule().ResolveName(session_dictionary_name).AsType<PythonDictionary>(); auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name, dict.get()); auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
if (!pfunc) if (!pfunc.IsAllocated())
return retval; return nullptr;
Py_INCREF(ThreadPlan_PyObj); PythonObject tp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(tp_value));
retval = pfunc(tp_value, dict.get()); if (!tp_arg.IsAllocated())
Py_RETURN_NONE;
PythonObject result = pfunc(tp_arg, dict);
// FIXME: At this point we should check that the class we found supports all the methods // FIXME: At this point we should check that the class we found supports all the methods
// that we need. // that we need.
Py_XINCREF(retval); if (result.IsAllocated())
return result.release();
if (retval) Py_RETURN_NONE;
return retval;
else
Py_RETURN_NONE;
} }
SWIGEXPORT bool SWIGEXPORT bool
@ -475,74 +456,64 @@ LLDBSWIGPythonCallThreadPlan
bool &got_error bool &got_error
) )
{ {
bool ret_val = false; using namespace lldb_private;
got_error = false; got_error = false;
PyErr_Cleaner py_err_cleaner(false); PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
auto pfunc = self.ResolveName<PythonCallable>(method_name);
PyCallable pfunc = PyCallable::FindWithMemberFunction((PyObject *) implementor, method_name); if (!pfunc.IsAllocated())
return false;
if (!pfunc) PythonObject result;
{ if (event != nullptr)
return ret_val;
}
PyObject* py_return = Py_None;
if (event != NULL)
{ {
lldb::SBEvent sb_event(event); lldb::SBEvent sb_event(event);
PythonObject event_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_event));
PyObject *py_obj_event = SBTypeToSWIGWrapper(sb_event); result = pfunc(event_arg);
py_return = pfunc(py_obj_event);
} }
else else
{ result = pfunc();
py_return = pfunc();
}
if (PyErr_Occurred()) if (PyErr_Occurred())
{ {
got_error = true; got_error = true;
printf ("Return value was neither false nor true for call to %s.\n", method_name); printf ("Return value was neither false nor true for call to %s.\n", method_name);
PyErr_Print(); PyErr_Print();
} return false;
else
{
if (py_return == Py_True)
ret_val = true;
else if (py_return == Py_False)
ret_val = false;
else
{
// Somebody returned the wrong thing...
got_error = true;
printf ("Wrong return value type for call to %s.\n", method_name);
}
} }
Py_XDECREF(py_return); if (result.get() == Py_True)
return true;
else if (result.get() == Py_False)
return false;
return ret_val; // Somebody returned the wrong thing...
got_error = true;
printf ("Wrong return value type for call to %s.\n", method_name);
return false;
} }
// wrapper that calls an optional instance member of an object taking no arguments // wrapper that calls an optional instance member of an object taking no arguments
static PyObject* static PyObject*
LLDBSwigPython_CallOptionalMember LLDBSwigPython_CallOptionalMember
( (
PyObject* self, PyObject* implementor,
char* callee_name, char* callee_name,
PyObject* ret_if_not_found = Py_None, PyObject* ret_if_not_found = Py_None,
bool* was_found = NULL bool* was_found = NULL
) )
{ {
using namespace lldb_private;
PyErr_Cleaner py_err_cleaner(false); PyErr_Cleaner py_err_cleaner(false);
PyCallable pfunc = PyCallable::FindWithMemberFunction(self,callee_name); PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
auto pfunc = self.ResolveName<PythonCallable>(callee_name);
if (!pfunc) if (!pfunc.IsAllocated())
{ {
if (was_found) if (was_found)
*was_found = false; *was_found = false;
@ -553,8 +524,8 @@ LLDBSwigPython_CallOptionalMember
if (was_found) if (was_found)
*was_found = true; *was_found = true;
PyObject* py_return = pfunc(); PythonObject result = pfunc();
return py_return; return result.release();
} }
SWIGEXPORT size_t SWIGEXPORT size_t
@ -564,47 +535,29 @@ LLDBSwigPython_CalculateNumChildren
uint32_t max uint32_t max
) )
{ {
size_t ret_val = 0; using namespace lldb_private;
bool int_match = false;
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor, "num_children"); PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("num_children");
if (!pfunc) if (!pfunc.IsAllocated())
return ret_val; return 0;
PyObject* py_return = NULL; PythonObject result;
auto argc = pfunc.GetNumArguments(); auto argc = pfunc.GetNumArguments();
if (argc.num_args == 1) if (argc.count == 1)
py_return = pfunc(); result = pfunc();
else if (argc.num_args == 2) else if (argc.count == 2)
py_return = pfunc(max); result = pfunc(PythonInteger(max));
if (!py_return) if (!result.IsAllocated())
return ret_val; return 0;
// PyInt_* are not available for Python 3 and above. PythonInteger int_result = result.AsType<PythonInteger>();
#if PY_MAJOR_VERSION < 3 if (!int_result.IsAllocated())
if (PyInt_Check (py_return)) return 0;
{
int_match = true;
ret_val = static_cast<size_t> (PyInt_AsLong (py_return));
}
#endif
// We want to check for PyLong only if the return value did not size_t ret_val = int_result.GetInteger();
// match PyInt. This is because we do not want to call PyLong_Check if
// PyInt_Check returns true but PyInt_AsLong generates an error.
if (!int_match && PyLong_Check (py_return))
{
#if PY_MAJOR_VERSION < 3
ret_val = static_cast<size_t> (PyLong_AsUnsignedLong (py_return));
#else
// PyLong_AsSize_t is available only for Python 3 and above.
ret_val = PyLong_AsSize_t (py_return);
#endif
}
Py_XDECREF(py_return);
if (PyErr_Occurred()) if (PyErr_Occurred())
{ {
@ -612,8 +565,8 @@ LLDBSwigPython_CalculateNumChildren
PyErr_Clear(); PyErr_Clear();
} }
if (argc.num_args == 1 && ret_val > max) if (argc.count == 1)
ret_val = max; ret_val = std::min(ret_val, max);
return ret_val; return ret_val;
} }
@ -625,34 +578,28 @@ LLDBSwigPython_GetChildAtIndex
uint32_t idx uint32_t idx
) )
{ {
using namespace lldb_private;
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_at_index"); PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("get_child_at_index");
if (!pfunc) if (!pfunc.IsAllocated())
return NULL; return nullptr;
PyObject *py_return = NULL; PythonObject result = pfunc(PythonInteger(idx));
py_return = pfunc(idx);
if (py_return == NULL || py_return == Py_None) if (!result.IsAllocated())
{ return nullptr;
Py_XDECREF(py_return);
return NULL;
}
lldb::SBValue* sbvalue_ptr = NULL; lldb::SBValue* sbvalue_ptr = nullptr;
if (SWIG_ConvertPtr(result.get(), (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
return nullptr;
if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1) if (sbvalue_ptr == nullptr)
{ return nullptr;
Py_XDECREF(py_return);
return NULL;
}
if (sbvalue_ptr == NULL) return result.release();
return NULL;
return py_return;
} }
SWIGEXPORT int SWIGEXPORT int
@ -662,25 +609,25 @@ LLDBSwigPython_GetIndexOfChildWithName
const char* child_name const char* child_name
) )
{ {
using namespace lldb_private;
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_index"); PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("get_child_index");
if (!pfunc) if (!pfunc.IsAllocated())
return UINT32_MAX; return UINT32_MAX;
PyObject *py_return = NULL; PythonObject result = pfunc(PythonString(child_name));
py_return = pfunc(child_name);
if (py_return == NULL || py_return == Py_None) if (!result.IsAllocated())
{
Py_XDECREF(py_return);
return UINT32_MAX; return UINT32_MAX;
}
long retval = PyInt_AsLong(py_return); PythonInteger int_result = result.AsType<PythonInteger>();
Py_XDECREF(py_return); if (!int_result.IsAllocated())
return UINT32_MAX;
int64_t retval = int_result.GetInteger();
if (retval >= 0) if (retval >= 0)
return (uint32_t)retval; return (uint32_t)retval;
@ -812,30 +759,26 @@ LLDBSwigPythonCallCommand
lldb::SBDebugger debugger_sb(debugger); lldb::SBDebugger debugger_sb(debugger);
lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
bool retval = false;
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PythonDictionary dict = PythonModule::MainModule().ResolveName(session_dictionary_name).AsType<PythonDictionary>(); auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,dict.get()); auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
if (!pfunc) if (!pfunc.IsAllocated())
return retval; return false;
// pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
// see comment above for SBCommandReturnObjectReleaser for further details // see comment above for SBCommandReturnObjectReleaser for further details
PyObject* pvalue = NULL; auto argc = pfunc.GetNumArguments();
PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb));
PyCallable::argc argc = pfunc.GetNumArguments(); if (argc.count == 5 || argc.has_varargs)
if (argc.num_args == 5 || argc.varargs == true) pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict);
pvalue = pfunc(debugger_sb, args, exe_ctx_sb, &cmd_retobj_sb, dict.get());
else else
pvalue = pfunc(debugger_sb, args, &cmd_retobj_sb, dict.get()); pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict);
Py_XDECREF (pvalue); return true;
retval = true;
return retval;
} }
SWIGEXPORT bool SWIGEXPORT bool
@ -848,7 +791,7 @@ LLDBSwigPythonCallCommandObject
lldb::ExecutionContextRefSP exe_ctx_ref_sp lldb::ExecutionContextRefSP exe_ctx_ref_sp
) )
{ {
using namespace lldb_private;
lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj); lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj);
SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb); SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb);
lldb::SBDebugger debugger_sb(debugger); lldb::SBDebugger debugger_sb(debugger);
@ -856,18 +799,19 @@ LLDBSwigPythonCallCommandObject
PyErr_Cleaner py_err_cleaner(true); PyErr_Cleaner py_err_cleaner(true);
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"__call__"); PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("__call__");
if (!pfunc) if (!pfunc.IsAllocated())
return false; return false;
// pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
// see comment above for SBCommandReturnObjectReleaser for further details // see comment above for SBCommandReturnObjectReleaser for further details
PyObject* pvalue = NULL; PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb));
pvalue = pfunc(debugger_sb, args, exe_ctx_sb, &cmd_retobj_sb); pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg);
Py_XDECREF (pvalue);
return true; return true;
} }

View File

@ -904,31 +904,35 @@ PythonCallable::Reset(PyRefType type, PyObject *py_obj)
} }
void PythonCallable::ArgInfo
PythonCallable::GetNumArguments(size_t &num_args, bool &has_varargs, bool &has_kwargs) const PythonCallable::GetNumArguments() const
{ {
num_args = 0; ArgInfo result = { 0, false, false };
has_varargs = false;
has_kwargs = false;
if (!IsValid()) if (!IsValid())
return; return result;
PyObject *py_func_obj = m_py_obj; PyObject *py_func_obj = m_py_obj;
if (PyMethod_Check(py_func_obj)) if (PyMethod_Check(py_func_obj))
py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
if (!py_func_obj) if (!py_func_obj)
return; return result;
PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
if (!code) if (!code)
return; return result;
num_args = code->co_argcount; result.count = code->co_argcount;
if (code->co_flags & CO_VARARGS) result.has_varargs = !!(code->co_flags & CO_VARARGS);
has_varargs = true; result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
if (code->co_flags & CO_VARKEYWORDS) return result;
has_kwargs = true; }
PythonObject
PythonCallable::operator ()()
{
return PythonObject(PyRefType::Owned,
PyObject_CallObject(m_py_obj, nullptr));
} }
PythonObject PythonObject

View File

@ -207,9 +207,23 @@ public:
static PythonObject static PythonObject
ResolveNameWithDictionary(llvm::StringRef name, PythonDictionary dict); ResolveNameWithDictionary(llvm::StringRef name, PythonDictionary dict);
template<typename T>
static T
ResolveNameWithDictionary(llvm::StringRef name, PythonDictionary dict)
{
return ResolveNameWithDictionary(name, dict).AsType<T>();
}
PythonObject PythonObject
ResolveName(llvm::StringRef name) const; ResolveName(llvm::StringRef name) const;
template<typename T>
T
ResolveName(llvm::StringRef name) const
{
return ResolveName(name).AsType<T>();
}
bool bool
HasAttribute(llvm::StringRef attribute) const; HasAttribute(llvm::StringRef attribute) const;
@ -410,6 +424,12 @@ class PythonModule : public PythonObject
class PythonCallable : public PythonObject class PythonCallable : public PythonObject
{ {
public: public:
struct ArgInfo {
size_t count;
bool has_varargs : 1;
bool has_kwargs : 1;
};
PythonCallable(); PythonCallable();
PythonCallable(PyRefType type, PyObject *o); PythonCallable(PyRefType type, PyObject *o);
PythonCallable(const PythonCallable &dict); PythonCallable(const PythonCallable &dict);
@ -425,14 +445,24 @@ public:
void void
Reset(PyRefType type, PyObject *py_obj) override; Reset(PyRefType type, PyObject *py_obj) override;
void ArgInfo
GetNumArguments(size_t &num_args, bool &has_varargs, bool &has_kwargs) const; GetNumArguments() const;
PythonObject
operator ()();
PythonObject PythonObject
operator ()(std::initializer_list<PyObject*> args); operator ()(std::initializer_list<PyObject*> args);
PythonObject PythonObject
operator ()(std::initializer_list<PythonObject> args); operator ()(std::initializer_list<PythonObject> args);
template<typename Arg, typename... Args>
PythonObject
operator ()(const Arg &arg, Args... args)
{
return operator()({ arg, args... });
}
}; };