mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-10 07:38:04 -05:00
Add support for args to execute_python_file (#3972)
* 🎉 Python scripts can now be executed with arguments through Docker.🎉 * Make args optional --------- Co-authored-by: k-boikov <64261260+k-boikov@users.noreply.github.com> Co-authored-by: Reinier van der Leer <reinier.vanderleer@agpt.co>
This commit is contained in:
@@ -79,14 +79,22 @@ def execute_python_code(code: str, agent: Agent) -> str:
|
||||
"description": "The name of te file to execute",
|
||||
"required": True,
|
||||
},
|
||||
"args": {
|
||||
"type": "list[str]",
|
||||
"description": "The (command line) arguments to pass to the script",
|
||||
"required": False,
|
||||
},
|
||||
},
|
||||
)
|
||||
@sanitize_path_arg("filename")
|
||||
def execute_python_file(filename: Path, agent: Agent) -> str:
|
||||
def execute_python_file(
|
||||
filename: Path, agent: Agent, args: list[str] | str = []
|
||||
) -> str:
|
||||
"""Execute a Python file in a Docker container and return the output
|
||||
|
||||
Args:
|
||||
filename (Path): The name of the file to execute
|
||||
args (list, optional): The arguments with which to run the python script
|
||||
|
||||
Returns:
|
||||
str: The output of the file
|
||||
@@ -95,6 +103,9 @@ def execute_python_file(filename: Path, agent: Agent) -> str:
|
||||
f"Executing python file '{filename}' in working directory '{agent.config.workspace_path}'"
|
||||
)
|
||||
|
||||
if isinstance(args, str):
|
||||
args = args.split() # Convert space-separated string to a list
|
||||
|
||||
if not str(filename).endswith(".py"):
|
||||
raise InvalidArgumentError("Invalid file type. Only .py files are allowed.")
|
||||
|
||||
@@ -110,7 +121,7 @@ def execute_python_file(filename: Path, agent: Agent) -> str:
|
||||
f"Auto-GPT is running in a Docker container; executing {file_path} directly..."
|
||||
)
|
||||
result = subprocess.run(
|
||||
["python", "-B", str(file_path)],
|
||||
["python", "-B", str(file_path)] + args,
|
||||
capture_output=True,
|
||||
encoding="utf8",
|
||||
cwd=str(agent.workspace.root),
|
||||
@@ -152,7 +163,7 @@ def execute_python_file(filename: Path, agent: Agent) -> str:
|
||||
"python",
|
||||
"-B",
|
||||
file_path.relative_to(agent.workspace.root).as_posix(),
|
||||
],
|
||||
] + args,
|
||||
volumes={
|
||||
str(agent.workspace.root): {
|
||||
"bind": "/workspace",
|
||||
|
||||
@@ -2,6 +2,7 @@ import os
|
||||
import random
|
||||
import string
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -21,12 +22,22 @@ def random_code(random_string) -> str:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def python_test_file(config: Config, random_code: str) -> str:
|
||||
def python_test_file(config: Config, random_code: str):
|
||||
temp_file = tempfile.NamedTemporaryFile(dir=config.workspace_path, suffix=".py")
|
||||
temp_file.write(str.encode(random_code))
|
||||
temp_file.flush()
|
||||
|
||||
yield temp_file.name
|
||||
yield Path(temp_file.name)
|
||||
temp_file.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def python_test_args_file(config: Config):
|
||||
temp_file = tempfile.NamedTemporaryFile(dir=config.workspace_path, suffix=".py")
|
||||
temp_file.write(str.encode("import sys\nprint(sys.argv[1], sys.argv[2])"))
|
||||
temp_file.flush()
|
||||
|
||||
yield Path(temp_file.name)
|
||||
temp_file.close()
|
||||
|
||||
|
||||
@@ -35,23 +46,25 @@ def random_string():
|
||||
return "".join(random.choice(string.ascii_lowercase) for _ in range(10))
|
||||
|
||||
|
||||
def test_execute_python_file(python_test_file: str, random_string: str, agent: Agent):
|
||||
def test_execute_python_file(python_test_file: Path, random_string: str, agent: Agent):
|
||||
result: str = sut.execute_python_file(python_test_file, agent=agent)
|
||||
assert result.replace("\r", "") == f"Hello {random_string}!\n"
|
||||
|
||||
|
||||
def test_execute_python_file_args(
|
||||
python_test_args_file: Path, random_string: str, agent: Agent
|
||||
):
|
||||
random_args = [random_string] * 2
|
||||
random_args_string = " ".join(random_args)
|
||||
result = sut.execute_python_file(python_test_args_file, agent=agent, random_args)
|
||||
assert result == f"{random_args_string}\n"
|
||||
|
||||
|
||||
def test_execute_python_code(random_code: str, random_string: str, agent: Agent):
|
||||
result: str = sut.execute_python_code(random_code, agent=agent)
|
||||
assert result.replace("\r", "") == f"Hello {random_string}!\n"
|
||||
|
||||
|
||||
def test_execute_python_code_disallows_name_arg_path_traversal(
|
||||
random_code: str, agent: Agent
|
||||
):
|
||||
with pytest.raises(AccessDeniedError, match="path traversal"):
|
||||
sut.execute_python_code(random_code, agent=agent)
|
||||
|
||||
|
||||
def test_execute_python_code_overwrites_file(random_code: str, agent: Agent):
|
||||
ai_name = agent.ai_config.ai_name
|
||||
destination = os.path.join(
|
||||
|
||||
Reference in New Issue
Block a user