aider/tests/test_commands.py
Paul Gauthier 8be2f8086c aider: Add a test case to reproduce the issue of trying to add a directory using the /add command.
# Aider chat conversation:

USER: add a test case to reproduce this issue: Trying to add just a directory makes the program throw the following and exit:

> /add src/components

Traceback (most recent call last):
  File "/home/palmerd/.local/bin/aider", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/main.py", line 369, in main
    coder.run()
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/coders/base_coder.py", line 382, in run
    new_user_message = self.run_loop()
                       ^^^^^^^^^^^^^^^
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/coders/base_coder.py", line 446, in run_loop
    return self.commands.run(inp)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/commands.py", line 60, in run
    return self.do_run(matching_commands[0][1:], rest_inp)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/commands.py", line 45, in do_run
    return cmd_method(args)
           ^^^^^^^^^^^^^^^^
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/commands.py", line 264, in cmd_add
    content = self.io.read_text(abs_file_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/palmerd/.local/lib/python3.11/site-packages/aider/io.py", line 142, in read_text
    with open(str(filename), "r", encoding=self.encoding) as f:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IsADirectoryError: [Errno 21] Is a directory: '/home/palmerd/vue-frontend/src/components'

ASSISTANT: To reproduce this issue, we need to create a test case that tries to add a directory using the `/add` command. However, the code you've provided is not designed to handle test cases.

Could you please provide the test suite or the file where the test cases are written so that I can add a new test case?

USER: I added these *read-write* files: tests/test_commands.py

ASSISTANT: Great, we can add a test case in the `tests/test_commands.py` file. This test case will attempt to add a directory and check if the appropriate error is handled.

Here is the proposed change:

```python
tests/test_commands.py
<<<<<<< ORIGINAL
    def test_cmd_add_no_match(self):
        # Initialize the Commands and InputOutput objects
        io = InputOutput(pretty=False, yes=True)
        from aider.coders import Coder

        coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
        commands = Commands(io, coder)

        # Call the cmd_add method with a non-existent file pattern
        commands.cmd_add("*.nonexistent")

        # Check if no files have been added to the chat session
        self.assertEqual(len(coder.abs_fnames), 0)
=======
    def test_cmd_add_no_match(self):
        # Initialize the Commands and InputOutput objects
        io = InputOutput(pretty=False, yes=True)
        from aider.coders import Coder

        coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
        commands = Commands(io, coder)

        # Call the cmd_add method with a non-existent file pattern
        commands.cmd_add("*.nonexistent")

        # Check if no files have been added to the chat session
        self.assertEqual(len(coder.abs_fnames), 0)

    def test_cmd_add_directory(self):
        # Initialize the Commands and InputOutput objects
        io = InputOutput(pretty=False, yes=True)
        from aider.coders import Coder

        coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
        commands = Commands(io, coder)

        # Create a directory
        os.mkdir("test_dir")

        # Call the cmd_add method with a directory
        with self.assertRaises(IsADirectoryError):
            commands.cmd_add("test_dir")
>>>>>>> UPDATED
```

This new test case `test_cmd_add_directory` creates a directory named `test_dir` and attempts to add it using the `cmd_add` method. We expect an `IsADirectoryError` to be raised in this scenario.
2023-07-10 13:17:55 -07:00

162 lines
5.3 KiB
Python

import codecs
import os
import shutil
import sys
import tempfile
from io import StringIO
from pathlib import Path
from unittest import TestCase
from aider import models
from aider.coders import Coder
from aider.commands import Commands
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
class TestCommands(TestCase):
def setUp(self):
self.original_cwd = os.getcwd()
self.tempdir = tempfile.mkdtemp()
os.chdir(self.tempdir)
def tearDown(self):
os.chdir(self.original_cwd)
shutil.rmtree(self.tempdir)
def test_cmd_add(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
from aider.coders import Coder
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
# Call the cmd_add method with 'foo.txt' and 'bar.txt' as a single string
commands.cmd_add("foo.txt bar.txt")
# Check if both files have been created in the temporary directory
self.assertTrue(os.path.exists("foo.txt"))
self.assertTrue(os.path.exists("bar.txt"))
def test_cmd_add_with_glob_patterns(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
from aider.coders import Coder
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
# Create some test files
with open("test1.py", "w") as f:
f.write("print('test1')")
with open("test2.py", "w") as f:
f.write("print('test2')")
with open("test.txt", "w") as f:
f.write("test")
# Call the cmd_add method with a glob pattern
commands.cmd_add("*.py")
# Check if the Python files have been added to the chat session
self.assertIn(str(Path("test1.py").resolve()), coder.abs_fnames)
self.assertIn(str(Path("test2.py").resolve()), coder.abs_fnames)
# Check if the text file has not been added to the chat session
self.assertNotIn(str(Path("test.txt").resolve()), coder.abs_fnames)
def test_cmd_add_no_match(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
from aider.coders import Coder
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
# Call the cmd_add method with a non-existent file pattern
commands.cmd_add("*.nonexistent")
# Check if no files have been added to the chat session
self.assertEqual(len(coder.abs_fnames), 0)
def test_cmd_add_directory(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
from aider.coders import Coder
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
# Create a directory
os.mkdir("test_dir")
# Call the cmd_add method with a directory
with self.assertRaises(IsADirectoryError):
commands.cmd_add("test_dir")
def test_cmd_drop_with_glob_patterns(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
from aider.coders import Coder
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
subdir = Path("subdir")
subdir.mkdir()
(subdir / "subtest1.py").touch()
(subdir / "subtest2.py").touch()
Path("test1.py").touch()
Path("test2.py").touch()
# Add some files to the chat session
commands.cmd_add("*.py")
self.assertEqual(len(coder.abs_fnames), 2)
# Call the cmd_drop method with a glob pattern
commands.cmd_drop("*2.py")
self.assertIn(str(Path("test1.py").resolve()), coder.abs_fnames)
self.assertNotIn(str(Path("test2.py").resolve()), coder.abs_fnames)
def test_cmd_add_bad_encoding(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
from aider.coders import Coder
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
# Create a new file foo.bad which will fail to decode as utf-8
with codecs.open("foo.bad", "w", encoding="iso-8859-15") as f:
f.write("ÆØÅ") # Characters not present in utf-8
commands.cmd_add("foo.bad")
self.assertEqual(coder.abs_fnames, set())
def test_cmd_tokens(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
commands = Commands(io, coder)
commands.cmd_add("foo.txt bar.txt")
# Redirect the standard output to an instance of io.StringIO
stdout = StringIO()
sys.stdout = stdout
commands.cmd_tokens("")
# Reset the standard output
sys.stdout = sys.__stdout__
# Get the console output
console_output = stdout.getvalue()
self.assertIn("foo.txt", console_output)
self.assertIn("bar.txt", console_output)