Commit graph

1354 commits

Author SHA1 Message Date
Paul Gauthier
e43a48ee10 patch check_model_availability in tests 2023-06-01 08:58:35 -07:00
Paul Gauthier
2cc87a4afe aider: Added patch to setUp method and stored mock object as an instance variable.
# Context:
USER: how can i move the patch to setUp so that it is active for all tests?
ASSISTANT: To move the patch to the `setUp` method and make it active for all tests, you can use the `patch` as a context manager in the `setUp` method and store the mock object as an instance variable. Then, in the `tearDown` method, you can stop the patch. Here's how to do it:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        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 setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)
        self.patcher = patch("aider.main.Coder.check_model_availability")
        self.mock_check = self.patcher.start()
        self.mock_check.return_value = True

    def tearDown(self):
        os.chdir(self.original_cwd)
        shutil.rmtree(self.tempdir)
        self.patcher.stop()
>>>>>>> UPDATED
```

Now the patch is active for all tests, and you can remove the `with` statement from the `test_main_with_empty_dir_no_files_on_command` method:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def test_main_with_empty_dir_no_files_on_command(self):
        with patch("aider.main.Coder.check_model_availability") as mock_check:
            mock_check.return_value = True

            pipe_input = create_input(StringIO(""))
            main([], input=pipe_input, output=DummyOutput())
            pipe_input.close()
=======
    def test_main_with_empty_dir_no_files_on_command(self):
        pipe_input = create_input(StringIO(""))
        main([], input=pipe_input, output=DummyOutput())
        pipe_input.close()
>>>>>>> UPDATED
```
2023-06-01 08:54:15 -07:00
Paul Gauthier
a5414473d9 wip 2023-06-01 08:52:21 -07:00
Paul Gauthier
99693fe614 aider: Modified setUp method to patch check_model_availability with MagicMock object that always returns True.
# Context:
USER: the patch in `setUp` is not correcting forcing a return of true
ASSISTANT: To ensure that the patch in `setUp` correctly forces a return of `True`, you need to modify the `setUp` method in the `TestMain` class in the `tests/test_main.py` file. Here's the change:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

        with patch("aider.main.Coder.check_model_availability") as self.mock_check:
            self.mock_check.return_value = True
        super().setUp()
=======
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

        self.mock_check = MagicMock(return_value=True)
        with patch("aider.main.Coder.check_model_availability", new=self.mock_check):
            super().setUp()
>>>>>>> UPDATED
```

This change ensures that the `check_model_availability` method is patched with a `MagicMock` object that always returns `True`.
2023-06-01 08:50:55 -07:00
Paul Gauthier
4774f0518c wip 2023-06-01 08:49:55 -07:00
Paul Gauthier
2b07a334cc aider: Set return value of check_model_availability to True during test setup.
# Context:
USER: the patch in `setUp` is not correcting forcing a return of true
ASSISTANT: To fix the patch in `setUp`, you need to start the patch and set the return value to `True`. Here's the change you need to make in the `tests/test_main.py` file:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    self.mock_check = patch("aider.main.Coder.check_model_availability")
    self.mock_check.return_value = True
=======
    with patch("aider.main.Coder.check_model_availability") as self.mock_check:
        self.mock_check.return_value = True
        super().setUp()
>>>>>>> UPDATED
```

This change will ensure that the `check_model_availability` method returns `True` during the test setup.
2023-06-01 08:49:39 -07:00
Paul Gauthier
c97a0ce30a wip 2023-06-01 08:48:55 -07:00
Paul Gauthier
f4bc22e4fc wip 2023-06-01 08:46:42 -07:00
Paul Gauthier
1b49ba6e91 aider: Fixed the setUp method in the TestMain class to correctly mock the check_for_model_availability method.
# Context:
USER: E           AttributeError: <class 'aider.coder.Coder'> does not have the attribute 'check_for_model_availability'
ASSISTANT: It seems like you are trying to access the `check_for_model_availability` method of the `Coder` class, but it is not defined as an instance method. To fix this issue, you need to move the `check_model_availability` method inside the `Coder` class and update the tests accordingly.

Here are the changes you need to make:

