Commit graph

10395 commits

Author SHA1 Message Date
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
d28cb2beea noop 2023-05-29 11:27:19 -07:00
Paul Gauthier
27bd993cab Merge branch 'main' into call-graph 2023-05-29 11:18:30 -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
Paul Gauthier
caa61089d8 add py3.8, 3.9 to actions 2023-05-29 06:43:16 -07:00
paul-gauthier
9abaddb754
Update python-tests.yml 2023-05-29 05:57:27 -07:00
Paul Gauthier
b68ac68dd4 copy 2023-05-28 23:09:22 -07:00
Paul Gauthier
512c990916 copy 2023-05-28 22:59:07 -07:00
Paul Gauthier
92cd2f3ce6 isort 2023-05-28 22:47:38 -07:00
Paul Gauthier
95be55a2b6 aider: Updated isort package to version 5.11.1 in .pre-commit-config.yaml.
# Context:
USER: I ran this command:

 pre-commit run --all-files

And got this output:

[INFO] Installing environment for https://github.com/pycqa/isort.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: command: ('/Users/gauthier/.cache/pre-commit/repothul7kft/py_env-python3/bin/python', '-mpip', 'install', '.')
return code: 1
stdout:
    Processing /Users/gauthier/.cache/pre-commit/repothul7kft
      Installing build dependencies: started
      Installing build dependencies: finished with status 'done'
      Getting requirements to build wheel: started
      Getting requirements to build wheel: finished with status 'done'
      Preparing metadata (pyproject.toml): started
      Preparing metadata (pyproject.toml): finished with status 'error'
stderr:
      error: subprocess-exited-with-error

      × Preparing metadata (pyproject.toml) did not run successfully.
      │ exit code: 1
      ╰─> [17 lines of output]
          Traceback (most recent call last):
            File "/Users/gauthier/.cache/pre-commit/repothul7kft/py_env-python3/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
              main()
            File "/Users/gauthier/.cache/pre-commit/repothul7kft/py_env-python3/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
              json_out['return_val'] = hook(**hook_input['kwargs'])
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            File "/Users/gauthier/.cache/pre-commit/repothul7kft/py_env-python3/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 149, in prepare_metadata_for_build_wheel
              return hook(metadata_directory, config_settings)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            File "/private/var/folders/49/kxrdwwbx0h9bchx99397477c0000gn/T/pip-build-env-sqwnl1t6/overlay/lib/python3.11/site-packages/poetry/core/masonry/api.py", line 41, in prepare_metadata_for_build_wheel
              poetry = Factory().create_poetry(Path(".").resolve(), with_groups=False)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            File "/private/var/folders/49/kxrdwwbx0h9bchx99397477c0000gn/T/pip-build-env-sqwnl1t6/overlay/lib/python3.11/site-packages/poetry/core/factory.py", line 58, in create_poetry
              raise RuntimeError("The Poetry configuration is invalid:\n" + message)
          RuntimeError: The Poetry configuration is invalid:
            - [extras.pipfile_deprecated_finder.2] 'pip-shims<=0.3.4' does not match '^[a-zA-Z-_.0-9]+$'

          [end of output]

      note: This error originates from a subprocess, and is likely not a problem with pip.
    error: metadata-generation-failed

    × Encountered error while generating package metadata.
    ╰─> See above for output.

    note: This is an issue with the package mentioned above, not pip.
    hint: See above for details.
Check the log at /Users/gauthier/.cache/pre-commit/pre-commit.log

ASSISTANT: It seems like there is an issue with the `isort` package configuration in the `.pre-commit-config.yaml` file. The error message indicates that the `pip-shims<=0.3.4` does not match the expected pattern `^[a-zA-Z-_.0-9]+$`.

To fix this issue, you can try updating the `isort` package to the latest version. Modify the `.pre-commit-config.yaml` file as follows:

```yaml
.pre-commit-config.yaml
<<<<<<< ORIGINAL
  - repo: https://github.com/pycqa/isort
    rev: 5.10.1
    hooks:
      - id: isort
        args: ["--profile", "black"]
=======
  - repo: https://github.com/pycqa/isort
    rev: 5.11.1
    hooks:
      - id: isort
        args: ["--profile", "black"]
>>>>>>> UPDATED
```

