@@ -231,139 +231,30 @@ def jit_function(self, func, cols_list, extra_args):
231231 return self .func_call
232232
233233
234- def remove_fn_name_from_signature (signature ):
235- """
236- Removes the function name from a signature string.
237- The signature is expected to be in the form of "return_type function_name(type param1, type param2, ...)".
238- """
239- if "(" not in signature or ")" not in signature :
240- raise ValueError (f"Invalid signature format: { signature } " )
241-
242- return signature [: signature .index (" " )] + signature [signature .index ("(" ) :]
243-
244-
245- def get_cpp_overload_from_templ_proxy (func , types = None ):
246- """
247- Gets the C++ overload from a cppyy TemplateProxy using the input
248- and template arguments types.
249- """
250- signature = ", " .join (types ) if types else ""
251- template_args = func .__template_args__ [1 :- 1 ] if func .__template_args__ else ""
252- return func .__overload__ (signature , template_args )
253-
254-
255234def get_column_types (rdf , cols ):
256235 return [rdf .GetColumnType (col ) for col in cols ]
257236
258237
259- def get_overload_based_on_args (overload_types , types ):
260- """
261- Gets the C++ overloads for a function based on the provided signatures and types.
262- """
263- if not isinstance (overload_types , dict ):
264- raise TypeError ("Overload types must be a dictionary." )
265-
266- if not isinstance (types , list ) or not all (isinstance (t , str ) for t in types ):
267- raise TypeError ("Types must be a list of strings." )
268-
269- if len (overload_types ) == 1 :
270- # If there is only one signature, return it directly
271- return next (iter (overload_types ))
272-
273- for full_sig , info in overload_types .items ():
274- input_types = info .get ("input_types" , ())
275-
276- if len (input_types ) != len (types ):
277- continue
278-
279- match = True
280- for expected , actual in zip (input_types , types ):
281- # Loose match: require actual to appear somewhere in expected (e.g. "int" in "const int&")
282- if actual not in expected :
283- match = False
284- break
285-
286- if match :
287- return full_sig
288-
289- raise ValueError (
290- f"No matching overload found for types: { types } in signatures: { overload_types .keys ()} . Please check the function overloads."
291- )
292-
293-
294- def _get_cpp_signature (func , rdf , cols ):
238+ def _resolve_overload_based_on_cols (func , rdf , cols ):
295239 """
296240 Gets the C++ signature of a cppyy callable.
297241 """
298242 import ROOT
299243
300- if isinstance (func , ROOT ._cppyy .types .Template ):
301- func = get_cpp_overload_from_templ_proxy (func , get_column_types (rdf , cols ))
302-
303- if not isinstance (func , ROOT ._cppyy .types .Function ):
244+ if not isinstance (func , (ROOT ._cppyy .types .Function , ROOT ._cppyy .types .Template )):
304245 raise TypeError (f"Expected a cppyy callable, got { type (func ).__name__ } " )
305246
306- overload_types = func .func_overloads_types
307- matched_overload = get_overload_based_on_args (overload_types , get_column_types (rdf , cols ))
308- return remove_fn_name_from_signature (matched_overload )
247+ if isinstance (func , ROOT ._cppyy .types .Template ) and func .__template_args__ :
248+ template_args = func .__template_args__ [1 :- 1 ]
249+ else :
250+ template_args = ""
309251
310-
311- def _to_std_function (func , rdf , cols ):
312- """
313- Converts a cppyy callable to std::function.
314- """
315- import ROOT
316-
317- if not isinstance (func , ROOT ._cppyy .types .Function ) and not isinstance (func , ROOT ._cppyy .types .Template ):
318- raise TypeError (f"Expected a cppyy callable, got { type (func ).__name__ } " )
319-
320- signature = _get_cpp_signature (func , rdf , cols )
321- return ROOT .std .function (signature )
322-
323-
324- def _handle_cpp_callables (func , original_template , * args , rdf = None , cols = None ):
325- """
326- Checks whether the callable `func` is a cppyy proxy of one of these:
327- 1. C++ functor
328- 2. std::function
329- 3. C++ free function
330-
331- Cases 1 and 2 above are supported by cppyy, so we can just invoke the original
332- cppyy TemplateProxy (Filter or Define) with the callable as argument.
333- For case 3, we need to convert the callable to a std::function
334- before invoking the original cppyy TemplateProxy.
335-
336- Prior to the invocation of the original cppyy TemplateProxy, though, we
337- need to explicitly instantiate the template using the type of the `func`
338- callable. Implicit instantiation won't work since the original
339- implementation of Filter and Define is replaced by a pythonization.
340-
341- Arguments:
342- func: callable to be checked
343- original_rdf_method: cppyy proxy for Filter or Define
344- args: arguments passed by the user to Filter or Define
345- Returns:
346- RDataFrame: RDataFrame node if `func` can be classified in one of the
347- three cases above, None otherwise
348- """
349- import ROOT
350-
351- is_cpp_functor = lambda : isinstance (getattr (func , "__call__" , None ), ROOT ._cppyy .types .Function ) # noqa E731
352-
353- is_std_function = lambda : isinstance (getattr (func , "target_type" , None ), ROOT ._cppyy .types .Function ) # noqa E731
354-
355- # handle free functions
356- if callable (func ) and not is_cpp_functor () and not is_std_function ():
357- try :
358- func = _to_std_function (func , rdf , cols )
359- except TypeError as e :
360- if "Expected a cppyy callable" in str (e ):
361- pass # this function is not convertible to std::function, move on to the next check
362- else :
363- raise
364-
365- if is_cpp_functor () or is_std_function ():
366- return original_template [type (func )](* args )
252+ col_types = get_column_types (rdf , cols )
253+ signature = ", " .join (col_types ) if cols else ""
254+ if template_args :
255+ return func .__overload__ (signature , template_args )
256+ else :
257+ return func .__overload__ (signature )
367258
368259
369260class _WarnOnce :
@@ -460,9 +351,13 @@ def x_more_than_y(x):
460351 f"Arguments should be ('list', 'str',) not ({ type (args [0 ]).__name__ , type (args [1 ]).__name__ } ."
461352 )
462353
463- rdf_node = _handle_cpp_callables (func , rdf ._OriginalFilter , func , * args , rdf = rdf , cols = col_list )
464- if rdf_node is not None :
465- return rdf_node
354+ import ROOT
355+
356+ if isinstance (func , (ROOT ._cppyy .types .Function , ROOT ._cppyy .types .Template )):
357+ return rdf ._OriginalFilter (_resolve_overload_based_on_cols (func , rdf , col_list ), * args )
358+
359+ if isinstance (func , ROOT ._cppyy .types .Instance ):
360+ return rdf ._OriginalFilter (func , * args )
466361
467362 _WarnOnce .warn ()
468363 jitter = FunctionJitter (rdf )
@@ -520,9 +415,13 @@ def x_scaled(x):
520415 raise TypeError (f"Define takes a column list as third arguments but { type (cols ).__name__ } was given." )
521416
522417 func = callable_or_str
523- rdf_node = _handle_cpp_callables (func , rdf ._OriginalDefine , col_name , func , cols , rdf = rdf , cols = cols )
524- if rdf_node is not None :
525- return rdf_node
418+
419+ import ROOT
420+
421+ if isinstance (func , (ROOT ._cppyy .types .Function , ROOT ._cppyy .types .Template )):
422+ return rdf ._OriginalDefine (col_name , _resolve_overload_based_on_cols (func , rdf , cols ), cols )
423+ if isinstance (func , ROOT ._cppyy .types .Instance ):
424+ return rdf ._OriginalDefine (col_name , func , cols )
526425
527426 _WarnOnce .warn ()
528427 jitter = FunctionJitter (rdf )
0 commit comments