1. Move the `
^C KeyboardInterrupt
USER: fix the `setUp`
ASSISTANT: To fix the `setUp` method in the `TestMain` class, you need to update the way you are mocking the `check_for_model_availability` method. Here are the changes you need to make:

1. Modify the `setUp` method in the `TestMain` class to correctly mock the `check_for_model_availability` method of the `Coder` class.

```python
tests/test_main.py
<<<<<<< ORIGINAL
    with patch("aider.coder.Coder.check_for_model_availability") as mock_check:
        mock_check.return_value = True
        self.mock_check = mock_check
=======
    with patch("aider.coder.Coder.check_model_availability") as mock_check:
        mock_check.return_value = True
        self.mock_check = mock_check
>>>>>>> UPDATED
```

This change will ensure that the `check_for_model_availability` method is correctly mocked during the tests.
2023-06-01 08:45:02 -07:00
Paul Gauthier
fd70d9d63b aider: Patched check_for_model_availability to always return True during setUp method execution.
# Context:
USER: in setup, patch coder.check_for_model_availability to return true
ASSISTANT: To patch the `check_for_model_availability` method in the `setUp` method of the `TestMain` class, you can use the `unittest.mock.patch` context manager. Here's the change you need to make in the `tests/test_main.py` file:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)
=======
    from unittest.mock import MagicMock

    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

        with patch("aider.coder.Coder.check_for_model_availability") as mock_check:
            mock_check.return_value = True
            self.mock_check = mock_check
>>>>>>> UPDATED
```

This will patch the `check_for_model_availability` method to always return `True` during the `setUp` method execution.
2023-06-01 08:42:18 -07:00
Paul Gauthier
1f2aa1a6c8 Auto fallback to 3.5 2023-06-01 08:39:27 -07:00
Paul Gauthier
1b046e8111 aider: Added a new method to check the availability of OpenAI models and called it in the __init__ method to ensure the main_model is available in the list of OpenAI models.
# Context:
USER: in init, call check the list of available openai models and make sure the `main_model` is in there. if not, print an err msg
ASSISTANT:
^C KeyboardInterrupt
USER: in init, call check the list of available openai models and make sure the `main_model` is in there. if not, print an err msg
ASSISTANT: To check the list of available OpenAI models and make sure the `main_model` is in there, you need to modify the `__init__` method in the `Coder` class. Here's how you can do it:

1. Add a new method `check_model_availability` to the `Coder` class that takes the `main_model` as an argument and checks if it's available in the list of OpenAI models.
2. Call this method in the `__init__` method of the `Coder` class.

Here are the changes you need to make:

```python
aider/coder.py
<<<<<<< ORIGINAL
class Coder:
    abs_fnames = None
    repo = None
    last_aider_commit_hash = None
    last_asked_for_commit_time = 0

    def __init__(
=======
class Coder:
    abs_fnames = None
    repo = None
    last_aider_commit_hash = None
    last_asked_for_commit_time = 0

    def check_model_availability(self, main_model):
        available_models = openai.Model.list()
        model_ids = [model.id for model in available_models['data']]
        if main_model not in model_ids:
            raise ValueError(f"Model {main_model} is not available. Please choose from the available models: {model_ids}")

    def __init__(
>>>>>>> UPDATED
```

```python
aider/coder.py
<<<<<<< ORIGINAL
        self.main_model = main_model
        if main_model == "gpt-3.5-turbo":
            self.io.tool_error(
                f"aider doesn't work well with {main_model}, use gpt-4 for best results."
            )

        self.set_repo(fnames)
=======
        self.check_model_availability(main_model)
        self.main_model = main_model
        if main_model == "gpt-3.5-turbo":
            self.io.tool_error(
                f"aider doesn't work well with {main_model}, use gpt-4 for best results."
            )

        self.set_repo(fnames)
>>>>>>> UPDATED
```

