Skip to content

Commit 81d6cf2

Browse files
vepadulanosiliataider
authored andcommitted
[PyROOT] Get names and types of all overloads' signature
Expose two new attributes of a CPPOverload object on the Python side, namely `func_overloads_names` and `func_overloads_types`. The first returns a dictionary with all the input parameter names for all the overloads, the second returns a dictionary with the types of the return and input parameters for all the overloads. An example: ```python import ROOT from pprint import pprint ROOT.gInterpreter.Declare(""" int foo(int a, float b); int foo(int a); float foo(float b); double foo(int a, float b, double c); """) pprint(ROOT.foo.func_overloads_names) pprint(ROOT.foo.func_overloads_types) ``` Output: ``` {'double ::foo(int a, float b, double c)': ('a', 'b', 'c'), 'float ::foo(float b)': ('b',), 'int ::foo(int a)': ('a',), 'int ::foo(int a, float b)': ('a', 'b')} {'double ::foo(int a, float b, double c)': {'input_types': ('int', 'float', 'double'), 'return_type': 'double'}, 'float ::foo(float b)': {'input_types': ('float',), 'return_type': 'float'}, 'int ::foo(int a)': {'input_types': ('int',), 'return_type': 'int'}, 'int ::foo(int a, float b)': {'input_types': ('int', 'float'), 'return_type': 'int'}} ```
1 parent 6afd6e8 commit 81d6cf2

File tree

4 files changed

+125
-1
lines changed

4 files changed

+125
-1
lines changed

bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,70 @@ PyObject* CPyCppyy::CPPMethod::GetSignature(bool fa)
10551055
return CPyCppyy_PyText_FromString(GetSignatureString(fa).c_str());
10561056
}
10571057