After updating the `isort` version, try running the `pre-commit run --all-files` command again.
2023-05-28 22:46:02 -07:00
Paul Gauthier
4811bc91c2 aider: Added isort to the pre-commit configuration with the "black" profile.
# Context:
USER: add isort to pre-commit
ASSISTANT: To add isort to the pre-commit configuration, I need write access to the `.pre-commit-config.yaml` file. Please make it *read-write* and let me know.
USER: I added these *read-write* files: .pre-commit-config.yaml
ASSISTANT: Great! Now I will add isort to the `.pre-commit-config.yaml` file.

```yaml
.pre-commit-config.yaml
<<<<<<< ORIGINAL
repos:
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
        args: ["--line-length", "100", "--preview"]
  - repo: https://github.com/pycqa/flake8
    rev: 6.0.0
    hooks:
      - id: flake8
        args: ["--show-source"]
=======
repos:
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
        args: ["--line-length", "100", "--preview"]
  - repo: https://github.com/pycqa/flake8
    rev: 6.0.0
    hooks:
      - id: flake8
        args: ["--show-source"]
  - repo: https://github.com/pycqa/isort
    rev: 5.10.1
    hooks:
      - id: isort
        args: ["--profile", "black"]
>>>>>>> UPDATED
```

I've added isort to the pre-commit configuration with the "black" profile to ensure compatibility with the existing black formatter.
2023-05-28 22:43:37 -07:00
Paul Gauthier
48e9df2282 move tempdir handling to setup/teardown 2023-05-28 22:42:25 -07:00
Paul Gauthier
e50fe2469d aider: Added setUp and tearDown methods to TestCommands class to remember the current working directory, create a temporary directory, and change the working directory to the temporary directory in setUp, and change the working directory back to the original directory in tearDown.
# Context:
USER: add setUp and tearDown. in setUp, make a remember the cwd, make a tempdir and chdir there. in teardown, chdir back to the original dir
ASSISTANT: I will add `setUp` and `tearDown` methods to the `TestCommands` class in the `tests/test_commands.py` file. In the `setUp` method, I will
^C KeyboardInterrupt
USER: add setUp and tearDown. in setUp, make a remember the cwd, make a tempdir and chdir there. in teardown, chdir back to the original dir
ASSISTANT: I will add `setUp` and `tearDown` methods to the `TestCommands` class in the `tests/test_commands.py` file. In the `setUp` method, I will remember the current working directory, create a temporary directory, and change the working directory to the temporary directory. In the `tearDown` method, I will change the working directory back to the original directory.

Here are the changes:

```python
tests/test_commands.py
<<<<<<< ORIGINAL
class TestCommands(TestCase):
    def test_cmd_add(self):
=======
import shutil

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):
>>>>>>> UPDATED
```
2023-05-28 22:40:37 -07:00
Paul Gauthier
bb969c7197 aider: Added a temporary directory and changed the current working directory in tests/test_commands.py and restored the working directory after the context manager exits.
# Context:
USER: is there an idiomatic way in tests to make a tempdir, chdir there and then pop back to the previous cwd
ASSISTANT: Yes, you can use the `tempfile.TemporaryDirectory` context manager along with the `os.chdir` function to create a temporary directory, change the current working directory to it, and then automatically revert back to the previous working directory when the context manager exits. Here's an example:

```python
import os
import tempfile

def test_tempdir_example():
    original_cwd = os.getcwd()

    with tempfile.TemporaryDirectory() as tempdir:
        os.chdir(tempdir)
        # Perform your tests here

    # The working directory is automatically restored after the context manager exits
    assert os.getcwd() == original_cwd
```

In this example, the `test_tempdir_example` function creates a temporary directory, changes the current working directory to it, and then performs any tests inside the `with` block. When the block is exited, the working directory is automatically restored to its original value.
USER: do that in tests/test_commands.py
ASSISTANT: Here's the updated `tests/test_commands.py` with the temporary directory and working directory change:

```python
tests/test_commands.py
<<<<<<< ORIGINAL
import os
import tempfile
from unittest import TestCase
from aider.commands import Commands
from aider.io import InputOutput

class TestCommands(TestCase):
    def test_cmd_add(self):
        # Create a temporary directory and change the current working directory
        with tempfile.TemporaryDirectory() as tmpdir:
            os.chdir(tmpdir)

            # Initialize the Commands and InputOutput objects
            io = InputOutput(pretty=False, yes=True)
            from aider.coder import Coder

            coder = Coder(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"))
=======
import os
import tempfile
from unittest import TestCase
from aider.commands import Commands
from aider.io import InputOutput

class TestCommands(TestCase):
    def test_cmd_add(self):
        original_cwd = os.getcwd()

        with tempfile.TemporaryDirectory() as tmpdir:
            os.chdir(tmpdir)

            # Initialize the Commands and InputOutput objects
            io = InputOutput(pretty=False, yes=True)
            from aider.coder import Coder

            coder = Coder(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"))

        # The working directory is automatically restored after the context manager exits
        assert os.getcwd() == original_cwd
>>>>>>> UPDATED
```

I've added the `original_cwd` variable to store the original working directory before entering the `with` block. After the block is exited, the working directory is automatically restored, and I've added an assertion to check that the working directory is indeed restored to its original value.
2023-05-28 22:35:00 -07:00
Paul Gauthier
f6197fac40 cleanup 2023-05-28 22:29:21 -07:00
Paul Gauthier
c85c99f9d0 Merge remote-tracking branch 'origin/main' 2023-05-28 22:22:43 -07:00
Paul Gauthier
9b6eefa140 copy 2023-05-28 22:22:32 -07:00
Paul Gauthier
03f300ec75 aider: Updated test_repomap.py to put the JSON string on one line in the test_check_for_ctags_success method.
# Context:
USER: put all that json on one line
ASSISTANT: I will update the `tests/test_repomap.py` file to put the JSON string on one line in the `test_check_for_ctags_success` method.

```python
tests/test_repomap.py
<<<<<<< ORIGINAL
            mock_run.return_value = CompletedProcess(args=["ctags", "--version"], returncode=0, stdout=b'''{
  "_type": "tag",
  "name": "status",
  "path": "aider/main.py",
  "pattern": "/^    status = main()$/",
  "kind": "variable"
}''')
=======
            mock_run.return_value = CompletedProcess(args=["ctags", "--version"], returncode=0, stdout=b'{"_type": "tag", "name": "status", "path": "aider/main.py", "pattern": "/^    status = main()$/", "kind": "variable"}')
>>>>>>> UPDATED
```

Now the JSON string is on one line in the `test_check_for_ctags_success` method.
2023-05-28 22:19:44 -07:00
Paul Gauthier
346eb7a834 aider: Replaced string with bytes object in test_check_for_ctags_success to fix 'decode' method issue.
# Context:
USER: running test_check_for_ctags_success i get: tests/test_repomap.py 'str' object has no attribute 'decode'
ASSISTANT: It seems like the issue is with the `decode` method being called on a string object. I'll fix this issue for you. Here's the change you need to make in the `tests/test_repomap.py` file:

```python
tests/test_repomap.py
<<<<<<< ORIGINAL
            mock_run.return_value = CompletedProcess(args=["ctags", "--version"], returncode=0, stdout='''{
  "_type": "tag",
  "name": "status",
  "path": "aider/main.py",
  "pattern": "/^    status = main()$/",
  "kind": "variable"
}''')
=======
            mock_run.return_value = CompletedProcess(args=["ctags", "--version"], returncode=0, stdout=b'''{
  "_type": "tag",
  "name": "status",
  "path": "aider/main.py",
  "pattern": "/^    status = main()$/",
  "kind": "variable"
}''')
>>>>>>> UPDATED
```

This change replaces the string with a bytes object, so the `decode` method can be called without any issues.
2023-05-28 22:18:18 -07:00
paul-gauthier
563051f436
Update README.md 2023-05-28 20:14:44 -07:00
paul-gauthier
7e2e03fc98
Update README.md 2023-05-28 17:45:42 -07:00
paul-gauthier
91ee78ed5d
Update README.md 2023-05-28 17:45:15 -07:00
Paul Gauthier
f5de27ccdd aider: Updated test_check_for_ctags_success to return valid JSON output for get_tags.
# Context:
USER: the output of the subprocess.run needs to be valid json like this:

{
  "_type": "tag",
  "name": "status",
  "path": "aider/main.py",
  "pattern": "/^    status = main()$/",
  "kind": "variable"
}

ASSISTANT: To update the test `test_check_for_ctags_success` to return valid JSON output for `get_tags`, modify the `tests/test_repomap.py` file. Here's the change:

```python
tests/test_repomap.py
<<<<<<< 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="Exuberant Ctags 5.8")
=======
    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"
}''')
>>>>>>> UPDATED
```

This change updates the `stdout` value of the `CompletedProcess` object to return valid JSON output as specified. After making this change, run the tests again to ensure they pass.
2023-05-28 17:09:45 -07:00
Paul Gauthier
c2e8fee3d9 aider: Import CompletedProcess from the subprocess module to fix NameError in test_check_for_ctags_success.
# Context:
USER: pytest tests/test_repomap.py
ASSISTANT: I'm an AI language model and cannot execute commands directly. However,
^C KeyboardInterrupt
USER: I ran this command:

 pytest tests/test_repomap.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 5 items

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

=================================== FAILURES ===================================
___________________ TestRepoMap.test_check_for_ctags_success ___________________

self = <tests.test_repomap.TestRepoMap testMethod=test_check_for_ctags_success>

    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="Exuberant Ctags 5.8")
E           NameError: name 'CompletedProcess' is not defined

tests/test_repomap.py:67: NameError
=========================== short test summary info ============================
FAILED tests/test_repomap.py::TestRepoMap::test_check_for_ctags_success - Nam...
========================= 1 failed, 4 passed in 0.43s ==========================

ASSISTANT: It looks like there's a `NameError` because `CompletedProcess` is not defined. To fix this, you need to import `CompletedProcess` from the `subprocess` module. Here's the change:

```python
tests/test_repomap.py
<<<<<<< ORIGINAL
from unittest.mock import patch
=======
from unittest.mock import patch
from subprocess import CompletedProcess
>>>>>>> UPDATED
```

This change imports `CompletedProcess` from the `subprocess` module, which should resolve the `NameError`. After making this change, try running the tests again.
2023-05-28 17:08:28 -07:00
Paul Gauthier
6ead145c17 aider: Added test method test_check_for_ctags_success that patches subprocess.run to return a CompletedProcess object with a successful return code and sensible output, and checks if check_for_ctags returns True.
# Context:
USER: add another like that, but the patched subprocess should return sensible output for get_tags
ASSISTANT: To add another test for `check_for_ctags` that patches `subprocess` to return sensible output for `get_tags`, we'll modify the `tests/test_repomap.py` file. We'll use the `unittest.mock` library to patch the `subprocess.run` function to simulate a successful execution.

Here's the change:

```python
tests/test_repomap.py
<<<<<<< ORIGINAL
    def test_get_tags_map_without_ctags(self):
=======
    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="Exuberant Ctags 5.8")
            repo_map = RepoMap(use_ctags=True)
            result = repo_map.check_for_ctags()
            self.assertTrue(result)

    def test_get_tags_map_without_ctags(self):
>>>>>>> UPDATED
```

This adds a new test method `test_check_for_ctags_success` that patches `subprocess.run` to return a `CompletedProcess` object with a successful return code and sensible output. The test then checks if `check_for_ctags` returns `True`.
2023-05-28 17:07:49 -07:00
Paul Gauthier
8b3b4a2e26 Added import of unittest.mock to test_repomap.py. 2023-05-28 17:07:05 -07:00
Paul Gauthier
f2a116e0e1 aider: Added test method test_check_for_ctags_failure that patches subprocess.run to raise an exception, simulating a failure, and checks if check_for_ctags returns False.
# Context:
USER: in tests/test_repomap.py add a test for check_for_ctags which patches subprocess to fail. check_for_ctags should return false
ASSISTANT: To add a test for `check_for_ctags` that patches `subprocess` to fail, we'll modify the `tests/test_repomap.py` file. We'll use the `unittest.mock` library to patch the `subprocess.run` function to simulate a failure.

Here's the change:

```python
tests/test_repomap.py
<<<<<<< ORIGINAL
    def test_get_tags_map_without_ctags(self):
=======
    from unittest.mock import patch

    def test_check_for_ctags_failure(self):
        with patch("subprocess.run") as mock_run:
            mock_run.side_effect = Exception("ctags not found")
            repo_map = RepoMap(use_ctags=True)
            result = repo_map.check_for_ctags()
            self.assertFalse(result)

    def test_get_tags_map_without_ctags(self):
>>>>>>> UPDATED
```

