From 28f777d2c30362b453a00c055b35ebbd0024b81b Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 10 Feb 2026 19:14:12 +0100 Subject: [PATCH 1/8] CI: update MSYS2 packages before running tests Otherwise it installs the packages present at the time the installer was releases, which for some reason was broken the last time. Enable updates so the newest versions are used. --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 621334c2..dde08214 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -147,6 +147,7 @@ jobs: - uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.sys}} + update: true install: | mingw-w64-${{matrix.env}}-toolchain mingw-w64-${{matrix.env}}-python From ddbcfd617e162d8136462ebcffd2ebe4bfdc2529 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 10 Feb 2026 19:27:49 +0100 Subject: [PATCH 2/8] tests: fix test_glob_to_re with Python 3.14 Upstream changed from \Z to \z in https://github.com/python/cpython/commit/add0ca9ea00ab02fd3a58d059e8370c2d0a1d32c --- distutils/tests/test_filelist.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/distutils/tests/test_filelist.py b/distutils/tests/test_filelist.py index 130e6fb5..765b0a89 100644 --- a/distutils/tests/test_filelist.py +++ b/distutils/tests/test_filelist.py @@ -3,6 +3,7 @@ import logging import os import re +import sys from distutils import debug, filelist from distutils.errors import DistutilsTemplateError from distutils.filelist import FileList, glob_to_re, translate_pattern @@ -49,18 +50,21 @@ def test_glob_to_re(self): if os.sep == '\\': sep = re.escape(os.sep) + # https://docs.python.org/3/whatsnew/3.14.html#re + end = r"\z" if sys.version_info >= (3, 14) else r"\Z" + for glob, regex in ( # simple cases - ('foo*', r'(?s:foo[^%(sep)s]*)\Z'), - ('foo?', r'(?s:foo[^%(sep)s])\Z'), - ('foo??', r'(?s:foo[^%(sep)s][^%(sep)s])\Z'), + ('foo*', r'(?s:foo[^%(sep)s]*)%(end)s'), + ('foo?', r'(?s:foo[^%(sep)s])%(end)s'), + ('foo??', r'(?s:foo[^%(sep)s][^%(sep)s])%(end)s'), # special cases - (r'foo\\*', r'(?s:foo\\\\[^%(sep)s]*)\Z'), - (r'foo\\\*', r'(?s:foo\\\\\\[^%(sep)s]*)\Z'), - ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'), - (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z'), + (r'foo\\*', r'(?s:foo\\\\[^%(sep)s]*)%(end)s'), + (r'foo\\\*', r'(?s:foo\\\\\\[^%(sep)s]*)%(end)s'), + ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])%(end)s'), + (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])%(end)s'), ): - regex = regex % {'sep': sep} + regex = regex % {'sep': sep, 'end': end} assert glob_to_re(glob) == regex def test_process_template_line(self): From 766cc5ab455398b6a3b03e4e955efef04dd96aff Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 10 Feb 2026 19:30:43 +0100 Subject: [PATCH 3/8] tests: skip test_get_host_platform with mingw Python the platform strings are different there compared to the official CPython distributions, so just skip the test there. --- distutils/tests/test_util.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distutils/tests/test_util.py b/distutils/tests/test_util.py index 00c9743e..c053a153 100644 --- a/distutils/tests/test_util.py +++ b/distutils/tests/test_util.py @@ -20,6 +20,7 @@ get_host_platform, get_platform, grok_environment_error, + is_mingw, rfc822_escape, split_quoted, strtobool, @@ -42,6 +43,7 @@ def environment(monkeypatch): @pytest.mark.usefixtures('save_env') class TestUtil: + @pytest.mark.skipif(is_mingw(), reason="mingw has non-standard platform names") def test_get_host_platform(self): with mock.patch('os.name', 'nt'): with mock.patch('sys.version', '... [... (ARM64)]'): From 24363f47bf72dcca7a03cbea2baabf190b8c4da9 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 10 Feb 2026 20:11:18 +0100 Subject: [PATCH 4/8] tests: pin mypy and ruff to avoid CI breakage with newer versions Downgrade to a version which succeeds with the current code. This makes sure that new ruff/mypy releases don't break the CI. Feel free to fix things and update to newer versions. --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index b4a2fed8..2bf4c93d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,7 @@ doc = [ check = [ "pytest-checkdocs >= 2.14", "pytest-ruff >= 0.2.1; sys_platform != 'cygwin'", + "ruff == 0.13.3; sys_platform != 'cygwin'", ] cover = [ @@ -82,6 +83,7 @@ type = [ # Exclude PyPy from type checks (python/mypy#20454 jaraco/skeleton#187) "pytest-mypy >= 1.0.1; platform_python_implementation != 'PyPy'", + "mypy == 1.15.0", # local "types-docutils", From 7b5a796091718063ff009dff3d8642642f7c8d3c Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 17 Apr 2026 22:01:50 +0200 Subject: [PATCH 5/8] tests: force 3.9 as a ruff target for now 06da572c980b9b bumped the minimum Python version without fixing the resulting ruff errors. Target 3.9 again to keep CI green. --- ruff.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruff.toml b/ruff.toml index 06aa2304..fcc4cf0f 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,3 +1,5 @@ +target-version = "py39" + [lint] extend-select = [ # upstream From 00e41d2bfd39f683592cd72b69d1c964225fd2af Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 17 Apr 2026 22:09:04 +0200 Subject: [PATCH 6/8] CI: use Python 3.12 for Cygwin Now tha 3.9 is no longer supported. 3.12 is the next supported version in Cygwin. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dde08214..45cbe564 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -104,7 +104,7 @@ jobs: strategy: matrix: python: - - 39 + - 312 platform: - windows-latest runs-on: ${{ matrix.platform }} From bf0eb7a082406bff7c433ae08dcea4ffba9f5eb1 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 17 Apr 2026 22:17:26 +0200 Subject: [PATCH 7/8] CI: work around git permission warnings with cygwin Things fail with git introspection failed: fatal: detected dubious ownership in repository at '/cygdrive/d/a/distutils/distutils' I don't know what the real problem is, but just ignore permissions to get things green. --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 45cbe564..2f81af86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,7 +131,9 @@ jobs: python -m pip install tox - name: Run tests shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0} - run: python -m tox + run: | + git config --global --add safe.directory '*' + python -m tox test_msys2_mingw: strategy: From 174d6c358d591b4b376ea74fb3a56534df2941b5 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 17 Apr 2026 22:22:11 +0200 Subject: [PATCH 8/8] tests: fix test_get_host_platform with Python 3.15+ In https://github.com/python/cpython/commit/b9d43188e93967c3695e60f5ea6d8c2ca8a62c5d the logic was changed to no longer depend on sys.version for detecting the platform, so mocking it no longer works. Since get_host_platform() just forwards to sysconfig.get_platform(), there isn't much left to test, so just test that they return the same platform. --- distutils/tests/test_util.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/distutils/tests/test_util.py b/distutils/tests/test_util.py index c053a153..39d949cb 100644 --- a/distutils/tests/test_util.py +++ b/distutils/tests/test_util.py @@ -20,7 +20,6 @@ get_host_platform, get_platform, grok_environment_error, - is_mingw, rfc822_escape, split_quoted, strtobool, @@ -43,16 +42,8 @@ def environment(monkeypatch): @pytest.mark.usefixtures('save_env') class TestUtil: - @pytest.mark.skipif(is_mingw(), reason="mingw has non-standard platform names") def test_get_host_platform(self): - with mock.patch('os.name', 'nt'): - with mock.patch('sys.version', '... [... (ARM64)]'): - assert get_host_platform() == 'win-arm64' - with mock.patch('sys.version', '... [... (ARM)]'): - assert get_host_platform() == 'win-arm32' - - with mock.patch('sys.version_info', (3, 9, 0, 'final', 0)): - assert get_host_platform() == stdlib_sysconfig.get_platform() + assert get_host_platform() == stdlib_sysconfig.get_platform() def test_get_platform(self): with mock.patch('os.name', 'nt'):