in src/smolagents/local_python_executor.py [0:0]
def get_safe_module(raw_module, authorized_imports, visited=None):
"""Creates a safe copy of a module or returns the original if it's a function"""
# If it's a function or non-module object, return it directly
if not isinstance(raw_module, ModuleType):
return raw_module
# Handle circular references: Initialize visited set for the first call
if visited is None:
visited = set()
module_id = id(raw_module)
if module_id in visited:
return raw_module # Return original for circular refs
visited.add(module_id)
# Create new module for actual modules
safe_module = ModuleType(raw_module.__name__)
# Copy all attributes by reference, recursively checking modules
for attr_name in dir(raw_module):
try:
attr_value = getattr(raw_module, attr_name)
except (ImportError, AttributeError) as e:
# lazy / dynamic loading module -> INFO log and skip
logger.info(
f"Skipping import error while copying {raw_module.__name__}.{attr_name}: {type(e).__name__} - {e}"
)
continue
# Recursively process nested modules, passing visited set
if isinstance(attr_value, ModuleType):
attr_value = get_safe_module(attr_value, authorized_imports, visited=visited)
setattr(safe_module, attr_name, attr_value)
return safe_module