From 9c28bbc98e1c37cc3e1f43c0914a0efa3eb6f506 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 20 May 2024 08:55:49 -0700 Subject: [PATCH 1/6] Refactored linting process and error handling in commands. --- aider/coders/base_coder.py | 16 ++++++++++++-- aider/commands.py | 43 ++++++++++++++++++++++++-------------- aider/io.py | 2 +- aider/linter.py | 13 +++++++++--- aider/main.py | 19 ++++++++++------- 5 files changed, 64 insertions(+), 29 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index f5cf80051..158bdff7e 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -82,10 +82,19 @@ class Coder: ) if not main_model: - main_model = models.Model(models.DEFAULT_MODEL_NAME) + if from_coder: + main_model = from_coder.main_model + else: + main_model = models.Model(models.DEFAULT_MODEL_NAME) if edit_format is None: - edit_format = main_model.edit_format + if from_coder: + edit_format = from_coder.edit_format + else: + edit_format = main_model.edit_format + + if not io and from_coder: + io = from_coder.io if from_coder: use_kwargs = dict(from_coder.original_kwargs) # copy orig kwargs @@ -125,6 +134,9 @@ class Coder: return res + def clone(self, **kwargs): + return Coder.create(from_coder=self, **kwargs) + def get_announcements(self): lines = [] lines.append(f"Aider v{__version__}") diff --git a/aider/commands.py b/aider/commands.py index 95f9b67b8..36d6ba626 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -153,40 +153,51 @@ class Commands: commit_message = args.strip() self.coder.repo.commit(message=commit_message) - def cmd_lint(self, args): + def cmd_lint(self, args="", fnames=None): "Commit, run the linter on all dirty files, fix problems and commit again" if not self.coder.repo: self.io.tool_error("No git repository found.") return - if not self.coder.repo.is_dirty(): - self.io.tool_error("No more changes to commit.") - return + if not fnames: + fnames = self.coder.repo.get_dirty_files() - fnames = self.coder.repo.get_dirty_files() - linted = False + if not fnames: + self.io.tool_error("No dirty files to lint.") + return + + lint_coder = None for fname in fnames: try: errors = self.coder.linter.lint(fname, cmd=args) - linted = True except FileNotFoundError as err: self.io.tool_error(f"Unable to lint {fname}") self.io.tool_error(str(err)) continue - if errors: - # Commit everything before we start fixing lint errors - if self.coder.repo.is_dirty(): - self.cmd_commit("") + if not errors: + continue - self.io.tool_error(errors) + # Commit everything before we start fixing lint errors + if self.coder.repo.is_dirty(): + self.cmd_commit("") - abs_file_path = self.coder.abs_root_path(fname) - self.coder.abs_fnames.add(abs_file_path) - self.coder.run(errors) + self.io.tool_error(errors) - if linted and self.coder.repo.is_dirty(): + if not lint_coder: + lint_coder = self.coder.clone( + # Clear the chat history, fnames + cur_messages=[], + done_messages=[], + fnames=None, + ) + + lint_coder.add_rel_fname(fname) + lint_coder.run(errors) + lint_coder.abs_fnames = set() + + if lint_coder and self.coder.repo.is_dirty(): self.cmd_commit("") def cmd_clear(self, args): diff --git a/aider/io.py b/aider/io.py index ee770332e..85debfec3 100644 --- a/aider/io.py +++ b/aider/io.py @@ -325,7 +325,7 @@ class InputOutput: return res - def tool_error(self, message, strip=True): + def tool_error(self, message="", strip=True): self.num_error_outputs += 1 if message.strip(): diff --git a/aider/linter.py b/aider/linter.py index 4ca1ee17d..1435b4113 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -13,7 +13,6 @@ from tree_sitter_languages import get_parser # noqa: E402 warnings.simplefilter("ignore", category=FutureWarning) - class Linter: def __init__(self, encoding="utf-8", root=None): self.encoding = encoding @@ -22,9 +21,14 @@ class Linter: self.languages = dict( python=self.py_lint, ) + self.all_lint_cmd = None def set_linter(self, lang, cmd): - self.languages[lang] = cmd + if lang: + self.languages[lang] = cmd + return + + self.all_lint_cmd = cmd def get_rel_fname(self, fname): if self.root: @@ -66,7 +70,10 @@ class Linter: lang = filename_to_lang(fname) if not lang: return - cmd = self.languages.get(lang) + if self.all_lint_cmd: + cmd = self.all_lint_cmd + else: + cmd = self.languages.get(lang) if callable(cmd): linkres = cmd(fname, rel_fname, code) diff --git a/aider/main.py b/aider/main.py index ad4c55c3d..9cf0dda10 100644 --- a/aider/main.py +++ b/aider/main.py @@ -1,5 +1,6 @@ import configparser import os +import re import sys from pathlib import Path @@ -181,14 +182,18 @@ def parse_lint_cmds(lint_cmds, io): err = False res = dict() for lint_cmd in lint_cmds: - pieces = lint_cmd.split(":") - lang = pieces[0] - cmd = lint_cmd[len(lang) + 1 :] + if re.match(r"^[a-z]+:.*", lint_cmd): + pieces = lint_cmd.split(":") + lang = pieces[0] + cmd = lint_cmd[len(lang) + 1 :] + lang = lang.strip() + else: + lang = None + cmd = lint_cmd - lang = lang.strip() cmd = cmd.strip() - if lang and cmd: + if cmd: res[lang] = cmd else: io.tool_error(f'Unable to parse --lint-cmd "{lint_cmd}"') @@ -383,11 +388,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F return if args.commit: - coder.commands.cmd_commit("") + coder.commands.cmd_commit() return if args.lint: - coder.commands.cmd_lint("") + coder.commands.cmd_lint(fnames=fnames) return if args.test: From a115e594c0f8f7f67b838b57f52ee3b349d30ae1 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 20 May 2024 08:56:21 -0700 Subject: [PATCH 2/6] Add import statement for 're' module and fix regex pattern in linter.py. --- aider/linter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aider/linter.py b/aider/linter.py index 1435b4113..b2e2fd2b4 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -3,6 +3,7 @@ import subprocess import sys import traceback import warnings +import re from dataclasses import dataclass from pathlib import Path @@ -93,7 +94,6 @@ class Linter: return res def py_lint(self, fname, rel_fname, code): - result = "" basic_res = basic_lint(rel_fname, code) compile_res = lint_python_compile(fname, code) @@ -210,7 +210,7 @@ import re def find_filenames_and_linenums(text, fnames): """ - Search text for all occurrences of :\d+ and make a list of them + Search text for all occurrences of :\\d+ and make a list of them where is one of the filenames in the list `fnames`. """ pattern = re.compile(r"(\b(?:" + "|".join(re.escape(fname) for fname in fnames) + r"):\d+\b)") From ce5dabd5f1b24f71b92646d1fc9f8169c9e795c8 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 20 May 2024 08:56:30 -0700 Subject: [PATCH 3/6] Removed unused import statement for 're' module. --- aider/linter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aider/linter.py b/aider/linter.py index b2e2fd2b4..4f752c159 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -3,7 +3,6 @@ import subprocess import sys import traceback import warnings -import re from dataclasses import dataclass from pathlib import Path From ee516e3958648e4126dd5371af95cef6443c32c4 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 20 May 2024 08:56:42 -0700 Subject: [PATCH 4/6] Added import statement for regular expressions in linter module. --- aider/linter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aider/linter.py b/aider/linter.py index 4f752c159..b2e2fd2b4 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -3,6 +3,7 @@ import subprocess import sys import traceback import warnings +import re from dataclasses import dataclass from pathlib import Path From 57a2c61386bb6966cbf41fa41c38273e710fd545 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 20 May 2024 09:01:22 -0700 Subject: [PATCH 5/6] updated lint cmd descriptions --- aider/args.py | 2 +- aider/commands.py | 6 +++--- aider/linter.py | 5 +---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/aider/args.py b/aider/args.py index a528c78d0..a6d5bbe6a 100644 --- a/aider/args.py +++ b/aider/args.py @@ -313,7 +313,7 @@ def get_parser(default_config_files, git_root): group.add_argument( "--lint", action="store_true", - help="Run the linter on all dirty files, fix problems and commit", + help="Lint and fix provided files, or dirty files if none provided", default=False, ) group.add_argument( diff --git a/aider/commands.py b/aider/commands.py index 36d6ba626..affa5af5e 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -154,14 +154,14 @@ class Commands: self.coder.repo.commit(message=commit_message) def cmd_lint(self, args="", fnames=None): - "Commit, run the linter on all dirty files, fix problems and commit again" + "Lint and fix provided files or in-chat files if none provided" if not self.coder.repo: self.io.tool_error("No git repository found.") return if not fnames: - fnames = self.coder.repo.get_dirty_files() + fnames = self.coder.get_inchat_relative_files() if not fnames: self.io.tool_error("No dirty files to lint.") @@ -170,7 +170,7 @@ class Commands: lint_coder = None for fname in fnames: try: - errors = self.coder.linter.lint(fname, cmd=args) + errors = self.coder.linter.lint(fname) except FileNotFoundError as err: self.io.tool_error(f"Unable to lint {fname}") self.io.tool_error(str(err)) diff --git a/aider/linter.py b/aider/linter.py index b2e2fd2b4..f2afe2d05 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -1,9 +1,9 @@ import os +import re import subprocess import sys import traceback import warnings -import re from dataclasses import dataclass from pathlib import Path @@ -205,9 +205,6 @@ def traverse_tree(node): return errors -import re - - def find_filenames_and_linenums(text, fnames): """ Search text for all occurrences of :\\d+ and make a list of them From 5032ce1a953aaf8b7e6683b49db2f0767d576158 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 20 May 2024 09:19:02 -0700 Subject: [PATCH 6/6] bump deps for +grep-ast==0.3.2 --- dev-requirements.txt | 4 ++-- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index fcbb97d26..1b97b4d8d 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -105,7 +105,7 @@ pyproject-hooks==1.1.0 # via # build # pip-tools -pytest==8.2.0 +pytest==8.2.1 # via -r dev-requirements.in python-dateutil==2.9.0.post0 # via @@ -115,7 +115,7 @@ pytz==2024.1 # via pandas pyyaml==6.0.1 # via pre-commit -requests==2.31.0 +requests==2.32.0 # via sphinx rich==13.7.1 # via typer diff --git a/requirements.txt b/requirements.txt index 90a340ccb..b5d0731f4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -96,7 +96,7 @@ googleapis-common-protos==1.63.0 # grpcio-status greenlet==3.0.3 # via playwright -grep-ast==0.3.1 +grep-ast==0.3.2 # via -r requirements.in grpcio==1.63.0 # via