Spaces:
Sleeping
Sleeping
fix python code tool error
Browse files
agent.py
CHANGED
|
@@ -29,7 +29,8 @@ from tools import (
|
|
| 29 |
excel_to_text,
|
| 30 |
save_attachment_to_tempfile,
|
| 31 |
process_youtube_video,
|
| 32 |
-
transcribe_audio
|
|
|
|
| 33 |
)
|
| 34 |
|
| 35 |
load_dotenv()
|
|
@@ -69,6 +70,7 @@ excel_to_text: Convert Excel to Markdown table with attachment, args: {"excel_pa
|
|
| 69 |
process_youtube_video: Extract and analyze YouTube video content by providing the video URL. Returns video metadata and transcript, args: {"url": {"type": "string"}, "summarize": {"type": "boolean", "optional": true}}
|
| 70 |
transcribe_audio: Transcribe audio files using OpenAI Whisper, args: {"audio_path": {"type": "string"}, "file_content": {"type": "string", "optional": true}, "language": {"type": "string", "optional": true}}
|
| 71 |
|
|
|
|
| 72 |
IMPORTANT: Make sure your JSON is properly formatted with double quotes around keys and string values.
|
| 73 |
|
| 74 |
Example use for tools:
|
|
@@ -474,15 +476,64 @@ def python_code_node(state: AgentState) -> Dict[str, Any]:
|
|
| 474 |
print(f"Python code action_input: {action_input}")
|
| 475 |
print(f"Action input type: {type(action_input)}")
|
| 476 |
|
| 477 |
-
#
|
| 478 |
-
code =
|
| 479 |
-
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
|
| 487 |
# Additional validation: check for unmatched braces
|
| 488 |
open_braces = code.count('{')
|
|
@@ -490,7 +541,7 @@ def python_code_node(state: AgentState) -> Dict[str, Any]:
|
|
| 490 |
if open_braces != close_braces:
|
| 491 |
result = f"Error: Code contains unmatched braces. Found {open_braces} '{{' and {close_braces} '}}'. Please check your code syntax."
|
| 492 |
else:
|
| 493 |
-
# Call the code execution function
|
| 494 |
result = run_python_code(code)
|
| 495 |
|
| 496 |
print(f"Code execution result: {result[:100]}...") # Print first 100 chars
|
|
@@ -1109,7 +1160,17 @@ class TurboNerd:
|
|
| 1109 |
# Example usage:
|
| 1110 |
if __name__ == "__main__":
|
| 1111 |
agent = TurboNerd(max_iterations=25)
|
| 1112 |
-
response = agent("""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1113 |
print("\nFinal Response:")
|
| 1114 |
print(response)
|
| 1115 |
|
|
|
|
| 29 |
excel_to_text,
|
| 30 |
save_attachment_to_tempfile,
|
| 31 |
process_youtube_video,
|
| 32 |
+
transcribe_audio,
|
| 33 |
+
extract_python_code_from_complex_input
|
| 34 |
)
|
| 35 |
|
| 36 |
load_dotenv()
|
|
|
|
| 70 |
process_youtube_video: Extract and analyze YouTube video content by providing the video URL. Returns video metadata and transcript, args: {"url": {"type": "string"}, "summarize": {"type": "boolean", "optional": true}}
|
| 71 |
transcribe_audio: Transcribe audio files using OpenAI Whisper, args: {"audio_path": {"type": "string"}, "file_content": {"type": "string", "optional": true}, "language": {"type": "string", "optional": true}}
|
| 72 |
|
| 73 |
+
If you get stuck, try using another tool. For example if you are unable to find relevant information from the tavily_search tool, try using the wikipedia_search tool and vice versa.
|
| 74 |
IMPORTANT: Make sure your JSON is properly formatted with double quotes around keys and string values.
|
| 75 |
|
| 76 |
Example use for tools:
|
|
|
|
| 476 |
print(f"Python code action_input: {action_input}")
|
| 477 |
print(f"Action input type: {type(action_input)}")
|
| 478 |
|
| 479 |
+
# First try our specialized extraction function that handles nested structures
|
| 480 |
+
code = extract_python_code_from_complex_input(action_input)
|
| 481 |
+
|
| 482 |
+
# If extraction failed or returned the same complex structure, fallback to regex
|
| 483 |
+
if code == action_input or (isinstance(code, str) and code.strip().startswith('{') and '"code"' in code):
|
| 484 |
+
# Convert the action_input to string for regex processing if it's a dictionary
|
| 485 |
+
if isinstance(action_input, dict):
|
| 486 |
+
action_input_str = json.dumps(action_input)
|
| 487 |
+
else:
|
| 488 |
+
action_input_str = str(action_input)
|
| 489 |
+
|
| 490 |
+
# First, attempt direct regex extraction which is most robust for nested structures
|
| 491 |
+
import re
|
| 492 |
+
|
| 493 |
+
# Try to extract code using regex patterns for different nesting levels
|
| 494 |
+
# Pattern for deeply nested code
|
| 495 |
+
deep_pattern = re.search(r'"code"\s*:\s*"(.*?)(?<!\\)"\s*}\s*}\s*}', action_input_str, re.DOTALL)
|
| 496 |
+
if deep_pattern:
|
| 497 |
+
extracted_code = deep_pattern.group(1)
|
| 498 |
+
# Unescape the extracted code
|
| 499 |
+
extracted_code = extracted_code.replace('\\n', '\n').replace('\\"', '"').replace("\\'", "'")
|
| 500 |
+
code = extracted_code
|
| 501 |
+
print(f"Extracted deeply nested code using regex: {repr(code[:100])}")
|
| 502 |
+
|
| 503 |
+
# Pattern for single level nesting
|
| 504 |
+
elif '"code"' in action_input_str:
|
| 505 |
+
pattern = re.search(r'"code"\s*:\s*"(.*?)(?<!\\)"', action_input_str, re.DOTALL)
|
| 506 |
+
if pattern:
|
| 507 |
+
extracted_code = pattern.group(1)
|
| 508 |
+
# Unescape the extracted code
|
| 509 |
+
extracted_code = extracted_code.replace('\\n', '\n').replace('\\"', '"').replace("\\'", "'")
|
| 510 |
+
code = extracted_code
|
| 511 |
+
print(f"Extracted code using regex: {repr(code[:100])}")
|
| 512 |
+
|
| 513 |
+
# If regex extraction failed, try dictionary approaches
|
| 514 |
+
if code == action_input and isinstance(action_input, dict):
|
| 515 |
+
# Direct code access
|
| 516 |
+
if "code" in action_input:
|
| 517 |
+
code = action_input["code"]
|
| 518 |
+
print(f"Extracted code directly from dict: {repr(code[:100])}")
|
| 519 |
+
|
| 520 |
+
# Nested JSON structure handling
|
| 521 |
+
elif isinstance(action_input.get("code", ""), str) and action_input.get("code", "").strip().startswith('{'):
|
| 522 |
+
try:
|
| 523 |
+
nested_json = json.loads(action_input["code"])
|
| 524 |
+
if "action_input" in nested_json and isinstance(nested_json["action_input"], dict) and "code" in nested_json["action_input"]:
|
| 525 |
+
code = nested_json["action_input"]["code"]
|
| 526 |
+
print(f"Extracted code from nested JSON: {repr(code[:100])}")
|
| 527 |
+
except:
|
| 528 |
+
# If parsing fails, use the code field as-is
|
| 529 |
+
pass
|
| 530 |
+
|
| 531 |
+
# If still no code, use the action_input directly (string case)
|
| 532 |
+
if code == action_input and isinstance(action_input, str):
|
| 533 |
+
code = action_input
|
| 534 |
+
print(f"Using action_input as code: {repr(code[:100])}")
|
| 535 |
+
|
| 536 |
+
print(f"Final code to execute: {repr(code[:100])}...")
|
| 537 |
|
| 538 |
# Additional validation: check for unmatched braces
|
| 539 |
open_braces = code.count('{')
|
|
|
|
| 541 |
if open_braces != close_braces:
|
| 542 |
result = f"Error: Code contains unmatched braces. Found {open_braces} '{{' and {close_braces} '}}'. Please check your code syntax."
|
| 543 |
else:
|
| 544 |
+
# Call the code execution function, which now also has improved extraction logic
|
| 545 |
result = run_python_code(code)
|
| 546 |
|
| 547 |
print(f"Code execution result: {result[:100]}...") # Print first 100 chars
|
|
|
|
| 1160 |
# Example usage:
|
| 1161 |
if __name__ == "__main__":
|
| 1162 |
agent = TurboNerd(max_iterations=25)
|
| 1163 |
+
response = agent("""Given this table defining * on the set S = {a, b, c, d, e}
|
| 1164 |
+
|
| 1165 |
+
|*|a|b|c|d|e|
|
| 1166 |
+
|---|---|---|---|---|---|
|
| 1167 |
+
|a|a|b|c|b|d|
|
| 1168 |
+
|b|b|c|a|e|c|
|
| 1169 |
+
|c|c|a|b|b|a|
|
| 1170 |
+
|d|b|e|b|e|d|
|
| 1171 |
+
|e|d|b|a|d|c|
|
| 1172 |
+
|
| 1173 |
+
provide the subset of S involved in any possible counter-examples that prove * is not commutative. Provide your answer as a comma separated list of the elements in the set in alphabetical order.""")
|
| 1174 |
print("\nFinal Response:")
|
| 1175 |
print(response)
|
| 1176 |
|
tools.py
CHANGED
|
@@ -24,46 +24,207 @@ from youtube_transcript_api import YouTubeTranscriptApi, TranscriptsDisabled, No
|
|
| 24 |
|
| 25 |
load_dotenv()
|
| 26 |
|
| 27 |
-
def
|
| 28 |
-
"""
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
"open(", "file(", "eval(", "exec(",
|
| 35 |
-
"__import__", "input(", "raw_input(",
|
| 36 |
-
"__builtins__", "globals(", "locals(",
|
| 37 |
-
"compile(", "execfile(", "reload("
|
| 38 |
-
]
|
| 39 |
|
| 40 |
-
#
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
"from statistics import", "from collections import",
|
| 47 |
-
"from itertools import"
|
| 48 |
-
}
|
| 49 |
|
| 50 |
-
# Check
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
return f"Error: Code contains potentially unsafe operations: {dangerous_op}"
|
| 54 |
|
| 55 |
-
#
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
# Capture stdout to get print output
|
| 68 |
import io
|
| 69 |
import sys
|
|
|
|
| 24 |
|
| 25 |
load_dotenv()
|
| 26 |
|
| 27 |
+
def extract_python_code_from_complex_input(input_text):
|
| 28 |
+
"""
|
| 29 |
+
Dedicated function to extract Python code from deeply nested JSON structures.
|
| 30 |
+
This function handles the specific case of Python code embedded in nested JSON.
|
| 31 |
+
"""
|
| 32 |
+
import re
|
| 33 |
+
import json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
+
# Convert to string if it's not already
|
| 36 |
+
if not isinstance(input_text, str):
|
| 37 |
+
try:
|
| 38 |
+
input_text = json.dumps(input_text)
|
| 39 |
+
except:
|
| 40 |
+
input_text = str(input_text)
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
+
# Check if this looks like a JSON structure containing code
|
| 43 |
+
if not (input_text.strip().startswith('{') and '"code"' in input_text):
|
| 44 |
+
return input_text # Not a JSON structure, return as is
|
|
|
|
| 45 |
|
| 46 |
+
# First attempt: Try to extract using a direct regex for the nested case
|
| 47 |
+
# This pattern looks for "code": "..." with proper escaping
|
| 48 |
+
pattern = re.compile(r'"code"\s*:\s*"(.*?)(?<!\\)"\s*}', re.DOTALL)
|
| 49 |
+
matches = pattern.findall(input_text)
|
| 50 |
+
|
| 51 |
+
if matches:
|
| 52 |
+
# Get the longest match (most likely the complete code)
|
| 53 |
+
extracted_code = max(matches, key=len)
|
| 54 |
+
|
| 55 |
+
# Unescape common escape sequences
|
| 56 |
+
extracted_code = extracted_code.replace('\\n', '\n')
|
| 57 |
+
extracted_code = extracted_code.replace('\\"', '"')
|
| 58 |
+
extracted_code = extracted_code.replace("\\'", "'")
|
| 59 |
+
extracted_code = extracted_code.replace("\\\\", "\\")
|
| 60 |
+
|
| 61 |
+
print(f"Extracted code using direct regex approach: {extracted_code[:50]}...")
|
| 62 |
+
return extracted_code
|
| 63 |
+
|
| 64 |
+
# Second attempt: Try JSON parsing and navigate the structure
|
| 65 |
+
try:
|
| 66 |
+
parsed = json.loads(input_text)
|
| 67 |
+
|
| 68 |
+
# Navigate through possible structures
|
| 69 |
+
if isinstance(parsed, dict):
|
| 70 |
+
# Direct code field
|
| 71 |
+
if 'code' in parsed:
|
| 72 |
+
extracted = parsed['code']
|
| 73 |
+
if isinstance(extracted, str):
|
| 74 |
+
return extracted
|
| 75 |
+
|
| 76 |
+
# Action with action_input structure
|
| 77 |
+
if 'action' in parsed and 'action_input' in parsed:
|
| 78 |
+
action_input = parsed['action_input']
|
| 79 |
+
|
| 80 |
+
# Case 1: action_input is a dict with code
|
| 81 |
+
if isinstance(action_input, dict) and 'code' in action_input:
|
| 82 |
+
return action_input['code']
|
| 83 |
+
|
| 84 |
+
# Case 2: action_input is a string that might be JSON
|
| 85 |
+
if isinstance(action_input, str):
|
| 86 |
+
try:
|
| 87 |
+
nested = json.loads(action_input)
|
| 88 |
+
if isinstance(nested, dict) and 'code' in nested:
|
| 89 |
+
return nested['code']
|
| 90 |
+
except:
|
| 91 |
+
# If it's not valid JSON, might be the code itself
|
| 92 |
+
return action_input
|
| 93 |
+
except:
|
| 94 |
+
# If JSON parsing fails, try one more regex approach
|
| 95 |
+
# This looks for any content between balanced braces
|
| 96 |
+
try:
|
| 97 |
+
# Find the innermost code field
|
| 98 |
+
code_start = input_text.rfind('"code"')
|
| 99 |
+
if code_start != -1:
|
| 100 |
+
# Find the start of the value (after the colon and quote)
|
| 101 |
+
value_start = input_text.find(':', code_start)
|
| 102 |
+
if value_start != -1:
|
| 103 |
+
value_start = input_text.find('"', value_start)
|
| 104 |
+
if value_start != -1:
|
| 105 |
+
value_start += 1 # Move past the quote
|
| 106 |
+
# Now find the end quote that's not escaped
|
| 107 |
+
value_end = value_start
|
| 108 |
+
while True:
|
| 109 |
+
next_quote = input_text.find('"', value_end + 1)
|
| 110 |
+
if next_quote == -1:
|
| 111 |
+
break
|
| 112 |
+
# Check if this quote is escaped
|
| 113 |
+
if input_text[next_quote - 1] != '\\':
|
| 114 |
+
value_end = next_quote
|
| 115 |
+
break
|
| 116 |
+
value_end = next_quote
|
| 117 |
+
|
| 118 |
+
if value_end > value_start:
|
| 119 |
+
extracted = input_text[value_start:value_end]
|
| 120 |
+
# Unescape
|
| 121 |
+
extracted = extracted.replace('\\n', '\n')
|
| 122 |
+
extracted = extracted.replace('\\"', '"')
|
| 123 |
+
extracted = extracted.replace("\\'", "'")
|
| 124 |
+
extracted = extracted.replace("\\\\", "\\")
|
| 125 |
+
return extracted
|
| 126 |
+
except:
|
| 127 |
+
pass
|
| 128 |
|
| 129 |
+
# If all else fails, return the original input
|
| 130 |
+
return input_text
|
| 131 |
+
|
| 132 |
+
def run_python_code(code: str):
|
| 133 |
+
"""Execute Python code safely using exec() instead of subprocess."""
|
| 134 |
try:
|
| 135 |
+
# Pre-process code to handle complex nested structures
|
| 136 |
+
# This is our most aggressive approach to extract the actual code
|
| 137 |
+
code = extract_python_code_from_complex_input(code)
|
| 138 |
+
|
| 139 |
+
# First, check if the input is a nested JSON structure
|
| 140 |
+
if code.strip().startswith('{') and ('"action"' in code or "'action'" in code):
|
| 141 |
+
try:
|
| 142 |
+
# Common issue: escaped quotes causing JSON parse errors
|
| 143 |
+
# Pre-process to handle common escaping problems
|
| 144 |
+
preprocessed_code = code
|
| 145 |
+
|
| 146 |
+
# Handle the specific case we're seeing with nested escaped quotes
|
| 147 |
+
import re
|
| 148 |
+
|
| 149 |
+
# Search for nested code pattern - this is a more direct approach
|
| 150 |
+
code_pattern = re.search(r'"code"\s*:\s*"(.*?)"\s*\}\s*\}\s*\}', code, re.DOTALL)
|
| 151 |
+
if code_pattern:
|
| 152 |
+
extracted_code = code_pattern.group(1)
|
| 153 |
+
# Unescape the extracted code
|
| 154 |
+
extracted_code = extracted_code.replace('\\n', '\n').replace('\\"', '"').replace("\\'", "'")
|
| 155 |
+
code = extracted_code
|
| 156 |
+
print(f"Extracted code using regex pattern: {code[:100]}")
|
| 157 |
+
else:
|
| 158 |
+
# Try JSON parsing approach if regex fails
|
| 159 |
+
import json
|
| 160 |
+
try:
|
| 161 |
+
# First try direct parsing
|
| 162 |
+
parsed_json = json.loads(code)
|
| 163 |
+
|
| 164 |
+
# Check if this is an action structure with embedded code
|
| 165 |
+
if 'action' in parsed_json and 'action_input' in parsed_json:
|
| 166 |
+
if isinstance(parsed_json['action_input'], dict) and 'code' in parsed_json['action_input']:
|
| 167 |
+
# Extract the actual code from the nested structure
|
| 168 |
+
code = parsed_json['action_input']['code']
|
| 169 |
+
print(f"Extracted code using JSON parsing: {code[:100]}")
|
| 170 |
+
elif isinstance(parsed_json['action_input'], str):
|
| 171 |
+
# Try to parse the action_input as JSON if it's a string
|
| 172 |
+
try:
|
| 173 |
+
inner_input = json.loads(parsed_json['action_input'])
|
| 174 |
+
if isinstance(inner_input, dict) and 'code' in inner_input:
|
| 175 |
+
code = inner_input['code']
|
| 176 |
+
print(f"Extracted nested code: {code[:100]}")
|
| 177 |
+
except:
|
| 178 |
+
# If parsing fails, assume the action_input itself is the code
|
| 179 |
+
code = parsed_json['action_input']
|
| 180 |
+
print(f"Using action_input as code: {code[:100]}")
|
| 181 |
+
except json.JSONDecodeError:
|
| 182 |
+
# Direct parsing failed, try alternative approaches
|
| 183 |
+
print("JSON parsing failed, trying alternative approaches")
|
| 184 |
+
except Exception as e:
|
| 185 |
+
print(f"Error during code extraction: {str(e)}")
|
| 186 |
+
# If JSON parsing fails, proceed with the original code
|
| 187 |
+
pass
|
| 188 |
+
|
| 189 |
+
print(f"Final code to execute: {code[:100]}...")
|
| 190 |
+
|
| 191 |
+
# Check for potentially dangerous operations
|
| 192 |
+
dangerous_operations = [
|
| 193 |
+
"os.system", "os.popen", "os.unlink", "os.remove",
|
| 194 |
+
"subprocess.run", "subprocess.call", "subprocess.Popen",
|
| 195 |
+
"shutil.rmtree", "shutil.move", "shutil.copy",
|
| 196 |
+
"open(", "file(", "eval(", "exec(",
|
| 197 |
+
"__import__", "input(", "raw_input(",
|
| 198 |
+
"__builtins__", "globals(", "locals(",
|
| 199 |
+
"compile(", "execfile(", "reload("
|
| 200 |
+
]
|
| 201 |
+
|
| 202 |
+
# Safe imports that should be allowed
|
| 203 |
+
safe_imports = {
|
| 204 |
+
"import datetime", "import math", "import random",
|
| 205 |
+
"import statistics", "import collections", "import itertools",
|
| 206 |
+
"import re", "import json", "import csv", "import numpy",
|
| 207 |
+
"import pandas", "from math import", "from datetime import",
|
| 208 |
+
"from statistics import", "from collections import",
|
| 209 |
+
"from itertools import"
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
# Check for dangerous operations
|
| 213 |
+
for dangerous_op in dangerous_operations:
|
| 214 |
+
if dangerous_op in code:
|
| 215 |
+
return f"Error: Code contains potentially unsafe operations: {dangerous_op}"
|
| 216 |
+
|
| 217 |
+
# Check each line for imports
|
| 218 |
+
for line in code.splitlines():
|
| 219 |
+
line = line.strip()
|
| 220 |
+
if line.startswith("import ") or line.startswith("from "):
|
| 221 |
+
# Check if it's in our safe list
|
| 222 |
+
is_safe = any(line.startswith(safe_import) for safe_import in safe_imports)
|
| 223 |
+
# Also allow basic numpy/pandas imports
|
| 224 |
+
is_safe = is_safe or line.startswith("import numpy") or line.startswith("import pandas")
|
| 225 |
+
if not is_safe:
|
| 226 |
+
return f"Error: Code contains potentially unsafe import: {line}"
|
| 227 |
+
|
| 228 |
# Capture stdout to get print output
|
| 229 |
import io
|
| 230 |
import sys
|