1058+
/**
1059+
* @brief Returns a tuple with the names of the input parameters of this method.
1060+
*
1061+
* For example given a function with prototype:
1062+
*
1063+
* double foo(int a, float b, double c)
1064+
*
1065+
* this function returns:
1066+
*
1067+
* ('a', 'b', 'c')
1068+
*/
1069+
PyObject *CPyCppyy::CPPMethod::GetSignatureNames()
1070+
{
1071+
// Build a tuple of the argument names for this signature.
1072+
int argcount = GetMaxArgs();
1073+
PyObject *signature_names = PyTuple_New(argcount);
1074+
1075+
for (int iarg = 0; iarg < argcount; ++iarg) {
1076+
const std::string &argname_cpp = Cppyy::GetMethodArgName(fMethod, iarg);
1077+
PyObject *argname_py = CPyCppyy_PyText_FromString(argname_cpp.c_str());
1078+
PyTuple_SET_ITEM(signature_names, iarg, argname_py);
1079+
}
1080+
1081+
return signature_names;
1082+
}
1083+
1084+
/**
1085+
* @brief Returns a dictionary with the types of the signature of this method.
1086+
*
1087+
* This dictionary will store both the return type and the input parameter
1088+
* types of this method, respectively with keys "return_type" and
1089+
* "input_types", for example given a function with prototype:
1090+
*
1091+
* double foo(int a, float b, double c)
1092+
*
1093+
* this function returns:
1094+
*
1095+
* {'input_types': ('int', 'float', 'double'), 'return_type': 'double'}
1096+
*/
1097+
PyObject *CPyCppyy::CPPMethod::GetSignatureTypes()
1098+
{
1099+
1100+
PyObject *signature_types_dict = PyDict_New();
1101+
1102+
// Insert the return type first
1103+
std::string return_type = GetReturnTypeName();
1104+
PyObject *return_type_py = CPyCppyy_PyText_FromString(return_type.c_str());
1105+
PyDict_SetItem(signature_types_dict, CPyCppyy_PyText_FromString("return_type"), return_type_py);
1106+
1107+
// Build a tuple of the argument types for this signature.
1108+
int argcount = GetMaxArgs();
1109+
PyObject *parameter_types = PyTuple_New(argcount);
1110+
1111+
for (int iarg = 0; iarg < argcount; ++iarg) {
1112+
const std::string &argtype_cpp = Cppyy::GetMethodArgType(fMethod, iarg);
1113+
PyObject *argtype_py = CPyCppyy_PyText_FromString(argtype_cpp.c_str());
1114+
PyTuple_SET_ITEM(parameter_types, iarg, argtype_py);
1115+
}
1116+
1117+
PyDict_SetItem(signature_types_dict, CPyCppyy_PyText_FromString("input_types"), parameter_types);
1118+
1119+
return signature_types_dict;
1120+
}
1121+
10581122
//----------------------------------------------------------------------------
10591123
std::string CPyCppyy::CPPMethod::GetReturnTypeName()
10601124
{

bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class CPPMethod : public PyCallable {
5151

5252
public:
5353
PyObject* GetSignature(bool show_formalargs = true) override;
54+
PyObject* GetSignatureNames() override;
55+
PyObject* GetSignatureTypes() override;
5456
PyObject* GetPrototype(bool show_formalargs = true) override;
5557
PyObject* GetTypeName() override;
5658
PyObject* Reflex(Cppyy::Reflex::RequestId_t request,

bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ class TPythonCallback : public PyCallable {
6262
PyObject* GetSignature(bool /*show_formalargs*/ = true) override {
6363
return CPyCppyy_PyText_FromString("*args, **kwargs");
6464
}
65+
virtual PyObject* GetSignatureNames() {
66+
return PyTuple_New(0);
67+
}
68+
virtual PyObject* GetSignatureTypes() {
69+
return PyTuple_New(0);
70+
}
6571
PyObject* GetPrototype(bool /*show_formalargs*/ = true) override {
6672
return CPyCppyy_PyText_FromString("<callback>");
6773
}
@@ -285,6 +291,54 @@ static int mp_doc_set(CPPOverload* pymeth, PyObject *val, void *)
285291
return 0;
286292
}
287293

294+
/**
295+
* @brief Returns a dictionary with the input parameter names for all overloads.
296+
*
297+
* This dictionary may look like:
298+
*
299+
* {'double ::foo(int a, float b, double c)': ('a', 'b', 'c'),
300+
* 'float ::foo(float b)': ('b',),
301+
* 'int ::foo(int a)': ('a',),
302+
* 'int ::foo(int a, float b)': ('a', 'b')}
303+
*/
304+
static PyObject *mp_func_overloads_names(CPPOverload *pymeth)
305+
{
306+
307+
const CPPOverload::Methods_t &methods = pymeth->fMethodInfo->fMethods;
308+
309+
PyObject *overloads_names_dict = PyDict_New();
310+
311+
for (PyCallable *method : methods) {
312+
PyDict_SetItem(overloads_names_dict, method->GetPrototype(), method->GetSignatureNames());
313+
}
314+
315+
return overloads_names_dict;
316+
}
317+
318+
/**
319+
* @brief Returns a dictionary with the types of all overloads.
320+
*
321+
* This dictionary may look like:
322+
*
323+
* {'double ::foo(int a, float b, double c)': {'input_types': ('int', 'float', 'double'), 'return_type': 'double'},
324+
* 'float ::foo(float b)': {'input_types': ('float',), 'return_type': 'float'},
325+
* 'int ::foo(int a)': {'input_types': ('int',), 'return_type': 'int'},
326+
* 'int ::foo(int a, float b)': {'input_types': ('int', 'float'), 'return_type': 'int'}}
327+
*/
328+
static PyObject *mp_func_overloads_types(CPPOverload *pymeth)
329+
{
330+
331+
const CPPOverload::Methods_t &methods = pymeth->fMethodInfo->fMethods;
332+
333+
PyObject *overloads_types_dict = PyDict_New();
334+
335+
for (PyCallable *method : methods) {
336+
PyDict_SetItem(overloads_types_dict, method->GetPrototype(), method->GetSignatureTypes());
337+
}
338+
339+
return overloads_types_dict;
340+
}
341+
288342
//----------------------------------------------------------------------------
289343
static PyObject* mp_meth_func(CPPOverload* pymeth, void*)
290344
{
@@ -582,6 +636,8 @@ static PyGetSetDef mp_getset[] = {
582636
{(char*)"func_globals", (getter)mp_func_globals, nullptr, nullptr, nullptr},
583637
{(char*)"func_doc", (getter)mp_doc, (setter)mp_doc_set, nullptr, nullptr},
584638
{(char*)"func_name", (getter)mp_name, nullptr, nullptr, nullptr},
639+
{(char*)"func_overloads_types", (getter)mp_func_overloads_types, nullptr, nullptr, nullptr},
640+
{(char*)"func_overloads_names", (getter)mp_func_overloads_names, nullptr, nullptr, nullptr},
585641

586642

587643
// flags to control behavior
@@ -1250,4 +1306,4 @@ CPyCppyy::CPPOverload::MethodInfo_t::~MethodInfo_t()
12501306
Py_XDECREF(fDoc);
12511307
}
12521308

1253-
// TODO: something like PyMethod_Fini to clear up the free_list
1309+
// TODO: something like PyMethod_Fini to clear up the free_list

bindings/pyroot/cppyy/CPyCppyy/src/PyCallable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class PyCallable {
1818

1919
public:
2020
virtual PyObject* GetSignature(bool show_formalargs = true) = 0;
21+
virtual PyObject* GetSignatureNames() = 0;
22+
virtual PyObject* GetSignatureTypes() = 0;
2123
virtual PyObject* GetPrototype(bool show_formalargs = true) = 0;
2224
virtual PyObject* GetTypeName() { return GetPrototype(false); }
2325
virtual PyObject* GetDocString() { return GetPrototype(); }

0 commit comments

Comments
 (0)