Spaces:
Running
Running
File size: 2,255 Bytes
c61ccee |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import sys
from typing import Any, Callable, Iterable, List, Tuple
__all__ = ["trace_dependencies"]
def trace_dependencies(
callable: Callable[[Any], Any], inputs: Iterable[Tuple[Any, ...]]
) -> List[str]:
"""Trace the execution of a callable in order to determine which modules it uses.
Args:
callable: The callable to execute and trace.
inputs: The input to use during tracing. The modules used by 'callable' when invoked by each set of inputs
are union-ed to determine all modules used by the callable for the purpooses of packaging.
Returns: A list of the names of all modules used during callable execution.
"""
modules_used = set()
def record_used_modules(frame, event, arg):
# If the event being profiled is not a Python function
# call, there is nothing to do.
if event != "call":
return
# This is the name of the function that was called.
name = frame.f_code.co_name
module = None
# Try to determine the name of the module that the function
# is in:
# 1) Check the global namespace of the frame.
# 2) Check the local namespace of the frame.
# 3) To handle class instance method calls, check
# the attribute named 'name' of the object
# in the local namespace corresponding to "self".
if name in frame.f_globals:
module = frame.f_globals[name].__module__
elif name in frame.f_locals:
module = frame.f_locals[name].__module__
elif "self" in frame.f_locals:
method = getattr(frame.f_locals["self"], name, None)
module = method.__module__ if method else None
# If a module was found, add it to the set of used modules.
if module:
modules_used.add(module)
try:
# Attach record_used_modules as the profiler function.
sys.setprofile(record_used_modules)
# Execute the callable with all inputs.
for inp in inputs:
callable(*inp)
finally:
# Detach the profiler function.
sys.setprofile(None)
return list(modules_used)
|