These changes will add a new method `check_model_availability` to the `Coder` class and call it in the `__init__` method to ensure the `main_model` is available in the list of OpenAI models. If not, it will raise a `ValueError` with an appropriate error message.
2023-06-01 08:36:48 -07:00
Paul Gauthier
d95d4d931d copy 2023-06-01 06:19:08 -07:00
Paul Gauthier
93dae2c108 copy 2023-06-01 06:16:16 -07:00
Paul Gauthier
354a29f6be copy 2023-06-01 06:14:54 -07:00
Paul Gauthier
3b2c8c81ca copy 2023-05-31 16:29:53 -07:00
Paul Gauthier
3e384dd35b copy 2023-05-31 16:26:51 -07:00
Paul Gauthier
755cabe54f Merge remote-tracking branch 'origin/main' 2023-05-31 15:34:29 -07:00
paul-gauthier
d07d72c2d6
Update README.md 2023-05-31 09:33:59 -07:00
paul-gauthier
1031320836
Merge pull request #9 from jevon/patch-1
Update README.md
2023-05-31 08:25:21 -07:00
Jevon MacDonald
e1df502f34
Update README.md
Disambiguating the format to include OpenAI API token in ~/.aider.config.yml
2023-05-31 11:46:25 -03:00
Paul Gauthier
5d4fd15a21 do isort first 2023-05-30 13:55:28 -07:00
Paul Gauthier
77d20b6819 Fixed TAGS_CACHE 2023-05-30 13:54:56 -07:00
Paul Gauthier
5801bd9ca4 aider: Moved TAGS_CACHE into the RepoMap class.
# Context:
USER: move `TAGS_CACHE` into the class
ASSISTANT: To move the `TAGS_CACHE` into the `RepoMap` class, I will make the following changes:

```python
aider/repomap.py
<<<<<<< ORIGINAL
# Global cache for tags
TAGS_CACHE = {}
=======
>>>>>>> UPDATED
```

```python
aider/repomap.py
<<<<<<< ORIGINAL
class RepoMap:
    ctags_cmd = ["ctags", "--fields=+S", "--extras=-F", "--output-format=json"]

    def __init__(self, use_ctags=None, root=None, main_model="gpt-4"):
=======
    class RepoMap:
        ctags_cmd = ["ctags", "--fields=+S", "--extras=-F", "--output-format=json"]
        TAGS_CACHE = {}

        def __init__(self, use_ctags=None, root=None, main_model="gpt-4"):
>>>>>>> UPDATED
```

Now, the `TAGS_CACHE` is a class attribute of the `RepoMap` class.
2023-05-30 13:53:31 -07:00
Paul Gauthier
ca74eee2f9 Allow GPT to omit the filename from edit blocks, if an earlier block provided it 2023-05-30 11:45:21 -07:00
Paul Gauthier
ef22abd8be copy 2023-05-30 08:01:49 -07:00
Paul Gauthier
9cb793c82d reverted c9ebbdf0 2023-05-30 07:58:54 -07:00
Paul Gauthier
b359134f86 reverted a4e57e17b5 2023-05-30 07:58:31 -07:00
Paul Gauthier
0d568e2b59 screencast.svg 2023-05-30 06:42:05 -07:00
Paul Gauthier
6b4ce832b3 screencast.svg 2023-05-30 06:39:19 -07:00
Paul Gauthier
eb6aba8726 screencast.svg 2023-05-30 06:25:52 -07:00
Paul Gauthier
a4e57e17b5 aider: Added completions_height parameter to InputOutput class and passed it from aider/main.py.
# Context:
USER: pass it to `InputOutput` and store as a self. var
ASSISTANT: I will modify the `InputOutput` class in `aider/io.py` to accept the `completions_height` parameter and store it as an instance variable.

Here's the change to add the `completions_height` parameter to the `InputOutput` class:

```python
aider/io.py

^C KeyboardInterrupt
USER: `aider/io.py`
ASSISTANT: I will modify the `InputOutput` class in `aider/io.py` to accept the `completions_height` parameter and store it as an instance variable.

Here's the change to add the `completions_height` parameter to the `InputOutput` class:

```python
aider/io.py
<<<<<<< ORIGINAL
    def __init__(
        self,
        pretty=True,
        yes=False,
        input_history_file=None,
        chat_history_file=None,
        input=None,
        output=None,
        user_input_color="blue",
        tool_output_color=None,
        tool_error_color="red",
    ):
=======
    def __init__(
        self,
        pretty=True,
        yes=False,
        input_history_file=None,
        chat_history_file=None,
        input=None,
        output=None,
        user_input_color="blue",
        tool_output_color=None,
        tool_error_color="red",
        completions_height=10,
    ):
        self.completions_height = completions_height
