MCPcopy Create free account
hub / github.com/promptfoo/promptfoo / get_callable

Function get_callable

src/python/persistent_wrapper.py:106–165  ·  view source on GitHub ↗

Get the callable method from module, supporting 'Class.method' syntax.

(module, method_name)

Source from the content-addressed store, hash-verified

104
105
106def get_callable(module, method_name):
107 """Get the callable method from module, supporting 'Class.method' syntax."""
108 try:
109 if "." in method_name:
110 class_name, classmethod_name = method_name.split(".", 1)
111 cls = getattr(module, class_name)
112 return getattr(cls, classmethod_name)
113 else:
114 return getattr(module, method_name)
115 except AttributeError as e:
116 # Provide helpful error message when function not found
117 available_funcs = [
118 name
119 for name in dir(module)
120 if callable(getattr(module, name, None)) and not name.startswith("_")
121 ]
122
123 error_lines = [
124 f"Function '{method_name}' not found in module '{module.__name__}'",
125 "",
126 f"Available functions in your module: {', '.join(available_funcs) if available_funcs else '(none)'}",
127 "",
128 "Expected function names for promptfoo:",
129 " • call_api(prompt, options, context) - for chat/completions",
130 " • call_embedding_api(prompt, options) - for embeddings",
131 " • call_classification_api(prompt, options) - for classification",
132 "",
133 ]
134
135 # Fuzzy match suggestion
136 if available_funcs:
137 # Check for common mistakes
138 method_lower = method_name.lower()
139 for func in available_funcs:
140 func_lower = func.lower()
141 # Check if user used 'get_' instead of 'call_'
142 if method_lower.replace("call_", "") == func_lower.replace("get_", ""):
143 error_lines.append(
144 f"💡 Did you mean to rename '{func}' to '{method_name}'?"
145 )
146 break
147 # Check if function name is similar (missing 'call_' prefix)
148 elif method_lower.replace("call_", "") == func_lower:
149 error_lines.append(
150 f"💡 Did you mean to rename '{func}' to '{method_name}'?"
151 )
152 break
153 # Check if it's just a typo (Levenshtein-like)
154 elif (
155 len(set(method_lower) & set(func_lower)) > len(method_lower) * 0.6
156 and abs(len(method_lower) - len(func_lower)) <= 3
157 ):
158 error_lines.append(f"💡 Did you mean '{func}'?")
159 break
160
161 error_lines.append(
162 "\nSee https://www.promptfoo.dev/docs/providers/python/ for details."
163 )

Callers 1

handle_callFunction · 0.85

Calls 2

splitMethod · 0.80
appendMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…