import json import os from pathlib import Path import pytest from sweagent import TOOLS_DIR from tests.utils import make_python_tool_importable DEFAULT_TOOLS_DIR = TOOLS_DIR / "windowed" DEFAULT_TOOLS_BIN = DEFAULT_TOOLS_DIR / "bin" make_python_tool_importable(DEFAULT_TOOLS_DIR / "lib/windowed_file.py", "windowed_file") import windowed_file # type: ignore from windowed_file import TextNotFound, WindowedFile # type: ignore def test_env_file_override(with_tmp_env_file): assert Path(os.getenv("SWE_AGENT_ENV_FILE")).name == ".swe-agent-env" # type: ignore def create_test_file_with_content(tmp_env_file: Path, content: str) -> WindowedFile: test_path = tmp_env_file.parent.joinpath("test.py") registry = { "CURRENT_FILE": str(test_path), "FIRST_LINE": "0", "WINDOW": "10", } tmp_env_file.write_text(json.dumps(registry)) test_path.write_text(content) wf = WindowedFile(exit_on_exception=False) wf.offset_multiplier = 1 / 4 return wf @pytest.fixture def windowed_file(with_tmp_env_file) -> WindowedFile: content = "\n".join(map(str, range(100))) return create_test_file_with_content(with_tmp_env_file, content) def test_windowed_file(windowed_file): wfile = windowed_file assert wfile.first_line == 0 wfile.first_line = 10 assert wfile.first_line == 10 assert wfile.window == 10 assert wfile.n_lines == 100 a, b = wfile.line_range assert b - a == wfile.window - 1 assert wfile.line_range == (10, 19) wfile.print_window() wfile.replace_in_window("10", "Hello, world!") assert wfile.n_lines == 100 assert wfile.line_range == (7, 16) wfile.first_line = 50 wfile.print_window() wfile.replace_in_window("50", "Hello, world!") wfile.print_window() # Line 50 is now the 2nd line of the new window assert wfile.line_range == (47, 56) with pytest.raises(TextNotFound): wfile.replace_in_window("asdf", "Hello, world!") def test_windowed_file_goto(windowed_file): wfile = windowed_file assert wfile.first_line == 0 wfile.first_line = 10 wfile.goto(0, mode="top") assert wfile.line_range[0] == 0 wfile.goto(50, mode="top") # first line is 50 - 10//4 = 47 assert wfile.line_range[0] == 47 wfile.goto(100, mode="top") assert wfile.line_range[1] == 99 def test_windowed_file_scroll(windowed_file): wfile = windowed_file assert wfile.first_line == 0 wfile.first_line = 10 wfile.scroll(10) assert wfile.first_line == 20 wfile.scroll(-10) assert wfile.first_line == 10 wfile.scroll(-100) # Can't go lower than the middle of the lowest window assert wfile.first_line == 0 wfile.scroll(100) assert wfile.line_range[1] == 99 # def test_goto_command(windowed_file): # wfile = windowed_file # assert wfile.current_line == 10 # assert (DEFAULT_TOOLS_BIN / "goto").exists() # # Use sys.executable to get the correct Python interpreter # import sys # cmd = f"{sys.executable} {DEFAULT_TOOLS_BIN}/goto 50" # print( # subprocess.check_output( # cmd, # shell=True, # universal_newlines=True, # stderr=subprocess.STDOUT, # env=os.environ.copy(), # Ensure we pass the current environment # ) # ) # assert wfile.current_line == 50 _DEFAULT_WINDOW_OUTPUT = """[File: {path} (100 lines total)] (10 more lines above) 11:10 12:11 13:12 14:13 15:14 16:15 17:16 18:17 19:18 20:19 (80 more lines below) """ def test_print_window(windowed_file, capsys): wfile = windowed_file wfile.first_line = 10 wfile.print_window() captured = capsys.readouterr() print(captured.out) expected = _DEFAULT_WINDOW_OUTPUT.format(path=wfile.path.resolve()) assert captured.out == expected _DEFAULT_WINDOW_OUTPUT_NEW_FILE = """[File: {path} (1 lines total)] 1: """ def test_print_window_new_file(with_tmp_env_file, capsys): wfile = create_test_file_with_content(with_tmp_env_file, "\n") assert wfile.n_lines == 1 assert wfile.line_range == (0, 0) wfile.print_window() captured = capsys.readouterr() print(captured.out) expected = _DEFAULT_WINDOW_OUTPUT_NEW_FILE.format(path=wfile.path.resolve()) assert captured.out == expected