>>>>>>> UPDATED
```

Now, you need to pass the `completions_height` value from `aider/main.py` to the `InputOutput` class when creating an instance:

```python
aider/main.py
<<<<<<< ORIGINAL
    io = InputOutput(
        args.pretty,
        args.yes,
        args.input_history_file,
        args.chat_history_file,
        input=input,
        output=output,
        user_input_color=args.user_input_color,
        tool_output_color=args.tool_output_color,
        tool_error_color=args.tool_error_color,
    )
=======
    io = InputOutput(
        args.pretty,
        args.yes,
        args.input_history_file,
        args.chat_history_file,
        input=input,
        output=output,
        user_input_color=args.user_input_color,
        tool_output_color=args.tool_output_color,
        tool_error_color=args.tool_error_color,
        completions_height=args.completions_height,
    )
>>>>>>> UPDATED
```

Now, the `completions_height` value is passed to the `InputOutput` class and stored as an instance variable.
2023-05-29 17:33:39 -07:00
Paul Gauthier
c9ebbdf0c0 aider: Added a --completions-height command line parameter to aider/main.py.
# Context:
USER: add a --completions-height cmd line param to `aider/main.py`
ASSISTANT: I will add a `--completions-height` command line parameter to `aider/main.py`. This parameter will allow users to set the height of the completions displayed in the terminal.

Here's the change to add the `--completions-height` parameter:

```python
aider/main.py
<<<<<<< ORIGINAL
    parser.add_argument(
        "--no-dirty-commits",
        action="store_false",
        dest="dirty_commits",
        help="Disable dirty commit of changes",
    )
=======
    parser.add_argument(
        "--no-dirty-commits",
        action="store_false",
        dest="dirty_commits",
        help="Disable dirty commit of changes",
    )
    parser.add_argument(
        "--completions-height",
        type=int,
        default=10,
        metavar="COMPLETIONS_HEIGHT",
        help="Set the height of the completions displayed in the terminal (default: 10)",
    )
>>>>>>> UPDATED
```

This will add a new command line argument `--completions-height` with a default value of 10. Users can now set the height of the completions displayed in the terminal by providing a value for this argument.
2023-05-29 17:32:02 -07:00
Paul Gauthier
a7ab3d5d78 screencast.svg 2023-05-29 17:08:06 -07:00
Paul Gauthier
e25cf11aff stronger prompt against editing r/o files 2023-05-29 15:02:51 -07:00
Paul Gauthier
728d3f76a8 new gif 2023-05-29 14:55:04 -07:00
Paul Gauthier
765e0886f9 new gif 2023-05-29 12:21:43 -07:00
Paul Gauthier
2ff24a51dd bold italic 2023-05-29 12:13:28 -07:00
Paul Gauthier
fbb14b2823 aider: Changed pygments.literal.string to appear in inverse colors.
# Context:
USER: no. let's make pygments.literal.string be in inverse colors
ASSISTANT: To make `pygments.literal.string` appear in inverse colors, we need to modify the `aider/io.py` file. Update the `style` dictionary in the `get_input` method:

```python
aider/io.py
<<<<<<< ORIGINAL
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": f"underline {self.user_input_color}"})
=======
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": f"reverse {self.user_input_color}"})
>>>>>>> UPDATED
```

This change will apply the inverse color style to ticked words in the `PromptSession`.
2023-05-29 11:49:50 -07:00
Paul Gauthier
8f40f08636 aider: Updated the style dictionary in get_input method to apply underline style and self.user_input_color to ticked words.
# Context:
USER: underlined and self.user_input_color
ASSISTANT: To underline ticked words and apply the `self.user_input_color`, we need to modify the `aider/io.py` file. Update the `style` dictionary in the `get_input` method:

```python
aider/io.py
<<<<<<< ORIGINAL
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": "underline"})
=======
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": f"underline {self.user_input_color}"})
>>>>>>> UPDATED
```

This change will apply the underline style and the `self.user_input_color` to ticked words in the `PromptSession`.
2023-05-29 11:48:22 -07:00
Paul Gauthier
507442da3f aider: Added underline style to ticked words in PromptSession.
# Context:
USER: can we override the style for `ticked` words to just underline them, not change the color?
ASSISTANT: Yes, we can override the style for ticked words to underline them without changing the color. We need to modify the `aider/io.py` file. Update the `style` dictionary in the `InputOutput` class's `__init__` method:

```python
aider/io.py
<<<<<<< ORIGINAL
        if self.user_input_color:
            style = Style.from_dict
