Lasdw commited on
Commit
30e851e
·
1 Parent(s): 85c9819

Improved python code tool

Browse files
Files changed (2) hide show
  1. README.md +2 -2
  2. agent.py +129 -54
README.md CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
- title: Template Final Assignment
3
  emoji: 🏆
4
- colorFrom: indigo
5
  colorTo: blue
6
  sdk: gradio
7
  sdk_version: 5.29.0
 
1
  ---
2
+ title: Deep Research Agent
3
  emoji: 🏆
4
+ colorFrom: yellow
5
  colorTo: blue
6
  sdk: gradio
7
  sdk_version: 5.29.0
agent.py CHANGED
@@ -31,21 +31,26 @@ from supabase import create_client, Client
31
  load_dotenv()
32
 
33
  def run_python_code(code: str):
34
- """Execute Python code in a temporary file and return the output."""
35
  # Check for potentially dangerous operations
36
  dangerous_operations = [
37
  "os.system", "os.popen", "os.unlink", "os.remove",
38
  "subprocess.run", "subprocess.call", "subprocess.Popen",
39
  "shutil.rmtree", "shutil.move", "shutil.copy",
40
  "open(", "file(", "eval(", "exec(",
41
- "__import__"
 
 
42
  ]
43
 
44
  # Safe imports that should be allowed
45
  safe_imports = {
46
  "import datetime", "import math", "import random",
47
  "import statistics", "import collections", "import itertools",
48
- "import re", "import json", "import csv"
 
 
 
49
  }
50
 
51
  # Check for dangerous operations
@@ -57,62 +62,122 @@ def run_python_code(code: str):
57
  for line in code.splitlines():
58
  line = line.strip()
59
  if line.startswith("import ") or line.startswith("from "):
60
- # Skip if it's in our safe list
61
- if any(line.startswith(safe_import) for safe_import in safe_imports):
62
- continue
 
 
63
  return f"Error: Code contains potentially unsafe import: {line}"
64
 
65
- # Add print statements to capture the result
66
- # Find the last expression to capture its value
67
- lines = code.splitlines()
68
- modified_lines = []
69
-
70
- for i, line in enumerate(lines):
71
- modified_lines.append(line)
72
- # If this is the last line and doesn't have a print statement
73
- if i == len(lines) - 1 and not (line.strip().startswith("print(") or line.strip() == ""):
74
- # Add a print statement for the last expression
75
- if not line.strip().endswith(":"): # Not a control structure
76
- modified_lines.append(f"print('Result:', {line.strip()})")
77
-
78
- modified_code = "\n".join(modified_lines)
79
-
80
  try:
81
- # Create a temporary file
82
- with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as temp:
83
- temp_path = temp.name
84
- # Write the code to the file
85
- temp.write(modified_code.encode('utf-8'))
86
-
87
- # Run the Python file with restricted permissions
88
- result = subprocess.run(
89
- ['python', temp_path],
90
- capture_output=True,
91
- text=True,
92
- timeout=10 # Set a timeout to prevent infinite loops
93
- )
 
 
 
 
 
 
94
 
95
- # Clean up the temporary file
96
- os.unlink(temp_path)
97
-
98
- # Return the output or error
99
- if result.returncode == 0:
100
- output = result.stdout.strip()
101
- # If the output is empty but the code ran successfully
102
- if not output:
103
- # Try to extract the last line and evaluate it
104
- last_line = lines[-1].strip()
105
- if not last_line.startswith("print") and not last_line.endswith(":"):
106
- return f"Code executed successfully. The result of the last expression '{last_line}' should be its value."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  else:
108
- return "Code executed successfully with no output."
109
- return output
 
 
 
 
 
110
  else:
111
- return f"Error executing code: {result.stderr}"
112
- except subprocess.TimeoutExpired:
113
- # Clean up if timeout
114
- os.unlink(temp_path)
115
- return "Error: Code execution timed out after 10 seconds."
 
 
 
 
 
 
 
116
  except Exception as e:
117
  return f"Error executing code: {str(e)}"
118
 
@@ -1365,7 +1430,17 @@ class TurboNerd:
1365
  # Example usage:
1366
  if __name__ == "__main__":
1367
  agent = TurboNerd(max_execution_time=60)
1368
- response = agent("When was a picture of St. Thomas Aquinas first added to the Wikipedia page on the Principle of double effect?")
 
 
 
 
 
 
 
 
 
 
1369
  print("\nFinal Response:")
1370
  print(response)
1371
 
 
31
  load_dotenv()
32
 
33
  def run_python_code(code: str):
34
+ """Execute Python code safely using exec() instead of subprocess."""
35
  # Check for potentially dangerous operations
36
  dangerous_operations = [
37
  "os.system", "os.popen", "os.unlink", "os.remove",
38
  "subprocess.run", "subprocess.call", "subprocess.Popen",
39
  "shutil.rmtree", "shutil.move", "shutil.copy",
40
  "open(", "file(", "eval(", "exec(",
41
+ "__import__", "input(", "raw_input(",
42
+ "__builtins__", "globals(", "locals(",
43
+ "compile(", "execfile(", "reload("
44
  ]
45
 
46
  # Safe imports that should be allowed
47
  safe_imports = {
48
  "import datetime", "import math", "import random",
49
  "import statistics", "import collections", "import itertools",
50
+ "import re", "import json", "import csv", "import numpy",
51
+ "import pandas", "from math import", "from datetime import",
52
+ "from statistics import", "from collections import",
53
+ "from itertools import"
54
  }