This adds a new test method `test_check_for_ctags_failure` that patches `subprocess.run` to raise an exception, simulating a failure. The test then checks if `check_for_ctags` returns `False`.
2023-05-28 17:06:09 -07:00
Paul Gauthier
e78ea4299f removed test 2023-05-28 17:04:15 -07:00
Paul Gauthier
3b23efa4d8 aider: Changed test_main_with_ctags_mocked_failure to run within a temporary directory.
# Context:
USER: we need to cwd into a temp dir before the test
ASSISTANT: To change the working directory to a temporary directory before running the test, you can use the `tempfile.TemporaryDirectory()` context manager in the `test_main_with_ctags_mocked_failure` method. Here's the updated code for `tests/test_main.py`:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def test_main_with_ctags_mocked_failure(self):
        with patch("subprocess.run", side_effect=subprocess.CalledProcessError(1, "ctags")):
            with patch("aider.main.Coder") as MockCoder:
                main(["--ctags"])
                _, kwargs = MockCoder.call_args
                assert kwargs["use_ctags"] is False
=======
    def test_main_with_ctags_mocked_failure(self):
        with tempfile.TemporaryDirectory() as temp_dir:
            os.chdir(temp_dir)
            with patch("subprocess.run", side_effect=subprocess.CalledProcessError(1, "ctags")):
                with patch("aider.main.Coder") as MockCoder:
                    main(["--ctags"])
                    _, kwargs = MockCoder.call_args
                    assert kwargs["use_ctags"] is False
>>>>>>> UPDATED
```

This change will ensure that the test is run within a temporary directory.
2023-05-28 17:01:06 -07:00
Paul Gauthier
640479dafb aider: Added a test to tests/test_main.py that runs with --ctags but mocks subprocess to fail, asserting that coder.use_ctags is false.
# Context:
USER: add a test to tests/test_main.py that runs with --ctags but mocks subprocess to fail. assert that coder.use_ctags is false
ASSISTANT: To add a test that runs with `--ctags` but mocks `subprocess` to fail, you can follow these steps:

1. Import `subprocess` at the beginning of the `tests/test_main.py` file.
2. Add a new test method called `test_main_with_ctags_mocked_failure` to the `TestMain` class.
3. In the new test method, use the `unittest.mock.patch` context manager to mock the `subprocess.run` function to raise a `subprocess.CalledProcessError` exception.
4. Inside the context manager, call the `main` function with the `--ctags` argument.
5. Assert that `coder.use_ctags` is `False`.

Here's the code change for `tests/test_main.py`:

```python
tests/test_main.py
<<<<<<< ORIGINAL
import os
import tempfile
from unittest import TestCase
from unittest.mock import patch
from aider.main import main
=======
import os
import tempfile
import subprocess
from unittest import TestCase
from unittest.mock import patch
from aider.main import main
>>>>>>> UPDATED
```

```python
tests/test_main.py
<<<<<<< ORIGINAL
            with patch("aider.main.Coder") as MockCoder:
                main(["--dirty-commits"])
                _, kwargs = MockCoder.call_args
                assert kwargs["dirty_commits"] is True
=======
            with patch("aider.main.Coder") as MockCoder:
                main(["--dirty-commits"])
                _, kwargs = MockCoder.call_args
                assert kwargs["dirty_commits"] is True

    def test_main_with_ctags_mocked_failure(self):
        with patch("subprocess.run", side_effect=subprocess.CalledProcessError(1, "ctags")):
            with patch("aider.main.Coder") as MockCoder:
                main(["--ctags"])
                _, kwargs = MockCoder.call_args
                assert kwargs["use_ctags"] is False
>>>>>>> UPDATED
```

This will add the requested test to `tests/test_main.py`.
2023-05-28 16:59:41 -07:00
paul-gauthier
835dc07b99
Update README.md 2023-05-28 15:02:04 -07:00
Paul Gauthier
130385584a copy 2023-05-28 14:28:22 -07:00
Paul Gauthier
ce656425a9 copy 2023-05-28 14:26:57 -07:00
Paul Gauthier
d129458a9d copy 2023-05-28 14:11:18 -07:00
Paul Gauthier
2b4fa34415 copy 2023-05-28 13:59:45 -07:00