^C KeyboardInterrupt
USER: no, just for the markdown highlighting in the `PromptSession`
ASSISTANT: I apologize for the misunderstanding. To override the style for ticked words in the `PromptSession`, we need to modify the `aider/io.py` file. Update the `style` dictionary in the `get_input` method:

```python
aider/io.py
<<<<<<< ORIGINAL
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color})
=======
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": "underline"})
>>>>>>> UPDATED
```

This change will apply the underline style to ticked words in the `PromptSession` without changing their color.
2023-05-29 11:46:57 -07:00
Paul Gauthier
4a4d0efe89 aider: Replaced MarkdownLexer with PygmentsLexer to correctly highlight user input with markdown syntax.
# Context:
USER: AttributeError: 'MarkdownLexer' object has no attribute 'lex_document'
ASSISTANT: I apologize for the confusion. It seems I misunderstood the usage of `MarkdownLexer` with `prompt_toolkit`. Instead, we should use `PygmentsLexer` from `prompt_toolkit.lexers` to wrap the `MarkdownLexer`. Here's the updated change:

First, import `PygmentsLexer` from `prompt_toolkit.lexers`:

```python
aider/io.py
<<<<<<< ORIGINAL
from prompt_toolkit.completion import Completer, Completion
=======
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.lexers import PygmentsLexer
>>>>>>> UPDATED
```

Then, update the `PromptSession` instantiation in the `get_input` method:

```python
aider/io.py
<<<<<<< ORIGINAL
            session_kwargs = {
                "message": show,
                "completer": completer_instance,
                "reserve_space_for_menu": 4,
                "complete_style": CompleteStyle.MULTI_COLUMN,
                "input": self.input,
                "output": self.output,
                "lexer": MarkdownLexer(),
            }
=======
            session_kwargs = {
                "message": show,
                "completer": completer_instance,
                "reserve_space_for_menu": 4,
                "complete_style": CompleteStyle.MULTI_COLUMN,
                "input": self.input,
                "output": self.output,
                "lexer": PygmentsLexer(MarkdownLexer),
            }
>>>>>>> UPDATED
```

These changes will correctly use the `MarkdownLexer` with `prompt_toolkit` to highlight the user input with markdown syntax.
2023-05-29 11:43:50 -07:00
Paul Gauthier
2a0761b0ce aider: Added MarkdownLexer to highlight user input with markdown syntax.
# Context:
USER: have `prompt_toolkit` highlight the user input with a markdown lexer
ASSISTANT: To highlight the user input with a markdown lexer, we need to modify the `aider/io.py` file. We will import the `MarkdownLexer` from `pygments.lexers.markup` and use it as the lexer for the `PromptSession`.

Here's the change you need to make:

```python
aider/io.py
<<<<<<< ORIGINAL
from pygments.lexers import guess_lexer_for_filename
=======
from pygments.lexers import guess_lexer_for_filename, MarkdownLexer
>>>>>>> UPDATED
```

And update the `PromptSession` instantiation in the `get_input` method:

```python
aider/io.py
<<<<<<< ORIGINAL
            session_kwargs = {
                "message": show,
                "completer": completer_instance,
                "reserve_space_for_menu": 4,
                "complete_style": CompleteStyle.MULTI_COLUMN,
                "input": self.input,
                "output": self.output,
            }
=======
            session_kwargs = {
                "message": show,
                "completer": completer_instance,
                "reserve_space_for_menu": 4,
                "complete_style": CompleteStyle.MULTI_COLUMN,
                "input": self.input,
                "output": self.output,
                "lexer": MarkdownLexer(),
            }
>>>>>>> UPDATED
```

These changes will import the `MarkdownLexer` and use it for the `PromptSession`, which will highlight the user input with markdown syntax.
2023-05-29 11:42:19 -07:00
Paul Gauthier
e4805490f5 quote autocompletions 2023-05-29 11:32:50 -07:00
Paul Gauthier
cdcb8b2e73 check for "missing filename" in valerr 2023-05-29 11:11:52 -07:00
Paul Gauthier
72a59e120c aider: Modified final test to check if a ValueError is raised.
# Context:
USER: the final test SHOULD raise ValueError
ASSISTANT: I understand that you want the final test in `tests/test_utils.py` to raise a `ValueError`. I will modify the test to check for the exception.

```python
tests/test_utils.py
<<<<<<< ORIGINAL
        # Should raise a ValueError!
        list(utils.find_original_update_blocks(edit))
=======
        with self.assertRaises(ValueError):
            list(utils.find_original_update_blocks(edit))
>>>>>>> UPDATED
```

Now, the final test in `tests/test_utils.py` will check if a `ValueError` is raised.
2023-05-29 07:14:42 -07:00
Paul Gauthier
445c253abc fixed corner case bugs in find_original_update_blocks 2023-05-29 07:12:57 -07:00
Paul Gauthier
87c902b285 aider: Fixed IndexError in find_original_update_blocks function.
# Context:
USER: I ran this command:

 pytest tests/test_utils.py

And got this output:

============================= test session starts ==============================
platform darwin -- Python 3.11.3, pytest-7.3.1, pluggy-1.0.0
rootdir: /Users/gauthier/Projects/aider
collected 11 items

tests/test_utils.py F..........                                          [100%]

=================================== FAILURES ===================================
__________________ TestUtils.test_false_incomplete_edit_block __________________

content = '\nNo problem! Here are the changes to patch `subprocess.check_output` instead of `subprocess.run` in both tests:\n\n`...h `subprocess.check_output` patches in both `test_check_for_ctags_failure` and `test_check_for_ctags_success` tests.\n'

    def find_original_update_blocks(content):
        # make sure we end with a newline, otherwise the regex will miss <<UPD on the last line
        if not content.endswith("\n"):
            content = content + "\n"

        pieces = re.split(split_re, content)

        pieces.reverse()
        processed = []

        try:
            while pieces:
                cur = pieces.pop()

                if cur in (DIVIDER, UPDATED):
                    processed.append(cur)
                    raise ValueError(f"Unexpected {cur}")

                if cur.strip() != ORIGINAL:
                    processed.append(cur)
                    continue

                processed.append(cur)  # original_marker

                filename = processed[-2].splitlines()[-1].strip()
                if not len(filename) or "`" in filename:
>                   filename = processed[-2].splitlines()[-2].strip()
E                   IndexError: list index out of range

aider/utils.py:234: IndexError

During handling of the above exception, another exception occurred:

self = <tests.test_utils.TestUtils testMethod=test_false_incomplete_edit_block>

        def test_false_incomplete_edit_block(self):
            edit = """
    No problem! Here are the changes to patch `subprocess.check_output` instead of `subprocess.run` in both tests:

    ```python
    tests/test_repomap.py
    <<<<<<< ORIGINAL
        def test_check_for_ctags_failure(self):
            with patch("subprocess.run") as mock_run:
                mock_run.side_effect = Exception("ctags not found")
    =======
        def test_check_for_ctags_failure(self):
            with patch("subprocess.check_output") as mock_check_output:
                mock_check_output.side_effect = Exception("ctags not found")
    >>>>>>> UPDATED

    <<<<<<< ORIGINAL
        def test_check_for_ctags_success(self):
            with patch("subprocess.run") as mock_run:
                mock_run.return_value = CompletedProcess(args=["ctags", "--version"], returncode=0, stdout='''{
      "_type": "tag",
      "name": "status",
      "path": "aider/main.py",
      "pattern": "/^    status = main()$/",
      "kind": "variable"
    }''')
    =======
        def test_check_for_ctags_success(self):
            with patch("subprocess.check_output") as mock_check_output:
                mock_check_output.return_value = '''{
      "_type": "tag",
      "name": "status",
      "path": "aider/main.py",
      "pattern": "/^    status = main()$/",
      "kind": "variable"
    }'''
    >>>>>>> UPDATED
    ```

    These changes replace the `subprocess.run` patches with `subprocess.check_output` patches in both `test_check_for_ctags_failure` and `test_check_for_ctags_success` tests.
    """
            # Should not raise a ValueError
>           list(utils.find_original_update_blocks(edit))

tests/test_utils.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

content = '\nNo problem! Here are the changes to patch `subprocess.check_output` instead of `subprocess.run` in both tests:\n\n`...h `subprocess.check_output` patches in both `test_check_for_ctags_failure` and `test_check_for_ctags_success` tests.\n'

    def find_original_update_blocks(content):
        # make sure we end with a newline, otherwise the regex will miss <<UPD on the last line
        if not content.endswith("\n"):
            content = content + "\n"

        pieces = re.split(split_re, content)

        pieces.reverse()
        processed = []

        try:
            while pieces:
                cur = pieces.pop()

                if cur in (DIVIDER, UPDATED):
                    processed.append(cur)
                    raise ValueError(f"Unexpected {cur}")

                if cur.strip() != ORIGINAL:
                    processed.append(cur)
                    continue

                processed.append(cur)  # original_marker

                filename = processed[-2].splitlines()[-1].strip()
                if not len(filename) or "`" in filename:
                    filename = processed[-2].splitlines()[-2].strip()
                    if not len(filename) or "`" in filename:
                        raise ValueError(f"Bad/missing filename. It should go right above {ORIGINAL}")

                original_text = pieces.pop()
                processed.append(original_text)

                divider_marker = pieces.pop()
                processed.append(divider_marker)
                if divider_marker.strip() != DIVIDER:
                    raise ValueError(f"Expected {DIVIDER}")

                updated_text = pieces.pop()

                updated_marker = pieces.pop()
                if updated_marker.strip() != UPDATED:
                    raise ValueError(f"Expected {UPDATED}")

                yield filename, original_text, updated_text
        except ValueError as e:
            processed = "".join(processed)
            err = e.args[0]
            raise ValueError(f"{processed}\n^^^ {err}")
        except IndexError:
            processed = "".join(processed)
>           raise ValueError(f"{processed}\n^^^ Incomplete ORIGINAL/UPDATED block.")
E           ValueError:
E           No problem! Here are the changes to patch `subprocess.check_output` instead of `subprocess.run` in both tests:
E
E           ```python
E           tests/test_repomap.py
E           <<<<<<< ORIGINAL
E               def test_check_for_ctags_failure(self):
E                   with patch("subprocess.run") as mock_run:
E                       mock_run.side_effect = Exception("ctags not found")
E           =======
E
E           <<<<<<< ORIGINAL
E
E           ^^^ Incomplete ORIGINAL/UPDATED block.

aider/utils.py:259: ValueError
=========================== short test summary info ============================
FAILED tests/test_utils.py::TestUtils::test_false_incomplete_edit_block - Val...
========================= 1 failed, 10 passed in 0.04s =========================

ASSISTANT: It seems that the test `test_false_incomplete_edit_block` is failing due to an IndexError in the `find_original_update_blocks` function in `aider/utils.py`. I will fix the issue by handling the IndexError properly.

```python
aider/utils.py
<<<<<<< ORIGINAL
    if not len(filename) or "`" in filename:
        filename = processed[-2].splitlines()[-2].strip()
        if not len(filename) or "`" in filename:
            raise ValueError(f"Bad/missing filename. It should go right above {ORIGINAL}")
=======
    try:
        if not len(filename) or "`" in filename:
            filename = processed[-2].splitlines()[-2].strip()
            if not len(filename) or "`" in filename:
                raise ValueError(f"Bad/missing filename. It should go right above {ORIGINAL}")
    except IndexError:
        raise ValueError(f"Bad/missing filename. It should go right above {ORIGINAL}")
>>>>>>> UPDATED
```

Now, the IndexError should be handled properly, and the test should pass. Please run the tests again to confirm the fix.
2023-05-29 07:09:09 -07:00
Paul Gauthier
a404698a92 added test_false_incomplete_edit_block 2023-05-29 07:07:08 -07:00
Paul Gauthier
82cc64eb6f upgrade actions versions 2023-05-29 06:46:22 -07:00