Skip to content

Commit 269eeda

Browse files
committed
Send back implementation details
1 parent 1953f97 commit 269eeda

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

singlestoredb/apps/_python_udfs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ async def run_udf_app(
4141

4242
base_url = generate_base_url(app_config)
4343

44+
# something
45+
4446
udf_suffix = ''
4547
if app_config.running_interactively:
4648
udf_suffix = '_test'

singlestoredb/functions/ext/asgi.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,53 @@ def _locate_app_functions(self, cur: Any) -> Tuple[Set[str], Set[str]]:
12641264
links.add(link)
12651265
return funcs, links
12661266

1267+
def _get_function_implementation(self, func: Callable[..., Any], func_name: str) -> Dict[str, Any]:
1268+
"""
1269+
Extract function implementation details.
1270+
1271+
Parameters
1272+
----------
1273+
func : Callable
1274+
The function to analyze
1275+
func_name : str
1276+
Name of the function
1277+
1278+
Returns
1279+
-------
1280+
Dict[str, Any]
1281+
Implementation details including source code, file location, etc.
1282+
"""
1283+
if not func:
1284+
return {
1285+
'implementation': f"# Function {func_name} not found",
1286+
'source_file': None,
1287+
'line_number': None,
1288+
}
1289+
1290+
try:
1291+
# Get source code
1292+
source = inspect.getsource(func)
1293+
# Clean up indentation
1294+
source = textwrap.dedent(source)
1295+
1296+
# Get file and line info
1297+
source_file = inspect.getfile(func)
1298+
line_number = inspect.getsourcelines(func)[1]
1299+
1300+
return {
1301+
'implementation': source,
1302+
'source_file': source_file,
1303+
'line_number': line_number,
1304+
}
1305+
1306+
except (OSError, TypeError) as e:
1307+
# Handle cases where source is not available (REPL, compiled, etc.)
1308+
return {
1309+
'implementation': f"# Source code not available for {func_name}\n# Reason: {str(e)}",
1310+
'source_file': getattr(func, '__module__', 'unknown'),
1311+
'line_number': None,
1312+
}
1313+
12671314
def get_function_info(
12681315
self,
12691316
func_name: Optional[str] = None,
@@ -1321,12 +1368,17 @@ def get_function_info(
13211368
if a.get('default', no_default) is not no_default:
13221369
returns[-1]['default'] = a['default']
13231370

1371+
func_name_str = key.decode('utf-8') if isinstance(key, bytes) else key
1372+
original_func = self.external_functions.get(func_name_str)
1373+
implementation_info = self._get_function_implementation(original_func, func_name_str)
1374+
13241375
sql = sql_map.get(sig['name'], '')
13251376
functions[sig['name']] = dict(
13261377
args=args,
13271378
returns=returns,
13281379
function_type=info['function_type'],
13291380
sql_statement=sql,
1381+
**implementation_info,
13301382
)
13311383

13321384
return functions

0 commit comments

Comments
 (0)