basic-open-agent-tools 0.4.0__tar.gz → 0.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. {basic_open_agent_tools-0.4.0/src/basic_open_agent_tools.egg-info → basic_open_agent_tools-0.4.2}/PKG-INFO +1 -1
  2. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/pyproject.toml +1 -1
  3. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/file_system/__init__.py +4 -0
  4. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/file_system/operations.py +95 -0
  5. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2/src/basic_open_agent_tools.egg-info}/PKG-INFO +1 -1
  6. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_transform.py +0 -1
  7. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_file_system_tools.py +82 -1
  8. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/LICENSE +0 -0
  9. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/README.md +0 -0
  10. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/setup.cfg +0 -0
  11. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/setup.py +0 -0
  12. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/__init__.py +0 -0
  13. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/crypto/__init__.py +0 -0
  14. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/__init__.py +0 -0
  15. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/archive_processing.py +0 -0
  16. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/binary_processing.py +0 -0
  17. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/config_processing.py +0 -0
  18. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/csv_tools.py +0 -0
  19. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/json_tools.py +0 -0
  20. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/object_serialization.py +0 -0
  21. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/structures.py +0 -0
  22. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/transform.py +0 -0
  23. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/data/validation.py +0 -0
  24. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/exceptions.py +0 -0
  25. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/file_system/info.py +0 -0
  26. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/file_system/tree.py +0 -0
  27. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/file_system/validation.py +0 -0
  28. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/helpers.py +0 -0
  29. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/network/__init__.py +0 -0
  30. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/system/__init__.py +0 -0
  31. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/text/__init__.py +0 -0
  32. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/text/processing.py +0 -0
  33. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/types.py +0 -0
  34. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools/utilities/__init__.py +0 -0
  35. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools.egg-info/SOURCES.txt +0 -0
  36. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools.egg-info/dependency_links.txt +0 -0
  37. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools.egg-info/requires.txt +0 -0
  38. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/src/basic_open_agent_tools.egg-info/top_level.txt +0 -0
  39. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_archive_processing.py +0 -0
  40. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_binary_processing.py +0 -0
  41. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_config_processing.py +0 -0
  42. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_csv_tools.py +0 -0
  43. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_json_tools.py +0 -0
  44. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_object_serialization.py +0 -0
  45. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_structures.py +0 -0
  46. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_data_validation.py +0 -0
  47. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_helpers.py +0 -0
  48. {basic_open_agent_tools-0.4.0 → basic_open_agent_tools-0.4.2}/tests/test_text_processing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-open-agent-tools
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: An open foundational toolkit providing essential components for building AI agents with minimal dependencies for local (non-HTTP/API) actions.
5
5
  Home-page: https://github.com/open-agent-tools/basic-open-agent-tools
6
6
  Author: Open Agent Tools
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"
4
4
 
5
5
  [project]
6
6
  name = "basic-open-agent-tools"
7
- version = "0.4.0" # Advanced data processing modules complete
7
+ version = "0.4.2" # Add targeted file editing functions for safer agent operations
8
8
  description = "An open foundational toolkit providing essential components for building AI agents with minimal dependencies for local (non-HTTP/API) actions."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -27,9 +27,11 @@ from .operations import (
27
27
  create_directory,
28
28
  delete_directory,
29
29
  delete_file,
30
+ insert_at_line,
30
31
  list_directory_contents,
31
32
  move_file,
32
33
  read_file_to_string,
34
+ replace_in_file,
33
35
  write_file_from_string,
34
36
  )
