Skip to content

Test Python 3.15#853

Open
hugovk wants to merge 3 commits into
mesonbuild:mainfrom
hugovk:release-add-3.15
Open

Test Python 3.15#853
hugovk wants to merge 3 commits into
mesonbuild:mainfrom
hugovk:release-add-3.15

Conversation

@hugovk

@hugovk hugovk commented Jun 17, 2026

Copy link
Copy Markdown

Python 3.15 is now in beta, so it's time to start testing:

We strongly encourage maintainers of third-party Python projects to test with 3.15 during the beta phase and report issues found to the Python bug tracker as soon as possible. While the release is planned to be feature-complete entering the beta phase, it is possible that features may be modified or, in rare cases, removed up until the start of the release candidate phase (2026-08-04). Our goal is to have no ABI changes after beta 4 and as few code changes as possible after the first release candidate. To achieve that, it will be extremely important to get as much exposure for 3.15 as possible during the beta phase.

https://discuss.python.org/t/python-3-15-0-beta-2-is-here/107610

This is especially important for foundational projects such as meson-python, so libraries know they can use it for their own 3.15 testing.


Also bump GitHub Actions.

@rgommers

Copy link
Copy Markdown
Contributor

Thanks @hugovk! Quick question: did an existing test case for symlinks fail for you on Windows py3.15?

@rgommers rgommers added the CI Continuous Integration label Jun 17, 2026
@rgommers rgommers added this to the v0.21.0 milestone Jun 17, 2026
@hugovk

hugovk commented Jun 17, 2026

Copy link
Copy Markdown
Author

Yes, you can see it here:

________________________________ test_symlinks ________________________________

tmp_path = WindowsPath('C:/Users/runneradmin/AppData/Local/Temp/pytest-of-runneradmin/pytest-0/test_symlinks0')
sdist_symlinks = WindowsPath('C:/Users/runneradmin/AppData/Local/Temp/pytest-of-runneradmin/pytest-0/test0/mesonpy-test-hklax70z/symlinks-1.0.0.tar.gz')

    @pytest.mark.skipif(sys.version_info >= (3, 14) and MESON_VERSION < (1, 9, 2), reason='incompatible Python version')
    @pytest.mark.filterwarnings('ignore:symbolic link')
    def test_symlinks(tmp_path, sdist_symlinks):
        with tarfile.open(sdist_symlinks, 'r:gz') as sdist:
            names = {member.name for member in sdist.getmembers()}
            mtimes = {member.mtime for member in sdist.getmembers()}
    
        # Check that the symlinks `baz.py` and `qux.py` pointing outside the
        # source tree are not included. These files are present in the
        # meson-python git repository but cannot be included in the meson-python
        # sdist. Thus this test is effective only when run from a git checkout.
>       assert names == {
            'symlinks-1.0.0/PKG-INFO',
            'symlinks-1.0.0/meson.build',
            'symlinks-1.0.0/pyproject.toml',
            'symlinks-1.0.0/__init__.py',
            'symlinks-1.0.0/submodule/__init__.py',
            'symlinks-1.0.0/submodule/aaa.py',
            'symlinks-1.0.0/submodule/bbb.py',
        }
E       AssertionError: assert {'symlinks-1.0.0/meson.build', 'symlinks-1.0.0/PKG-INFO', 'symlinks-1.0.0/submodule/bbb.py', 'symlinks-1.0.0/__init__.py', 'symlinks-1.0.0/submodule/aaa.py', 'symlinks-1.0.0/pyproject.toml'} == {'symlinks-1.0.0/submodule/aaa.py', 'symlinks-1.0.0/pyproject.toml', 'symlinks-1.0.0/meson.build', 'symlinks-1.0.0/PKG-INFO', 'symlinks-1.0.0/submodule/bbb.py', 'symlinks-1.0.0/submodule/__init__.py', 'symlinks-1.0.0/__init__.py'}
E         
E         Extra items in the right set:
E         'symlinks-1.0.0/submodule/__init__.py'
E         
E         Full diff:
E           {
E               'symlinks-1.0.0/PKG-INFO',
E               'symlinks-1.0.0/__init__.py',
E               'symlinks-1.0.0/meson.build',
E               'symlinks-1.0.0/pyproject.toml',
E         -     'symlinks-1.0.0/submodule/__init__.py',
E               'symlinks-1.0.0/submodule/aaa.py',
E               'symlinks-1.0.0/submodule/bbb.py',
E           }

