|
import os |
|
|
|
from typing import Dict, Tuple |
|
|
|
import pytest |
|
|
|
from gpt_engineer.core.chat_to_files import parse_diffs |
|
from gpt_engineer.core.diff import is_similar |
|
from gpt_engineer.core.files_dict import file_to_lines_dict |
|
|
|
THIS_FILE_DIR = os.path.dirname(os.path.abspath(__file__)) |
|
|
|
example_diff = """ |
|
Irrelevant line to be ignored |
|
|
|
another irrelevant line to be ignored |
|
```diff |
|
--- example.txt |
|
+++ example.txt |
|
@@ -12,3 +12,4 @@ |
|
sample text 1 |
|
sample text 2 |
|
+ added extra line here |
|
- original text A |
|
+ updated original text A with changes |
|
@@ -35,4 +36,5 @@ |
|
checking status: |
|
- perform operation X |
|
+ perform operation X only if specific condition holds |
|
+ new operation related to condition |
|
evaluating next step: |
|
- execute step Y |
|
+ revised execution of step Y |
|
``` |
|
""" |
|
|
|
example_multiple_diffs = """ |
|
I apologize for the oversight. Let's correct the `calculator.py` file with the proper git diff format, ensuring that the context lines match the original code exactly. |
|
|
|
```diff |
|
--- calculator.py |
|
+++ calculator.py |
|
@@ -1,3 +1,3 @@ |
|
class Calculator: |
|
- def add(self, a, b): |
|
- return a - b # Logical |
|
+ def add(self, a, b): # Adds two numbers |
|
+ return a + b |
|
``` |
|
|
|
Now, let's create the `main.py` file with the correct git diff format: |
|
|
|
```diff |
|
--- /dev/null |
|
+++ main.py |
|
@@ -0,0 +1,7 @@ |
|
+from calculator import Calculator |
|
+ |
|
+# Function to demonstrate the usage of the Calculator class |
|
+def main(): |
|
+ calc = Calculator() |
|
+if __name__ == "__main__": |
|
+ main() |
|
``` |
|
|
|
These changes should now correctly apply to the provided code and create a simple calculator program with a command-line interface. |
|
|
|
|
|
""" |
|
|
|
example_line_dist_diff = """ |
|
Irrelevant line to be ignored |
|
|
|
another irrelevant line to be ignored |
|
```diff |
|
--- example.txt |
|
+++ example.txt |
|
@@ -10,4 +13,5 @@ |
|
sample text 1 |
|
sample text 2 |
|
+ added extra line here |
|
- original text A |
|
+ updated original text A with changes |
|
@@ -33,14 +363,5 @@ |
|
checking status: |
|
- perform operation X |
|
+ perform operation X only if specific condition holds |
|
+ new operation related to condition |
|
evaluating next step: |
|
- execute step Y |
|
+ revised execution of step Y |
|
``` |
|
""" |
|
|
|
add_example = """ |
|
Uninteresting stuff |
|
```diff |
|
--- /dev/null |
|
+++ new_file.txt |
|
@@ -0,0 +1,3 @@ |
|
+First example line |
|
+ |
|
+Last example line |
|
``` |
|
""" |
|
|
|
file_example = """# Introduction |
|
|
|
@Analysis |
|
Overview: outcomes |
|
% |
|
Background: *context* |
|
|
|
Method: [] |
|
! |
|
Theories: ? |
|
> Leading up... |
|
sample text 1 |
|
sample text 2 |
|
original text A |
|
a |
|
Challenges: ~ |
|
|
|
Perspectives: <> |
|
|
|
Strategy: {#} |
|
+ |
|
Outcomes: ^^^ |
|
|
|
Future: ||| |
|
|
|
x |
|
|
|
Y |
|
|
|
Z |
|
|
|
|
|
|
|
code |
|
checking status: |
|
perform operation X |
|
evaluating next step: |
|
execute step Y |
|
End. |
|
|
|
Conclusion: *** |
|
""" |
|
|
|
|
|
|
|
def test_basic_similarity(): |
|
assert is_similar("abc", "cab") |
|
assert not is_similar("abc", "def") |
|
|
|
|
|
def test_case_insensitivity_and_whitespace(): |
|
assert is_similar("A b C", "c a b") |
|
assert not is_similar("Abc", "D e F") |
|
|
|
|
|
def test_length_and_character_frequency(): |
|
assert is_similar("aabbc", "bacba") |
|
assert not is_similar("aabbcc", "abbcc") |
|
|
|
|
|
def test_edge_cases(): |
|
assert not is_similar("", "a") |
|
assert is_similar("a", "a") |
|
|
|
|
|
def insert_string_in_lined_string(string, to_insert, line_number): |
|
split_string = string.split("\n") |
|
split_string.insert(line_number - 1, to_insert) |
|
return "\n".join(split_string) |
|
|
|
|
|
def test_diff_changing_one_file(): |
|
diffs = parse_diffs(example_diff) |
|
for filename, diff in diffs.items(): |
|
string_diff = diff.diff_to_string() |
|
correct_diff = "\n".join(example_diff.strip().split("\n")[4:-1]) |
|
assert string_diff == correct_diff |
|
|
|
|
|
def test_diff_adding_one_file(): |
|
add_diff = parse_diffs(add_example) |
|
for filename, diff in add_diff.items(): |
|
string_add_diff = diff.diff_to_string() |
|
correct_add_diff = "\n".join(add_example.strip().split("\n")[2:-1]) |
|
assert string_add_diff == correct_add_diff |
|
|
|
|
|
def test_diff_changing_two_files(): |
|
merged_diff = parse_diffs(example_diff + add_example) |
|
correct_diff = "\n".join(example_diff.strip().split("\n")[4:-1]) |
|
correct_add_diff = "\n".join(add_example.strip().split("\n")[2:-1]) |
|
assert merged_diff["example.txt"].diff_to_string() == correct_diff |
|
assert merged_diff["new_file.txt"].diff_to_string() == correct_add_diff |
|
|
|
|
|
def test_validate_diff_correct(): |
|
lines_dict = file_to_lines_dict(file_example) |
|
diffs = parse_diffs(example_diff) |
|
|
|
list(diffs.values())[0].validate_and_correct(lines_dict) |
|
|
|
|
|
def test_correct_distorted_numbers(): |
|
lines_dict = file_to_lines_dict(file_example) |
|
diffs = parse_diffs(example_line_dist_diff) |
|
|
|
list(diffs.values())[0].validate_and_correct(lines_dict) |
|
correct_diff = "\n".join(example_diff.strip().split("\n")[4:-1]) |
|
assert diffs["example.txt"].diff_to_string() == correct_diff |
|
|
|
|
|
def test_correct_skipped_lines(): |
|
distorted_example = insert_string_in_lined_string( |
|
file_example, "#\n#comment\n#\n#", 14 |
|
) |
|
diffs = parse_diffs(example_diff) |
|
list(diffs.values())[0].validate_and_correct(file_to_lines_dict(distorted_example)) |
|
with open( |
|
os.path.join( |
|
THIS_FILE_DIR, |
|
"improve_function_test_cases", |
|
"corrected_diff_from_missing_lines", |
|
), |
|
"r", |
|
) as f: |
|
corrected_diff_from_missing_lines = f.read() |
|
assert ( |
|
diffs["example.txt"].diff_to_string().strip() |
|
== corrected_diff_from_missing_lines.strip() |
|
) |
|
|
|
|
|
def test_correct_skipped_lines_and_number_correction(): |
|
distorted_example = insert_string_in_lined_string( |
|
file_example, "#\n#comment\n#\n#", 14 |
|
) |
|
diffs = parse_diffs(example_line_dist_diff) |
|
|
|
for diff in diffs.values(): |
|
problems = diff.validate_and_correct(file_to_lines_dict(distorted_example)) |
|
print(problems) |
|
with open( |
|
os.path.join( |
|
THIS_FILE_DIR, |
|
"improve_function_test_cases", |
|
"corrected_diff_from_missing_lines", |
|
), |
|
"r", |
|
) as f: |
|
corrected_diff_from_missing_lines = f.read() |
|
assert ( |
|
diffs["example.txt"].diff_to_string().strip() |
|
== corrected_diff_from_missing_lines.strip() |
|
) |
|
|
|
|
|
def test_diff_regex(): |
|
diff = parse_diffs(example_diff) |
|
assert len(diff) == 1 |
|
|
|
diffs = parse_diffs(example_multiple_diffs) |
|
assert len(diffs) == 2 |
|
|
|
|
|
def parse_chats_with_regex( |
|
diff_file_name: str, code_file_name: str |
|
) -> Tuple[str, str, Dict]: |
|
|
|
with open( |
|
os.path.join(THIS_FILE_DIR, "improve_function_test_cases", diff_file_name), "r" |
|
) as f: |
|
diff_content = f.read() |
|
|
|
|
|
with open( |
|
os.path.join(THIS_FILE_DIR, "improve_function_test_cases", code_file_name), "r" |
|
) as f: |
|
code_content = f.read() |
|
|
|
|
|
diffs = parse_diffs(diff_content) |
|
|
|
return diff_content, code_content, diffs |
|
|
|
|
|
|
|
def test_controller_diff(): |
|
parse_chats_with_regex("controller_chat", "controller_code") |
|
|
|
|
|
def test_simple_calculator_diff(): |
|
parse_chats_with_regex("simple_calculator_chat", "simple_calculator_code") |
|
|
|
|
|
def test_complex_temperature_converter_diff(): |
|
parse_chats_with_regex("temperature_converter_chat", "temperature_converter_code") |
|
|
|
|
|
def test_complex_task_master_diff(): |
|
parse_chats_with_regex("task_master_chat", "task_master_code") |
|
|
|
|
|
def test_long_file_diff(): |
|
parse_chats_with_regex("wheaties_example_chat", "wheaties_example_code") |
|
|
|
|
|
if __name__ == "__main__": |
|
pytest.main() |
|
|