35
37
  from .tree import (
@@ -47,6 +49,8 @@ __all__ = [
47
49
  "read_file_to_string",
48
50
  "write_file_from_string",
49
51
  "append_to_file",
52
+ "replace_in_file",
53
+ "insert_at_line",
50
54
  # Directory operations
51
55
  "list_directory_contents",
52
56
  "create_directory",
@@ -233,3 +233,98 @@ def copy_file(source_path: str, destination_path: str) -> bool:
233
233
  return True
234
234
  except OSError as e:
235
235
  raise FileSystemError(f"Failed to copy {src_path} to {dst_path}: {e}")
236
+
237
+
238
+ def replace_in_file(
239
+ file_path: str, old_text: str, new_text: str, count: int = -1
240
+ ) -> bool:
241
+ """Replace occurrences of text within a file without rewriting the entire content.
242
+
243
+ This function performs targeted text replacement, making it safer for agents
244
+ to make small changes without accidentally removing other content.
245
+
246
+ Args:
247
+ file_path: Path to the file to modify
248
+ old_text: Text to search for and replace
249
+ new_text: Text to replace the old text with
250
+ count: Maximum number of replacements to make (-1 for all occurrences)
251
+
252
+ Returns:
253
+ True if successful (even if no replacements were made)
254
+
255
+ Raises:
256
+ FileSystemError: If file doesn't exist, can't be read, or write fails
257
+ ValueError: If old_text is empty
258
+ """
259
+ if not old_text:
260
+ raise ValueError("old_text cannot be empty")
261
+
262
+ validate_file_content(new_text, "replace")
263
+ path = validate_path(file_path, "replace")
264
+
265
+ if not path.is_file():
266
+ raise FileSystemError(f"File not found: {path}")
267
+
268
+ try:
269
+ # Read current content
270
+ content = path.read_text(encoding="utf-8")
271
+
272
+ # Perform replacement
273
+ updated_content = content.replace(old_text, new_text, count)
274
+
275
+ # Write back to file
276
+ path.write_text(updated_content, encoding="utf-8")
277
+ return True
278
+ except (OSError, UnicodeDecodeError) as e:
279
+ raise FileSystemError(f"Failed to replace text in file {path}: {e}")
280
+
281
+
282
+ def insert_at_line(file_path: str, line_number: int, content: str) -> bool:
283
+ """Insert content at a specific line number in a file.
284
+
285
+ This function allows precise insertion of text at a specific line,
286
+ making it safer for agents to add content without overwriting files.
287
+
288
+ Args:
289
+ file_path: Path to the file to modify
290
+ line_number: Line number to insert at (1-based indexing)
291
+ content: Content to insert (will be added as a new line)
292
+
293
+ Returns:
294
+ True if successful
295
+
296
+ Raises:
297
+ FileSystemError: If file doesn't exist, can't be read, or write fails
298
+ ValueError: If line_number is less than 1
299
+ """
300
+ if line_number < 1:
301
+ raise ValueError("line_number must be 1 or greater")
302
+
303
+ validate_file_content(content, "insert")
304
+ path = validate_path(file_path, "insert")
305
+
306
+ if not path.is_file():
307
+ raise FileSystemError(f"File not found: {path}")
308
+
309
+ try:
310
+ # Read current lines
311
+ lines = path.read_text(encoding="utf-8").splitlines(keepends=True)
312
+
313
+ # Ensure content ends with newline if it doesn't already
314
+ if content and not content.endswith("\n"):
315
+ content += "\n"
316
+
317
+ # Insert at specified line (convert to 0-based index)
318
+ insert_index = line_number - 1
319
+
320
+ # If line number is beyond file length, append to end
321
+ if insert_index >= len(lines):
322
+ lines.append(content)
323
+ else:
324
+ lines.insert(insert_index, content)
325
+
326
+ # Write back to file
327
+ path.write_text("".join(lines), encoding="utf-8")
328
+ return True
329
+ except (OSError, UnicodeDecodeError) as e:
330
+ raise FileSystemError(f"Failed to insert content in file {path}: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-open-agent-tools
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: An open foundational toolkit providing essential components for building AI agents with minimal dependencies for local (non-HTTP/API) actions.
5
5
  Home-page: https://github.com/open-agent-tools/basic-open-agent-tools
6
6
  Author: Open Agent Tools
@@ -1,6 +1,5 @@
1
1
  """Tests for data transformation functions."""
2
2
 
3
-
4
3
  import pytest
5
4
 
6
5
  from basic_open_agent_tools.data.transform import (
@@ -72,15 +72,96 @@ class TestFileSystemModule:
72
72
  assert "subdir1" in shallow_tree
73
73
  assert "nested" not in shallow_tree
74
74
 
75
+ def test_replace_in_file(self):
76
+ """Test targeted text replacement in files."""
77
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as f:
78
+ test_file = f.name
79
+
80
+ try:
81
+ # Create test file with content
82
+ content = "Hello world!\nThis is a test.\nHello again!"
83
+ file_system.write_file_from_string(test_file, content)
84
+
85
+ # Test replacement
86
+ result = file_system.replace_in_file(test_file, "Hello", "Hi")
87
+ assert result is True
88
+
89
+ # Verify replacement
90
+ updated_content = file_system.read_file_to_string(test_file)
91
+ assert "Hi world!" in updated_content
92
+ assert "Hi again!" in updated_content
93
+ assert "This is a test." in updated_content
94
+
95
+ # Test limited replacement count
96
+ file_system.write_file_from_string(test_file, content)
97
+ result = file_system.replace_in_file(test_file, "Hello", "Hi", count=1)
98
+ assert result is True
99
+
100
+ updated_content = file_system.read_file_to_string(test_file)
101
+ assert updated_content.count("Hi") == 1
102
+ assert updated_content.count("Hello") == 1
103
+
104
+ finally:
105
+ if os.path.exists(test_file):
106
+ os.unlink(test_file)
107
+
108
+ def test_insert_at_line(self):
109
+ """Test inserting content at specific line numbers."""
110
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as f:
111
+ test_file = f.name
112
+
113
+ try:
114
+ # Create test file with multiple lines
115
+ content = "Line 1\nLine 2\nLine 3"
116
+ file_system.write_file_from_string(test_file, content)
117
+
118
+ # Test inserting at beginning
119
+ result = file_system.insert_at_line(test_file, 1, "New Line 1")
120
+ assert result is True
121
+
122
+ updated_content = file_system.read_file_to_string(test_file)
123
+ lines = updated_content.split("\n")
124
+ assert lines[0] == "New Line 1"
125
+ assert lines[1] == "Line 1"
126
+
127
+ # Test inserting in middle
128
+ file_system.write_file_from_string(test_file, content)
129
+ result = file_system.insert_at_line(test_file, 2, "Inserted Line")
130
+ assert result is True
131
+
132
+ updated_content = file_system.read_file_to_string(test_file)
133
+ lines = updated_content.split("\n")
134
+ assert lines[0] == "Line 1"
135
+ assert lines[1] == "Inserted Line"
136
+ assert lines[2] == "Line 2"
137
+
138
+ # Test inserting beyond file length (should append)
139
+ file_system.write_file_from_string(test_file, content)
140
+ result = file_system.insert_at_line(test_file, 10, "Appended Line")
141
+ assert result is True
142
+
143
+ updated_content = file_system.read_file_to_string(test_file)
144
+ assert "Appended Line" in updated_content
145
+
146
+ finally:
147
+ if os.path.exists(test_file):
148
+ os.unlink(test_file)
149
+
75
150
  def test_submodule_imports(self):
76
151
  """Test that individual submodules can be imported."""
77
152
  from basic_open_agent_tools.file_system.info import file_exists
78
- from basic_open_agent_tools.file_system.operations import read_file_to_string
153
+ from basic_open_agent_tools.file_system.operations import (
154
+ insert_at_line,
155
+ read_file_to_string,
156
+ replace_in_file,
157
+ )
79
158
  from basic_open_agent_tools.file_system.tree import list_all_directory_contents
80
159
  from basic_open_agent_tools.file_system.validation import validate_path
81
160
 
82
161
  # Just test that imports work
83
162
  assert callable(read_file_to_string)
163
+ assert callable(replace_in_file)
164
+ assert callable(insert_at_line)
84
165
  assert callable(file_exists)
85
166
  assert callable(list_all_directory_contents)
86
167
  assert callable(validate_path)