mtimes     = {1781692825.0}
names      = {'symlinks-1.0.0/PKG-INFO',
 'symlinks-1.0.0/__init__.py',
 'symlinks-1.0.0/meson.build',
 'symlinks-1.0.0/pyproject.toml',
 'symlinks-1.0.0/submodule/aaa.py',
 'symlinks-1.0.0/submodule/bbb.py'}
sdist      = <tarfile.TarFile object at 0x000002857D733410>
sdist_symlinks = WindowsPath('C:/Users/runneradmin/AppData/Local/Temp/pytest-of-runneradmin/pytest-0/test0/mesonpy-test-hklax70z/symlinks-1.0.0.tar.gz')
tmp_path   = WindowsPath('C:/Users/runneradmin/AppData/Local/Temp/pytest-of-runneradmin/pytest-0/test_symlinks0')

tests\test_sdist.py:235: AssertionError
---------------------------- Captured stdout setup ----------------------------
Initialized empty Git repository in D:/a/meson-python/meson-python/tests/packages/symlinks/.git/
+ meson setup D:\a\meson-python\meson-python\tests\packages\symlinks D:\a\meson-python\meson-python\tests\packages\symlinks\.mesonpy-3wrsh3w8 -Dbuildtype=release -Db_ndebug=if-release -Db_vscrt=md --fatal-meson-warnings --native-file=D:\a\meson-python\meson-python\tests\packages\symlinks\.mesonpy-3wrsh3w8\meson-python-native-file.ini
The Meson build system

Version: 1.11.1

Source dir: D:\a\meson-python\meson-python\tests\packages\symlinks

Build dir: D:\a\meson-python\meson-python\tests\packages\symlinks\.mesonpy-3wrsh3w8

Build type: native build

Project name: symlinks

Project version: undefined

Host machine cpu family: x86_64

Host machine cpu: x86_64

Program python found: YES (C:\hostedtoolcache\windows\Python\3.15.0-beta.2\x64\python.exe)

Build targets in project: 0



symlinks undefined



  User defined options

    Native files: D:\a\meson-python\meson-python\tests\packages\symlinks\.mesonpy-3wrsh3w8\meson-python-native-file.ini

    b_ndebug    : if-release

    b_vscrt     : md

    buildtype   : release



Found ninja.EXE-1.13.0.git.kitware.jobserver-pipe-1 at C:\hostedtoolcache\windows\Python\3.15.0-beta.2\x64\Scripts\ninja.EXE

+ meson dist --allow-dirty --no-tests --formats gztar
Created D:\a\meson-python\meson-python\tests\packages\symlinks\.mesonpy-3wrsh3w8\meson-dist\symlinks-undefined.tar.gz

https://github.com/hugovk/meson-python/actions/runs/27682956779/job/81874680435

(I had to "hack" my feature branch name as release-add-3.15 to work around the annoying branch restrictions to run CI on my fork...)

Comment thread mesonpy/__init__.py
name = member.name
target = posixpath.normpath(posixpath.join(posixpath.dirname(member.name), member.linkname))
# Normalize the link target to use forward slashes. On
# Windows on Python 3.15 rewrites slashes to backslashes in

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Windows on Python 3.15 rewrites slashes to backslashes in
# Windows, Python 3.15 rewrites slashes to backslashes in

Comment thread mesonpy/__init__.py
Comment on lines +1044 to +1045
# CPython gh-57911), and Meson propagates these backslashed
# targets into the dist tarball. Without this normalization

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this sentence means. I understand that Python forces \ as path separator on Windows when reading a tar archive. What does it mean that Meson "propagates these backward slashed targets into the dist tarball"? Python would return link targets using the\ path separator regardless. Also, AFAIK the only path separator for tar archives is /. Are you saying that Python 3.15 converts / to \ when reading a tar archive on Windows, but it does not do the opposite when writing it? This would be a bug in CPython.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't understand the rationale in changing the path separator on Windows for link targets but not for regular file paths.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This python/cpython@c1a9c23 seems the commit that should have changed the behavior of the tarfile`` module. However, there only tarfile.TarFile.extractis modified to change the path separators. Here we don't useextract()butgetmembers()` thus I don't understand where the back slashes would be coming from.

Comment thread mesonpy/__init__.py
# targets into the dist tarball. Without this normalization
# the ``posixpath`` resolution below would fail to match the
# link target, dropping links that point inside the archive.
linkname = member.linkname.replace('\\', '/')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\ is a valid filename character on Unix systems. The replace cannot be done unconditionally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI Continuous Integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants