aider is AI pair programming in your terminal https://aider.chat/
Find a file
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
.github/workflows upgrade actions versions 2023-05-29 06:46:22 -07:00
_layouts new gif 2023-05-27 17:31:02 -07:00
aider aider: Fixed IndexError in find_original_update_blocks function. 2023-05-29 07:09:09 -07:00
assets copy 2023-05-28 14:11:18 -07:00
docs copy 2023-05-27 07:42:21 -07:00
examples copy 2023-05-27 18:10:45 -07:00
tests added test_false_incomplete_edit_block 2023-05-29 07:07:08 -07:00
.flake8 debug 2023-05-08 22:55:55 -07:00
.pre-commit-config.yaml isort 2023-05-28 22:47:38 -07:00
_config.yml copy 2023-05-16 06:51:40 -07:00
CNAME Create CNAME 2023-05-15 12:54:06 -07:00
LICENSE.txt Added Apache 2.0 license 2023-05-15 08:29:00 -07:00
README.md copy 2023-05-28 23:09:22 -07:00
requirements.txt updated python version list 2023-05-27 13:54:32 -07:00
setup.py isort 2023-05-28 22:47:38 -07:00

aider is GPT-4 powered coding in your terminal

aider is a command-line chat tool that allows you to write and edit code with GPT-4. You can ask GPT to help you start a new project, or modify code in your existing git repo. Aider has features to help GPT understand and modify larger codebases and aider makes it easy to git commit, diff & undo changes proposed by GPT.

aider screenshot

Example chat transcripts

Here are some example transcripts that show how you can chat with aider to write and edit code with GPT-4.

You can find more chat transcripts on the examples page.

Features

  • Chat with GPT-4 about your code by launching aider from the command line with set of source files to discuss and edit together. GPT can see and edit the content of those files.
  • If you or GPT mention other filenames that are part of the git repo, aider will ask if you'd like to add them to the chat. See also the in-chat /add and /drop commands described below, which are other ways to manage which files are part of the chat context.
  • Request new features, changes, improvements, or bug fixes to your code. Ask for new test cases, updated documentation or code refactors.
  • aider will apply the edits suggested by GPT-4 directly to your source files.
  • aider will automatically commit each changeset to your local git repo with a descriptive commit message. These frequent, automatic commits provide a safety net. It's easy to undo aider changes or use standard git workflows to manage longer sequences of changes.
  • aider can review multiple source files at once and make coordinated code changes across all of them in a single changeset/commit.
  • aider can give GPT a map of your entire git repo, which helps it understand and modify large codebases.
  • You can edit the files by hand using your editor while chatting with aider.
    • aider will notice if you edit the files outside the chat.
    • It will help you commit these out-of-band changes, if you'd like.
    • It will bring the updated file contents into the chat.
    • You can bounce back and forth between the aider chat and your editor, to fluidly collaborate.
  • Live, colorized, human friendly output.
  • Readline style chat input history, with autocompletion of code tokens found in the source files being discussed (via prompt_toolkit and pygments lexers)

Installation

  1. Install the package:

    • From GitHub: pip install git+https://github.com/paul-gauthier/aider.git
    • From your local copy of the repo in develop mode to pick up local edits immediately: pip install -e .
  2. Set up your OpenAI API key as an environment variable OPENAI_API_KEY or by including it in an .aider.config.yml file (see aider --help).

  3. Optionally, install universal ctags. This is helpful if you plan to work with repositories with more than a handful of files. This allows aider --ctags to build a map of your entire git repo and share it with GPT to help it better understand and modify large codebases.

Usage

Run the aider tool by executing the following command:

aider <file1> <file2> ...

Replace <file1>, <file2>, etc., with the paths to the source code files you want to work on. These files will be added to the chat session.

You can also just launch aider anywhere in a git repo without naming files on the command line. It will discover all the files in the repo. You can then add and remove individual files in the chat session with the /add and /drop chat commands described below. If you or GPT mention one of the repo's filenames in the conversation, aider will ask if you'd like to add it to the chat.

You can also use additional command-line options, environment variables or configuration file to set many options:

  -c CONFIG_FILE, --config CONFIG_FILE
                        Specify the config file (default: search for .aider.conf.yml in git root or home directory)
  --input-history-file INPUT_HISTORY_FILE
                        Specify the chat input history file (default: .aider.input.history) [env var: AIDER_INPUT_HISTORY_FILE]
  --chat-history-file CHAT_HISTORY_FILE
                        Specify the chat history file (default: .aider.chat.history.md) [env var: AIDER_CHAT_HISTORY_FILE]
  --model MODEL         Specify the model to use for the main chat (default: gpt-4) [env var: AIDER_MODEL]
  -3                    Use gpt-3.5-turbo model for the main chat (not advised)
  --pretty              Enable pretty, colorized output (default: True) [env var: AIDER_PRETTY]
  --no-pretty           Disable pretty, colorized output [env var: AIDER_NO_PRETTY]
  --apply FILE          Apply the changes from the given file instead of running the chat (debug) [env var: AIDER_APPLY]
  --auto-commits        Enable auto commit of changes (default: True) [env var: AIDER_AUTO_COMMITS]
  --no-auto-commits     Disable auto commit of changes [env var: AIDER_NO_AUTO_COMMITS]
  --dirty-commits       Enable dirty commit of changes [env var: AIDER_DIRTY_COMMITS]
  --no-dirty-commits    Disable dirty commit of changes [env var: AIDER_NO_DIRTY_COMMITS]
  --openai-api-key OPENAI_API_KEY
                        Specify the OpenAI API key [env var: OPENAI_API_KEY]
  --dry-run             Perform a dry run without applying changes (default: False) [env var: AIDER_DRY_RUN]
  --show-diffs          Show diffs when committing changes (default: False) [env var: AIDER_SHOW_DIFFS]
  --ctags [CTAGS]       Add ctags to the chat to help GPT understand the codebase (default: check for ctags executable) [env var: AIDER_CTAGS]
  --yes                 Always say yes to every confirmation [env var: AIDER_YES]
  -v, --verbose         Enable verbose output [env var: AIDER_VERBOSE]

In chat commands

aider supports the following commands from within the chat:

  • /add <file>: Add matching files to the chat session.
  • /drop <file>: Remove matching files from the chat session.
  • /ls: List all known files and those included in the chat session.
  • /commit [message]: Commit outstanding changes to the repo. Use this to commit edits you made outside the chat, with your editor or git commands. aider will provide a commit message if you don't.
  • /undo: Undo the last git commit if it was done by aider.
  • /diff: Display the diff of the last aider commit.
  • /run <command>: Run a shell command and optionally add the output to the chat.
  • /help: Show help about all commands.

To use a command, simply type it in the chat input followed by any required arguments.

Tips

  • Large changes are best performed as a sequence of thoughtful bite sized steps, where you plan out the approach and overall design. Don't ask GPT to "build a house" all in one go. Instead, think about the architecture you want and then ask it to "build a foundation", "erect the walls", "run the wiring", etc.
  • Use Control-C to safely interrupt aider if it isn't providing a useful response. The partial response remains in the conversation, so you can refer to it when you reply with more information or direction.
  • Use the /run command to run tests, linters, etc and show the output to GPT so it can fix any issues.
  • Enter a multiline chat message by entering { alone on the first line. End the multiline message with } alone on the last line.
  • If your code is throwing an error, paste the error message and stack trace into aider as a multiline {} message and let aider fix the bug.
  • GPT-4 knows about a lot of standard tools and libraries, but may get some of the fine details wrong about APIs and function arguments. You can paste doc snippets into the chat with the multiline {} syntax.
  • aider will notice if you launch it on a git repo with uncommitted changes and offer to commit them before proceeding.
  • aider can only see the content of the files you specify, but it also gets a list of all the files in the repo. It may ask to see additional files if it feels that's needed for your requests.

Limitations

You probably need GPT-4 api access to use aider. You can invoke it with aider -3 to try using gpt-3.5-turbo, but it will almost certainly fail to function correctly. GPT-3.5 is unable to consistently follow directions to generate concise code edits in a stable, parsable format.

You can only use aider to edit code that fits in the GPT context window. For GPT-4 that is 8k tokens. It helps to be selective about how many source files you discuss with aider at one time. You might consider refactoring your code into more, smaller files (which is usually a good idea anyway). You can use aider to help perform such refactorings, if you start before the files get too large.

If you have access to gpt-4-32k, I would be curious to hear how it works with aider.