Skip to content

Commit ff7c1b3

Browse files
committed
fix: make shipped module source inspectable for nested remote calls
1 parent e1dfc83 commit ff7c1b3

2 files changed

Lines changed: 52 additions & 3 deletions

File tree

‎runpod/runtimes/task/runner.py‎

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,13 @@ def execute_request(request):
150150
# exec mirrors deployed-mode module import: the code is the
151151
# user's full module, so __name__ is set like an import would
152152
# (main guards stay inert) and decorated handles resolve to
153-
# their wrapped functions
154-
namespace = {"__name__": "__runpod_live__"}
155-
exec(function_code, namespace) # noqa: S102 - that is the job
153+
# their wrapped functions. the source is written to a real
154+
# file first so inspect.getsource works inside the function
155+
# (nested .remote() calls re-extract sibling source)
156+
source_path = _materialize_source(function_code)
157+
namespace = {"__name__": "__runpod_live__", "__file__": source_path}
158+
code_obj = compile(function_code, source_path, "exec")
159+
exec(code_obj, namespace) # noqa: S102 - that is the job
156160
if function_name not in namespace:
157161
return {
158162
"success": False,
@@ -188,6 +192,21 @@ def execute_request(request):
188192
}
189193

190194

195+
def _materialize_source(function_code):
196+
"""persist request source to a stable path for inspect/linecache."""
197+
import hashlib
198+
import tempfile
199+
200+
digest = hashlib.sha256(function_code.encode()).hexdigest()[:16]
201+
path = os.path.join(
202+
tempfile.gettempdir(), f"runpod_live_{digest}.py"
203+
)
204+
if not os.path.exists(path):
205+
with open(path, "w") as f:
206+
f.write(function_code)
207+
return path
208+
209+
191210
class _Tee(io.TextIOBase):
192211
"""write-through to multiple streams, flushing eagerly so log
193212
followers see lines as they happen."""

‎tests/test_apps/test_dispatch.py‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,33 @@ def test_execute_request_unwraps_handles(self):
304304
)
305305
assert response["success"], response.get("error")
306306
assert response["json_result"] == "AAAAAA"
307+
308+
def test_nested_source_extraction_from_shipped_module(self):
309+
# inside a live worker, a function calling sibling.remote()
310+
# re-extracts that sibling's source via inspect; the shipped
311+
# module must be inspectable after exec
312+
from runpod.runtimes.task.runner import execute_request
313+
314+
code = (
315+
"import runpod\n"
316+
"app = runpod.App('t2')\n"
317+
"@app.queue()\n"
318+
"def sibling(x):\n"
319+
" return x\n"
320+
"@app.queue()\n"
321+
"def caller():\n"
322+
" import inspect\n"
323+
" from runpod.apps.serialization import get_function_source\n"
324+
" return get_function_source(sibling._fn)\n"
325+
)
326+
response = execute_request(
327+
{
328+
"function_name": "caller",
329+
"function_code": code,
330+
"args": [],
331+
"kwargs": {},
332+
"serialization_format": "json",
333+
}
334+
)
335+
assert response["success"], response.get("error")
336+
assert "def sibling" in response["json_result"]

0 commit comments

Comments
 (0)