github-actions[bot]
Deploy to HF Space from 2e7e2d503b896377e0bf161a73314974dd7ee7d1
b8a331e
Raw
History Blame Contribute Delete
5.95 kB
"""
Tool implementations for the Data Cleaning environment.
Provides file operations and Python code execution for data cleaning tasks.
"""
import os
import subprocess
import tempfile
from typing import Any, Dict, Tuple
class DataCleanTools:
"""
Tool implementations for data cleaning tasks.
Args:
workspace_dir: Working directory for agent operations
messy_file_path: Path to the input messy file
"""
def __init__(self, workspace_dir: str, messy_file_path: str):
self.workspace_dir = workspace_dir
self.messy_file_path = messy_file_path
self.submitted_file_path = None
def execute_tool(
self, tool_name: str, tool_args: Dict[str, Any]
) -> Tuple[str, bool]:
"""
Execute a tool and return its result.
Args:
tool_name: Name of the tool to execute
tool_args: Arguments for the tool
Returns:
Tuple of (result_string, is_final_action)
"""
if tool_name == "read_file":
return self.read_file(**tool_args), False
elif tool_name == "run_python":
return self.run_python(**tool_args), False
elif tool_name == "write_file":
return self.write_file(**tool_args), False
elif tool_name == "submit_cleaned_file":
return self.submit_cleaned_file(**tool_args), True
else:
return f"Error: Unknown tool '{tool_name}'", False
def read_file(self, path: str) -> str:
"""
Read a file from the workspace.
Args:
path: Relative path to the file in the workspace
Returns:
File contents or error message
"""
# Resolve path relative to workspace
if not os.path.isabs(path):
full_path = os.path.join(self.workspace_dir, path)
else:
# Security check: ensure path is within workspace
full_path = os.path.abspath(path)
if not full_path.startswith(os.path.abspath(self.workspace_dir)):
return f"Error: Path '{path}' is outside workspace directory"
if not os.path.exists(full_path):
return f"Error: File '{path}' not found"
try:
with open(full_path, "r", encoding="utf-8") as f:
content = f.read()
return content
except Exception as e:
return f"Error reading file: {str(e)}"
def run_python(self, code: str) -> str:
"""
Execute Python code in a sandboxed environment.
Args:
code: Python code to execute
Returns:
stdout/stderr from execution or error message
"""
# Create a temporary file for the code
with tempfile.NamedTemporaryFile(
mode="w", suffix=".py", delete=False, dir=self.workspace_dir
) as f:
f.write(code)
temp_file = f.name
try:
# Execute with timeout and capture output
result = subprocess.run(
["python", temp_file],
cwd=self.workspace_dir,
capture_output=True,
text=True,
timeout=10,
)
output = ""
if result.stdout:
output += f"stdout:\n{result.stdout}\n"
if result.stderr:
output += f"stderr:\n{result.stderr}\n"
if result.returncode != 0:
output += f"\nExit code: {result.returncode}"
return output if output else "Code executed successfully (no output)"
except subprocess.TimeoutExpired:
return "Error: Code execution timed out (10s limit)"
except Exception as e:
return f"Error executing code: {str(e)}"
finally:
# Clean up temp file
try:
os.unlink(temp_file)
except:
pass
def write_file(self, path: str, content: str) -> str:
"""
Write content to a file in the workspace.
Args:
path: Relative path to the file in the workspace
content: Content to write
Returns:
Success message or error
"""
# Resolve path relative to workspace
if not os.path.isabs(path):
full_path = os.path.join(self.workspace_dir, path)
else:
# Security check: ensure path is within workspace
full_path = os.path.abspath(path)
if not full_path.startswith(os.path.abspath(self.workspace_dir)):
return f"Error: Path '{path}' is outside workspace directory"
try:
# Ensure directory exists (only if path has a directory component)
dir_path = os.path.dirname(full_path)
if dir_path:
os.makedirs(dir_path, exist_ok=True)
with open(full_path, "w", encoding="utf-8") as f:
f.write(content)
return f"File written successfully: {path}"
except Exception as e:
return f"Error writing file: {str(e)}"
def submit_cleaned_file(self, path: str) -> str:
"""
Submit a cleaned file as the final answer.
Args:
path: Relative path to the cleaned file
Returns:
Confirmation message
"""
# Resolve path relative to workspace
if not os.path.isabs(path):
full_path = os.path.join(self.workspace_dir, path)
else:
full_path = os.path.abspath(path)
if not full_path.startswith(os.path.abspath(self.workspace_dir)):
return f"Error: Path '{path}' is outside workspace directory"
if not os.path.exists(full_path):
return f"Error: File '{path}' not found. Please create it first."
self.submitted_file_path = full_path
return f"Cleaned file submitted: {path}"