Skip to content

Commit dd6615e

Browse files
vepadulanosiliataider
authored andcommitted
[PyROOT] Add cppyy patch
1 parent 81d6cf2 commit dd6615e

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
From fedd8c12b44af98afaa3dc2791126521af12f1f1 Mon Sep 17 00:00:00 2001
2+
From: Vincenzo Eduardo Padulano <[email protected]>
3+
Date: Mon, 18 Oct 2021 19:03:19 +0200
4+
Subject: [PATCH] [PyROOT] Get names and types of all overloads' signature
5+
6+
Expose two new attributes of a CPPOverload object on the Python side,
7+
namely `func_overloads_names` and `func_overloads_types`. The first
8+
returns a dictionary with all the input parameter names for all the
9+
overloads, the second returns a dictionary with the types of the return
10+
and input parameters for all the overloads. An example:
11+
12+
```python
13+
import ROOT
14+
from pprint import pprint
15+
16+
ROOT.gInterpreter.Declare("""
17+
int foo(int a, float b);
18+
int foo(int a);
19+
float foo(float b);
20+
double foo(int a, float b, double c);
21+
""")
22+
23+
pprint(ROOT.foo.func_overloads_names)
24+
pprint(ROOT.foo.func_overloads_types)
25+
```
26+
Output:
27+
```
28+
{'double ::foo(int a, float b, double c)': ('a', 'b', 'c'),
29+
'float ::foo(float b)': ('b',),
30+
'int ::foo(int a)': ('a',),
31+
'int ::foo(int a, float b)': ('a', 'b')}
32+
{'double ::foo(int a, float b, double c)': {'input_types': ('int',
33+
'float',
34+
'double'),
35+
'return_type': 'double'},
36+
'float ::foo(float b)': {'input_types': ('float',), 'return_type': 'float'},
37+
'int ::foo(int a)': {'input_types': ('int',), 'return_type': 'int'},
38+
'int ::foo(int a, float b)': {'input_types': ('int', 'float'),
39+
'return_type': 'int'}}
40+
```
41+
---
42+
.../pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx | 64 +++++++++++++++++++
43+
.../pyroot/cppyy/CPyCppyy/src/CPPMethod.h | 2 +
44+
.../pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx | 59 +++++++++++++++++
45+
.../pyroot/cppyy/CPyCppyy/src/PyCallable.h | 2 +
46+
4 files changed, 127 insertions(+)
47+
48+
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx
49+
index 2189348594..16b2371cd5 100644
50+
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx
51+
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx
52+
@@ -801,6 +801,70 @@ PyObject* CPyCppyy::CPPMethod::GetSignature(bool fa)
53+
return CPyCppyy_PyText_FromString(GetSignatureString(fa).c_str());
54+
}
55+
56+
+/**
57+
+ * @brief Returns a tuple with the names of the input parameters of this method.
58+
+ *
59+
+ * For example given a function with prototype:
60+
+ *
61+
+ * double foo(int a, float b, double c)
62+
+ *
63+
+ * this function returns:
64+
+ *
65+
+ * ('a', 'b', 'c')
66+
+ */
67+
+PyObject *CPyCppyy::CPPMethod::GetSignatureNames()
68+
+{
69+
+ // Build a tuple of the argument names for this signature.
70+
+ int argcount = GetMaxArgs();
71+
+ PyObject *signature_names = PyTuple_New(argcount);
72+
+
73+
+ for (int iarg = 0; iarg < argcount; ++iarg) {
74+
+ const std::string &argname_cpp = Cppyy::GetMethodArgName(fMethod, iarg);
75+
+ PyObject *argname_py = CPyCppyy_PyText_FromString(argname_cpp.c_str());
76+
+ PyTuple_SET_ITEM(signature_names, iarg, argname_py);
77+
+ }
78+
+
79+
+ return signature_names;
80+
+}
81+
+
82+
+/**
83+
+ * @brief Returns a dictionary with the types of the signature of this method.
84+
+ *
85+
+ * This dictionary will store both the return type and the input parameter
86+
+ * types of this method, respectively with keys "return_type" and
87+
+ * "input_types", for example given a function with prototype:
88+
+ *
89+
+ * double foo(int a, float b, double c)
90+
+ *
91+
+ * this function returns:
92+
+ *
93+
+ * {'input_types': ('int', 'float', 'double'), 'return_type': 'double'}
94+
+ */
95+
+PyObject *CPyCppyy::CPPMethod::GetSignatureTypes()
96+
+{
97+
+
98+
+ PyObject *signature_types_dict = PyDict_New();
99+
+
100+
+ // Insert the return type first
101+
+ std::string return_type = GetReturnTypeName();
102+
+ PyObject *return_type_py = CPyCppyy_PyText_FromString(return_type.c_str());
103+
+ PyDict_SetItem(signature_types_dict, CPyCppyy_PyText_FromString("return_type"), return_type_py);
104+
+
105+
+ // Build a tuple of the argument types for this signature.
106+
+ int argcount = GetMaxArgs();
107+
+ PyObject *parameter_types = PyTuple_New(argcount);
108+
+
109+
+ for (int iarg = 0; iarg < argcount; ++iarg) {
110+
+ const std::string &argtype_cpp = Cppyy::GetMethodArgType(fMethod, iarg);
111+
+ PyObject *argtype_py = CPyCppyy_PyText_FromString(argtype_cpp.c_str());
112+
+ PyTuple_SET_ITEM(parameter_types, iarg, argtype_py);
113+
+ }
114+
+
115+
+ PyDict_SetItem(signature_types_dict, CPyCppyy_PyText_FromString("input_types"), parameter_types);
116+
+
117+
+ return signature_types_dict;
118+
+}
119+
+
120+
//----------------------------------------------------------------------------
121+
std::string CPyCppyy::CPPMethod::GetReturnTypeName()
122+
{
123+
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.h b/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.h
124+
index ddd8aa113d..81e4dfbabb 100644
125+
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.h
126+
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.h
127+
@@ -24,6 +24,8 @@ public:
128+
129+
public:
130+
virtual PyObject* GetSignature(bool show_formalargs = true);
131+
+ virtual PyObject* GetSignatureNames();
132+
+ virtual PyObject* GetSignatureTypes();
133+
virtual PyObject* GetPrototype(bool show_formalargs = true);
134+
virtual int GetPriority();
135+
virtual bool IsGreedy();
136+
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
137+
index 28bbd635c2..ae4358c584 100644
138+
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
139+
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
140+
@@ -58,6 +58,15 @@ public:
141+
virtual PyObject* GetSignature(bool /*show_formalargs*/ = true) {
142+
return CPyCppyy_PyText_FromString("*args, **kwargs");
143+
}
144+
+
145+
+ virtual PyObject* GetSignatureNames() {
146+
+ return PyTuple_New(0);
147+
+ }
148+
+
149+
+ virtual PyObject* GetSignatureTypes() {
150+
+ return PyTuple_New(0);
151+
+ }
152+
+
153+
virtual PyObject* GetPrototype(bool /*show_formalargs*/ = true) {
154+
return CPyCppyy_PyText_FromString("<callback>");
155+
}
156+
@@ -241,6 +250,54 @@ static PyObject* mp_doc(CPPOverload* pymeth, void*)
157+
return doc;
158+
}
159+
160+
+/**
161+
+ * @brief Returns a dictionary with the input parameter names for all overloads.
162+
+ *
163+
+ * This dictionary may look like:
164+
+ *
165+
+ * {'double ::foo(int a, float b, double c)': ('a', 'b', 'c'),
166+
+ * 'float ::foo(float b)': ('b',),
167+
+ * 'int ::foo(int a)': ('a',),
168+
+ * 'int ::foo(int a, float b)': ('a', 'b')}
169+
+ */
170+
+static PyObject *mp_func_overloads_names(CPPOverload *pymeth)
171+
+{
172+
+
173+
+ const CPPOverload::Methods_t &methods = pymeth->fMethodInfo->fMethods;
174+
+
175+
+ PyObject *overloads_names_dict = PyDict_New();
176+
+
177+
+ for (PyCallable *method : methods) {
178+
+ PyDict_SetItem(overloads_names_dict, method->GetPrototype(), method->GetSignatureNames());
179+
+ }
180+
+
181+
+ return overloads_names_dict;
182+
+}
183+
+
184+
+/**
185+
+ * @brief Returns a dictionary with the types of all overloads.
186+
+ *
187+
+ * This dictionary may look like:
188+
+ *
189+
+ * {'double ::foo(int a, float b, double c)': {'input_types': ('int', 'float', 'double'), 'return_type': 'double'},
190+
+ * 'float ::foo(float b)': {'input_types': ('float',), 'return_type': 'float'},
191+
+ * 'int ::foo(int a)': {'input_types': ('int',), 'return_type': 'int'},
192+
+ * 'int ::foo(int a, float b)': {'input_types': ('int', 'float'), 'return_type': 'int'}}
193+
+ */
194+
+static PyObject *mp_func_overloads_types(CPPOverload *pymeth)
195+
+{
196+
+
197+
+ const CPPOverload::Methods_t &methods = pymeth->fMethodInfo->fMethods;
198+
+
199+
+ PyObject *overloads_types_dict = PyDict_New();
200+
+
201+
+ for (PyCallable *method : methods) {
202+
+ PyDict_SetItem(overloads_types_dict, method->GetPrototype(), method->GetSignatureTypes());
203+
+ }
204+
+
205+
+ return overloads_types_dict;
206+
+}
207+
+
208+
//----------------------------------------------------------------------------
209+
static PyObject* mp_meth_func(CPPOverload* pymeth, void*)
210+
{
211+
@@ -514,6 +571,8 @@ static PyGetSetDef mp_getset[] = {
212+
{(char*)"func_globals", (getter)mp_func_globals, nullptr, nullptr, nullptr},
213+
{(char*)"func_doc", (getter)mp_doc, nullptr, nullptr, nullptr},
214+
{(char*)"func_name", (getter)mp_name, nullptr, nullptr, nullptr},
215+
+ {(char*)"func_overloads_types", (getter)mp_func_overloads_types, nullptr, nullptr, nullptr},
216+
+ {(char*)"func_overloads_names", (getter)mp_func_overloads_names, nullptr, nullptr, nullptr},
217+
218+
{(char*)"__creates__", (getter)mp_getcreates, (setter)mp_setcreates,
219+
(char*)"For ownership rules of result: if true, objects are python-owned", nullptr},
220+
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/PyCallable.h b/bindings/pyroot/cppyy/CPyCppyy/src/PyCallable.h
221+
index 4185e563ca..9131b3c32c 100644
222+
--- a/bindings/pyroot/cppyy/CPyCppyy/src/PyCallable.h
223+
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/PyCallable.h
224+
@@ -15,6 +15,8 @@ public:
225+
226+
public:
227+
virtual PyObject* GetSignature(bool show_formalargs = true) = 0;
228+
+ virtual PyObject* GetSignatureNames() = 0;
229+
+ virtual PyObject* GetSignatureTypes() = 0;
230+
virtual PyObject* GetPrototype(bool show_formalargs = true) = 0;
231+
virtual PyObject* GetDocString() { return GetPrototype(); }
232+
233+
--
234+
2.37.2
235+

0 commit comments

Comments
 (0)