From 6df2c1595fdbb02f0e99b27cdca07f42ff5f0345 Mon Sep 17 00:00:00 2001 From: Titusz Pan Date: Wed, 23 Apr 2025 11:20:08 +0200 Subject: [PATCH 1/4] fix: remove branch filter from Windows tests workflow --- .github/workflows/windows-tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml index 21799563e..78fb1f3b7 100644 --- a/.github/workflows/windows-tests.yml +++ b/.github/workflows/windows-tests.yml @@ -8,8 +8,6 @@ on: - 'HISTORY.md' - '.github/workflows/*' - '!.github/workflows/windows-tests.yml' - branches: - - main pull_request: paths-ignore: - 'aider/website/**' From 5251a2452cf9c9c139774d50c6308cf78b8d4ba3 Mon Sep 17 00:00:00 2001 From: Titusz Pan Date: Wed, 23 Apr 2025 14:18:23 +0200 Subject: [PATCH 2/4] Add test to reproduce linting failure on windows --- tests/basic/test_linter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/basic/test_linter.py b/tests/basic/test_linter.py index 9dce56355..ace4a9311 100644 --- a/tests/basic/test_linter.py +++ b/tests/basic/test_linter.py @@ -1,3 +1,4 @@ +import os import unittest from unittest.mock import MagicMock, patch @@ -36,6 +37,15 @@ class TestLinter(unittest.TestCase): result = self.linter.run_cmd("test_cmd", "test_file.py", "code") self.assertIsNone(result) + def test_run_cmd_win(self): + if os.name != "nt": + self.skipTest("This test only runs on Windows") + from pathlib import Path + root = Path(__file__).parent.parent.parent.absolute().as_posix() + linter = Linter(encoding="utf-8", root=root) + result = linter.run_cmd("dir", "tests/basic", "code") + self.assertIsNone(result) + @patch("subprocess.Popen") def test_run_cmd_with_errors(self, mock_popen): mock_process = MagicMock() From d9aa3cb2d43f38632dd85dd7311616b7e5c0fb02 Mon Sep 17 00:00:00 2001 From: Titusz Pan Date: Wed, 23 Apr 2025 14:33:01 +0200 Subject: [PATCH 3/4] Replace shlex with cross-platform oslex --- aider/linter.py | 4 ++-- aider/utils.py | 7 ++----- requirements.txt | 6 +++++- requirements/requirements.in | 1 + tests/basic/test_linter.py | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/aider/linter.py b/aider/linter.py index 920a8b7c6..51ed40b70 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -4,7 +4,7 @@ import subprocess import sys import traceback import warnings -import shlex +import oslex from dataclasses import dataclass from pathlib import Path @@ -45,7 +45,7 @@ class Linter: return fname def run_cmd(self, cmd, rel_fname, code): - cmd += " " + shlex.quote(rel_fname) + cmd += " " + oslex.quote(rel_fname) returncode = 0 stdout = "" diff --git a/aider/utils.py b/aider/utils.py index c6773f140..8ab8184a3 100644 --- a/aider/utils.py +++ b/aider/utils.py @@ -1,7 +1,7 @@ import itertools import os import platform -import shlex +import oslex import subprocess import sys import tempfile @@ -384,10 +384,7 @@ def printable_shell_command(cmd_list): Returns: str: Shell-escaped command string. """ - if platform.system() == "Windows": - return subprocess.list2cmdline(cmd_list) - else: - return shlex.join(cmd_list) + return oslex.join(cmd_list) def main(): diff --git a/requirements.txt b/requirements.txt index 44dbe2956..62832718b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -184,6 +184,8 @@ monotonic==1.6 # via # -c requirements/common-constraints.txt # posthog +mslex==1.3.0 + # via oslex multidict==6.4.3 # via # -c requirements/common-constraints.txt @@ -202,6 +204,8 @@ openai==1.73.0 # via # -c requirements/common-constraints.txt # litellm +oslex==0.1.3 + # via -r requirements/requirements.in packaging==24.2 # via # -c requirements/common-constraints.txt @@ -423,6 +427,6 @@ zipp==3.21.0 # via # -c requirements/common-constraints.txt # importlib-metadata - + tree-sitter==0.23.2; python_version < "3.10" tree-sitter==0.24.0; python_version >= "3.10" diff --git a/requirements/requirements.in b/requirements/requirements.in index 101f16988..5d75f3fa7 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -28,6 +28,7 @@ watchfiles socksio pip pillow +oslex # The proper dependency is networkx[default], but this brings # in matplotlib and a bunch of other deps diff --git a/tests/basic/test_linter.py b/tests/basic/test_linter.py index ace4a9311..60132b565 100644 --- a/tests/basic/test_linter.py +++ b/tests/basic/test_linter.py @@ -43,7 +43,7 @@ class TestLinter(unittest.TestCase): from pathlib import Path root = Path(__file__).parent.parent.parent.absolute().as_posix() linter = Linter(encoding="utf-8", root=root) - result = linter.run_cmd("dir", "tests/basic", "code") + result = linter.run_cmd("dir", "tests\\basic", "code") self.assertIsNone(result) @patch("subprocess.Popen") From 8ffe4662571ffdcebd3ac62cab1833e4a3cad888 Mon Sep 17 00:00:00 2001 From: Titusz Pan Date: Wed, 23 Apr 2025 14:40:43 +0200 Subject: [PATCH 4/4] Replace shlex with cross-platform oslex - fixes Aider-AI/aider#3746 --- .github/workflows/windows-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml index 78fb1f3b7..21799563e 100644 --- a/.github/workflows/windows-tests.yml +++ b/.github/workflows/windows-tests.yml @@ -8,6 +8,8 @@ on: - 'HISTORY.md' - '.github/workflows/*' - '!.github/workflows/windows-tests.yml' + branches: + - main pull_request: paths-ignore: - 'aider/website/**'