55
 
56
  # Check for dangerous operations
 
62
  for line in code.splitlines():
63
  line = line.strip()
64
  if line.startswith("import ") or line.startswith("from "):
65
+ # Check if it's in our safe list
66
+ is_safe = any(line.startswith(safe_import) for safe_import in safe_imports)
67
+ # Also allow basic numpy/pandas imports
68
+ is_safe = is_safe or line.startswith("import numpy") or line.startswith("import pandas")
69
+ if not is_safe:
70
  return f"Error: Code contains potentially unsafe import: {line}"
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  try:
73
+ # Capture stdout to get print output
74
+ import io
75
+ import sys
76
+ from contextlib import redirect_stdout
77
+
78
+ # Create a restricted globals environment
79
+ restricted_globals = {
80
+ '__builtins__': {
81
+ 'abs': abs, 'all': all, 'any': any, 'bin': bin, 'bool': bool,
82
+ 'chr': chr, 'dict': dict, 'dir': dir, 'divmod': divmod,
83
+ 'enumerate': enumerate, 'filter': filter, 'float': float,
84
+ 'format': format, 'hex': hex, 'int': int, 'len': len,
85
+ 'list': list, 'map': map, 'max': max, 'min': min, 'oct': oct,
86
+ 'ord': ord, 'pow': pow, 'print': print, 'range': range,
87
+ 'reversed': reversed, 'round': round, 'set': set, 'slice': slice,
88
+ 'sorted': sorted, 'str': str, 'sum': sum, 'tuple': tuple,
89
+ 'type': type, 'zip': zip,
90
+ }
91
+ }
92
 
93
+ # Allow safe modules
94
+ import math
95
+ import datetime
96
+ import random
97
+ import statistics
98
+ import collections
99
+ import itertools
100
+ import re
101
+ import json
102
+ import csv
103
+
104
+ restricted_globals['math'] = math
105
+ restricted_globals['datetime'] = datetime
106
+ restricted_globals['random'] = random
107
+ restricted_globals['statistics'] = statistics
108
+ restricted_globals['collections'] = collections
109
+ restricted_globals['itertools'] = itertools
110
+ restricted_globals['re'] = re
111
+ restricted_globals['json'] = json
112
+ restricted_globals['csv'] = csv
113
+
114
+ # Try to import numpy and pandas if available
115
+ try:
116
+ import numpy as np
117
+ restricted_globals['numpy'] = np
118
+ restricted_globals['np'] = np
119
+ except ImportError:
120
+ pass
121
+
122
+ try:
123
+ import pandas as pd
124
+ restricted_globals['pandas'] = pd
125
+ restricted_globals['pd'] = pd
126
+ except ImportError:
127
+ pass
128
+
129
+ # Create local scope
130
+ local_scope = {}
131
+
132
+ # Capture stdout
133
+ captured_output = io.StringIO()
134
+
135
+ # Execute the code with timeout simulation (not perfect but better than nothing)
136
+ with redirect_stdout(captured_output):
137
+ # Split code into lines and execute
138
+ lines = code.strip().split('\n')
139
+ last_line = None
140
+
141
+ for i, line in enumerate(lines):
142
+ line = line.strip()
143
+ if not line or line.startswith('#'):
144
+ continue
145
+
146
+ # Check if this is the last meaningful line
147
+ is_last = i == len(lines) - 1
148
+
149
+ # Execute the line
150
+ if is_last and not any(keyword in line for keyword in ['print', 'for', 'while', 'if', 'def', 'class', 'try', 'with']):
151
+ # If it's the last line and looks like an expression, store it
152
+ try:
153
+ # Try to evaluate as expression first
154
+ result = eval(line, restricted_globals, local_scope)
155
+ local_scope['_last_result'] = result
156
+ print(f"Result: {result}")
157
+ except:
158
+ # If that fails, execute as statement
159
+ exec(line, restricted_globals, local_scope)
160
  else:
161
+ exec(line, restricted_globals, local_scope)
162
+
163
+ # Get the captured output
164
+ output = captured_output.getvalue()
165
+
166
+ if output.strip():
167
+ return output.strip()
168
  else:
169
+ # If no output but we have a last result, show it
170
+ if '_last_result' in local_scope:
171
+ return f"Result: {local_scope['_last_result']}"
172
+ else:
173
+ return "Code executed successfully with no output."
174
+
175
+ except SyntaxError as e:
176
+ return f"Syntax Error: {str(e)}"
177
+ except NameError as e:
178
+ return f"Name Error: {str(e)}"
179
+ except ZeroDivisionError as e:
180
+ return f"Zero Division Error: {str(e)}"
181
  except Exception as e:
182
  return f"Error executing code: {str(e)}"
183
 
 
1430
  # Example usage:
1431
  if __name__ == "__main__":
1432
  agent = TurboNerd(max_execution_time=60)
1433
+ response = agent("""Given this table defining * on the set S = {a, b, c, d, e}
1434
+
1435
+ |*|a|b|c|d|e|
1436
+ |---|---|---|---|---|---|
1437
+ |a|a|b|c|b|d|
1438
+ |b|b|c|a|e|c|
1439
+ |c|c|a|b|b|a|
1440
+ |d|b|e|b|e|d|
1441
+ |e|d|b|a|d|c|
1442
+
1443
+ 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.""")
1444
  print("\nFinal Response:")
1445
  print(response)
1446