mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-01 23:32:39 +00:00
Squashed 'packages/tools/' content from commit 78317b9c
git-subtree-dir: packages/tools git-subtree-split: 78317b9c127f18bd040c1d77e3c0840cdc9a5b38
This commit is contained in:
35
crewai_tools/tools/file_writer_tool/README.md
Normal file
35
crewai_tools/tools/file_writer_tool/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
Here's the rewritten README for the `FileWriterTool`:
|
||||
|
||||
# FileWriterTool Documentation
|
||||
|
||||
## Description
|
||||
The `FileWriterTool` is a component of the crewai_tools package, designed to simplify the process of writing content to files. It is particularly useful in scenarios such as generating reports, saving logs, creating configuration files, and more. This tool supports creating new directories if they don't exist, making it easier to organize your output.
|
||||
|
||||
## Installation
|
||||
Install the crewai_tools package to use the `FileWriterTool` in your projects:
|
||||
|
||||
```shell
|
||||
pip install 'crewai[tools]'
|
||||
```
|
||||
|
||||
## Example
|
||||
To get started with the `FileWriterTool`:
|
||||
|
||||
```python
|
||||
from crewai_tools import FileWriterTool
|
||||
|
||||
# Initialize the tool
|
||||
file_writer_tool = FileWriterTool()
|
||||
|
||||
# Write content to a file in a specified directory
|
||||
result = file_writer_tool._run('example.txt', 'This is a test content.', 'test_directory')
|
||||
print(result)
|
||||
```
|
||||
|
||||
## Arguments
|
||||
- `filename`: The name of the file you want to create or overwrite.
|
||||
- `content`: The content to write into the file.
|
||||
- `directory` (optional): The path to the directory where the file will be created. Defaults to the current directory (`.`). If the directory does not exist, it will be created.
|
||||
|
||||
## Conclusion
|
||||
By integrating the `FileWriterTool` into your crews, the agents can execute the process of writing content to files and creating directories. This tool is essential for tasks that require saving output data, creating structured file systems, and more. By adhering to the setup and usage guidelines provided, incorporating this tool into projects is straightforward and efficient.
|
||||
62
crewai_tools/tools/file_writer_tool/file_writer_tool.py
Normal file
62
crewai_tools/tools/file_writer_tool/file_writer_tool.py
Normal file
@@ -0,0 +1,62 @@
|
||||
import os
|
||||
from typing import Any, Optional, Type
|
||||
|
||||
from crewai.tools import BaseTool
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
def strtobool(val) -> bool:
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
val = val.lower()
|
||||
if val in ("y", "yes", "t", "true", "on", "1"):
|
||||
return True
|
||||
elif val in ("n", "no", "f", "false", "off", "0"):
|
||||
return False
|
||||
else:
|
||||
raise ValueError(f"invalid value to cast to bool: {val!r}")
|
||||
|
||||
|
||||
class FileWriterToolInput(BaseModel):
|
||||
filename: str
|
||||
directory: Optional[str] = "./"
|
||||
overwrite: str | bool = False
|
||||
content: str
|
||||
|
||||
|
||||
class FileWriterTool(BaseTool):
|
||||
name: str = "File Writer Tool"
|
||||
description: str = (
|
||||
"A tool to write content to a specified file. Accepts filename, content, and optionally a directory path and overwrite flag as input."
|
||||
)
|
||||
args_schema: Type[BaseModel] = FileWriterToolInput
|
||||
|
||||
def _run(self, **kwargs: Any) -> str:
|
||||
try:
|
||||
# Create the directory if it doesn't exist
|
||||
if kwargs.get("directory") and not os.path.exists(kwargs["directory"]):
|
||||
os.makedirs(kwargs["directory"])
|
||||
|
||||
# Construct the full path
|
||||
filepath = os.path.join(kwargs.get("directory") or "", kwargs["filename"])
|
||||
|
||||
# Convert overwrite to boolean
|
||||
kwargs["overwrite"] = strtobool(kwargs["overwrite"])
|
||||
|
||||
# Check if file exists and overwrite is not allowed
|
||||
if os.path.exists(filepath) and not kwargs["overwrite"]:
|
||||
return f"File {filepath} already exists and overwrite option was not passed."
|
||||
|
||||
# Write content to the file
|
||||
mode = "w" if kwargs["overwrite"] else "x"
|
||||
with open(filepath, mode) as file:
|
||||
file.write(kwargs["content"])
|
||||
return f"Content successfully written to {filepath}"
|
||||
except FileExistsError:
|
||||
return (
|
||||
f"File {filepath} already exists and overwrite option was not passed."
|
||||
)
|
||||
except KeyError as e:
|
||||
return f"An error occurred while accessing key: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"An error occurred while writing to the file: {str(e)}"
|
||||
@@ -0,0 +1,138 @@
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
||||
from crewai_tools.tools.file_writer_tool.file_writer_tool import FileWriterTool
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tool():
|
||||
return FileWriterTool()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_env():
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
test_file = "test.txt"
|
||||
test_content = "Hello, World!"
|
||||
|
||||
yield {
|
||||
"temp_dir": temp_dir,
|
||||
"test_file": test_file,
|
||||
"test_content": test_content,
|
||||
}
|
||||
|
||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||
|
||||
|
||||
def get_test_path(filename, directory):
|
||||
return os.path.join(directory, filename)
|
||||
|
||||
|
||||
def read_file(path):
|
||||
with open(path, "r") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def test_basic_file_write(tool, temp_env):
|
||||
result = tool._run(
|
||||
filename=temp_env["test_file"],
|
||||
directory=temp_env["temp_dir"],
|
||||
content=temp_env["test_content"],
|
||||
overwrite=True,
|
||||
)
|
||||
|
||||
path = get_test_path(temp_env["test_file"], temp_env["temp_dir"])
|
||||
assert os.path.exists(path)
|
||||
assert read_file(path) == temp_env["test_content"]
|
||||
assert "successfully written" in result
|
||||
|
||||
|
||||
def test_directory_creation(tool, temp_env):
|
||||
new_dir = os.path.join(temp_env["temp_dir"], "nested_dir")
|
||||
result = tool._run(
|
||||
filename=temp_env["test_file"],
|
||||
directory=new_dir,
|
||||
content=temp_env["test_content"],
|
||||
overwrite=True,
|
||||
)
|
||||
|
||||
path = get_test_path(temp_env["test_file"], new_dir)
|
||||
assert os.path.exists(new_dir)
|
||||
assert os.path.exists(path)
|
||||
assert "successfully written" in result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"overwrite",
|
||||
["y", "yes", "t", "true", "on", "1", True],
|
||||
)
|
||||
def test_overwrite_true(tool, temp_env, overwrite):
|
||||
path = get_test_path(temp_env["test_file"], temp_env["temp_dir"])
|
||||
with open(path, "w") as f:
|
||||
f.write("Original content")
|
||||
|
||||
result = tool._run(
|
||||
filename=temp_env["test_file"],
|
||||
directory=temp_env["temp_dir"],
|
||||
content="New content",
|
||||
overwrite=overwrite,
|
||||
)
|
||||
|
||||
assert read_file(path) == "New content"
|
||||
assert "successfully written" in result
|
||||
|
||||
|
||||
def test_invalid_overwrite_value(tool, temp_env):
|
||||
result = tool._run(
|
||||
filename=temp_env["test_file"],
|
||||
directory=temp_env["temp_dir"],
|
||||
content=temp_env["test_content"],
|
||||
overwrite="invalid",
|
||||
)
|
||||
assert "invalid value" in result
|
||||
|
||||
|
||||
def test_missing_required_fields(tool, temp_env):
|
||||
result = tool._run(
|
||||
directory=temp_env["temp_dir"],
|
||||
content=temp_env["test_content"],
|
||||
overwrite=True,
|
||||
)
|
||||
assert "An error occurred while accessing key: 'filename'" in result
|
||||
|
||||
|
||||
def test_empty_content(tool, temp_env):
|
||||
result = tool._run(
|
||||
filename=temp_env["test_file"],
|
||||
directory=temp_env["temp_dir"],
|
||||
content="",
|
||||
overwrite=True,
|
||||
)
|
||||
|
||||
path = get_test_path(temp_env["test_file"], temp_env["temp_dir"])
|
||||
assert os.path.exists(path)
|
||||
assert read_file(path) == ""
|
||||
assert "successfully written" in result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"overwrite",
|
||||
["n", "no", "f", "false", "off", "0", False],
|
||||
)
|
||||
def test_file_exists_error_handling(tool, temp_env, overwrite):
|
||||
path = get_test_path(temp_env["test_file"], temp_env["temp_dir"])
|
||||
with open(path, "w") as f:
|
||||
f.write("Pre-existing content")
|
||||
|
||||
result = tool._run(
|
||||
filename=temp_env["test_file"],
|
||||
directory=temp_env["temp_dir"],
|
||||
content="Should not be written",
|
||||
overwrite=overwrite,
|
||||
)
|
||||
|
||||
assert "already exists and overwrite option was not passed" in result
|
||||
assert read_file(path) == "Pre-existing content"
|
||||
Reference in New Issue
Block a user