mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-09 14:57:59 -05:00
Validate to_replace in edit_file_by_replace AgentSkill (#3073)
* Validate to_replace in edit_file_by_replace AgentSkill * Remove redundant replace reminder prompt * Add unit tests * Fix prompt
This commit is contained in:
@@ -605,7 +605,6 @@ def edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> N
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
@@ -650,12 +649,20 @@ def edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> N
|
||||
if to_replace.strip() == '':
|
||||
raise ValueError('`to_replace` must not be empty.')
|
||||
|
||||
if to_replace == new_content:
|
||||
raise ValueError('`to_replace` and `new_content` must be different.')
|
||||
|
||||
# search for `to_replace` in the file
|
||||
# if found, replace it with `new_content`
|
||||
# if not found, perform a fuzzy search to find the closest match and replace it with `new_content`
|
||||
with open(file_name, 'r') as file:
|
||||
file_content = file.read()
|
||||
|
||||
if file_content.count(to_replace) > 1:
|
||||
raise ValueError(
|
||||
'`to_replace` appears more than once, please include enough lines to make code in `to_replace` unique.'
|
||||
)
|
||||
|
||||
start = file_content.find(to_replace)
|
||||
if start != -1:
|
||||
# Convert start from index to line number
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -58,7 +58,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
@@ -602,13 +601,13 @@ open_file("bad.txt")
|
||||
----------
|
||||
|
||||
OBSERVATION:
|
||||
[File: /workspace/bad.txt (4 lines total)]
|
||||
(this is the beginning of the file)
|
||||
1|This is a stupid typoo.
|
||||
2|Really?
|
||||
3|No mor typos!
|
||||
4|Enjoy!
|
||||
(this is the end of the file)
|
||||
[File: /workspace/bad.txt (4 lines total)]
|
||||
(this is the beginning of the file)
|
||||
1|This is a stupid typoo.
|
||||
2|Really?
|
||||
3|No mor typos!
|
||||
4|Enjoy!
|
||||
(this is the end of the file)
|
||||
|
||||
|
||||
----------
|
||||
@@ -630,12 +629,12 @@ edit_file_by_replace(
|
||||
----------
|
||||
|
||||
OBSERVATION:
|
||||
[No exact match found in bad.txt for
|
||||
```
|
||||
This is a stupid typoo.
|
||||
No mor typos!
|
||||
```
|
||||
]
|
||||
[No exact match found in bad.txt for
|
||||
```
|
||||
This is a stupid typoo.
|
||||
No mor typos!
|
||||
```
|
||||
]
|
||||
|
||||
|
||||
----------
|
||||
@@ -657,14 +656,14 @@ edit_file_by_replace(
|
||||
----------
|
||||
|
||||
OBSERVATION:
|
||||
[File: /workspace/bad.txt (4 lines total after edit)]
|
||||
(this is the beginning of the file)
|
||||
1|This is a stupid typo.
|
||||
2|Really?
|
||||
3|No mor typos!
|
||||
4|Enjoy!
|
||||
(this is the end of the file)
|
||||
[File updated (edited at line 1). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
|
||||
[File: /workspace/bad.txt (4 lines total after edit)]
|
||||
(this is the beginning of the file)
|
||||
1|This is a stupid typo.
|
||||
2|Really?
|
||||
3|No mor typos!
|
||||
4|Enjoy!
|
||||
(this is the end of the file)
|
||||
[File updated (edited at line 1). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
|
||||
|
||||
|
||||
----------
|
||||
@@ -681,14 +680,14 @@ edit_file_by_replace(
|
||||
----------
|
||||
|
||||
OBSERVATION:
|
||||
[File: /workspace/bad.txt (4 lines total after edit)]
|
||||
(this is the beginning of the file)
|
||||
1|This is a stupid typo.
|
||||
2|Really?
|
||||
3|No more typos!
|
||||
4|Enjoy!
|
||||
(this is the end of the file)
|
||||
[File updated (edited at line 3). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
|
||||
[File: /workspace/bad.txt (4 lines total after edit)]
|
||||
(this is the beginning of the file)
|
||||
1|This is a stupid typo.
|
||||
2|Really?
|
||||
3|No more typos!
|
||||
4|Enjoy!
|
||||
(this is the end of the file)
|
||||
[File updated (edited at line 3). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
|
||||
|
||||
|
||||
ENVIRONMENT REMINDER: You have 10 turns left to complete the task.
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -46,7 +46,6 @@ edit_file_by_replace(file_name: str, to_replace: str, new_content: str) -> None:
|
||||
Edit a file. This will search for `to_replace` in the given file and replace it with `new_content`.
|
||||
Every *to_replace* must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
|
||||
Include enough lines to make code in `to_replace` unique. `to_replace` should NOT be empty.
|
||||
`edit_file_by_replace` will only replace the *first* matching occurrences.
|
||||
For example, given a file "/workspace/example.txt" with the following content:
|
||||
```
|
||||
line 1
|
||||
|
||||
@@ -693,41 +693,58 @@ def test_edit_file_by_replace_multiline(tmp_path):
|
||||
|
||||
with io.StringIO() as buf:
|
||||
with contextlib.redirect_stdout(buf):
|
||||
edit_file_by_replace(
|
||||
file_name=str(temp_file_path),
|
||||
to_replace='Line 2',
|
||||
new_content='REPLACE TEXT',
|
||||
)
|
||||
result = buf.getvalue()
|
||||
expected = (
|
||||
f'[File: {temp_file_path} (5 lines total after edit)]\n'
|
||||
'(this is the beginning of the file)\n'
|
||||
'1|Line 1\n'
|
||||
'2|REPLACE TEXT\n'
|
||||
'3|Line 2\n'
|
||||
'4|Line 4\n'
|
||||
'5|Line 5\n'
|
||||
'(this is the end of the file)\n'
|
||||
+ MSG_FILE_UPDATED.format(line_number=2)
|
||||
+ '\n'
|
||||
)
|
||||
assert result.split('\n') == expected.split('\n')
|
||||
|
||||
with open(temp_file_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
assert len(lines) == 5
|
||||
assert lines[0].rstrip() == 'Line 1'
|
||||
assert lines[1].rstrip() == 'REPLACE TEXT'
|
||||
assert lines[2].rstrip() == 'Line 2'
|
||||
assert lines[3].rstrip() == 'Line 4'
|
||||
assert lines[4].rstrip() == 'Line 5'
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match='`to_replace` appears more than once, please include enough lines to make code in `to_replace` unique',
|
||||
):
|
||||
edit_file_by_replace(
|
||||
file_name=str(temp_file_path),
|
||||
to_replace='Line 2',
|
||||
new_content='REPLACE TEXT',
|
||||
)
|
||||
|
||||
|
||||
def test_edit_file_by_replace_toreplace_empty():
|
||||
with pytest.raises(ValueError):
|
||||
def test_edit_file_by_replace_no_diff(tmp_path):
|
||||
temp_file_path = tmp_path / 'a.txt'
|
||||
content = 'Line 1\nLine 2\nLine 2\nLine 4\nLine 5'
|
||||
temp_file_path.write_text(content)
|
||||
|
||||
open_file(str(temp_file_path))
|
||||
|
||||
with io.StringIO() as buf:
|
||||
with contextlib.redirect_stdout(buf):
|
||||
with pytest.raises(
|
||||
ValueError, match='`to_replace` and `new_content` must be different'
|
||||
):
|
||||
edit_file_by_replace(
|
||||
file_name=str(temp_file_path),
|
||||
to_replace='Line 1',
|
||||
new_content='Line 1',
|
||||
)
|
||||
|
||||
|
||||
def test_edit_file_by_replace_toreplace_empty(tmp_path):
|
||||
temp_file_path = tmp_path / 'a.txt'
|
||||
content = 'Line 1\nLine 2\nLine 2\nLine 4\nLine 5'
|
||||
temp_file_path.write_text(content)
|
||||
|
||||
open_file(str(temp_file_path))
|
||||
|
||||
with io.StringIO() as buf:
|
||||
with contextlib.redirect_stdout(buf):
|
||||
with pytest.raises(ValueError, match='`to_replace` must not be empty.'):
|
||||
edit_file_by_replace(
|
||||
file_name=str(temp_file_path),
|
||||
to_replace=' ',
|
||||
new_content='Line 1',
|
||||
)
|
||||
|
||||
|
||||
def test_edit_file_by_replace_unknown_file():
|
||||
with pytest.raises(FileNotFoundError):
|
||||
edit_file_by_replace(
|
||||
str('unknown file'),
|
||||
'',
|
||||
'ORIGINAL TEXT',
|
||||
'REPLACE TEXT',
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user