From 33a5e22f181515d423da62d9d138811d70ea75ff Mon Sep 17 00:00:00 2001 From: jad-fahmi Date: Sun, 27 Sep 2026 21:19:04 +0800 Subject: [PATCH 1/6] BUG: check package splits after expanding install directories --- mesonpy/__init__.py | 26 +++++++++++++------------- tests/test_wheel.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index 928d8acb0..76305c77d 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -146,7 +146,6 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], exclude: List[str], include: List[str]) -> DefaultDict[str, List[_Entry]]: """Map files to the wheel, organized by wheel installation directory.""" wheel_files: DefaultDict[str, List[_Entry]] = collections.defaultdict(list) - packages: Dict[str, str] = {} excluded = _compile_patterns(exclude) included = _compile_patterns(include) @@ -165,18 +164,6 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], if path is None: raise BuildError(f'Could not map installation path to an equivalent wheel directory: {str(destination)!r}') - if path == 'purelib' or path == 'platlib': - package = destination.parts[1] - other = packages.setdefault(package, path) - if other != path: - this = os.fspath(pathlib.Path(path, *destination.parts[1:])) - module = next(entry.dst for entry in wheel_files[other] if entry.dst.parts[0] == destination.parts[1]) - that = os.fspath(other / module) - raise BuildError( - f'The {package} package is split between {path} and {other}: ' - f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' - f'It is recommended to set it in "import(\'python\').find_installation()"') - if key == 'install_subdirs' or key == 'targets' and os.path.isdir(src): exclude_files = {os.path.normpath(x) for x in target.get('exclude_files', [])} exclude_dirs = {os.path.normpath(x) for x in target.get('exclude_dirs', [])} @@ -208,6 +195,19 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], wheel_files[path].append(_Entry(dst, src, install_rpath, build_rpath)) + packages: Dict[str, Tuple[str, pathlib.Path]] = {} + for path in ('purelib', 'platlib'): + for entry in wheel_files.get(path, []): + package = entry.dst.parts[0] + other, module = packages.setdefault(package, (path, entry.dst)) + if other != path: + this = os.fspath(path / entry.dst) + that = os.fspath(other / module) + raise BuildError( + f'The {package} package is split between {path} and {other}: ' + f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' + f'It is recommended to set it in "import(\'python\').find_installation()"') + return wheel_files diff --git a/tests/test_wheel.py b/tests/test_wheel.py index a7cb150dc..883a6fe05 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -371,6 +371,38 @@ def test_purelib_platlib_split(package_purelib_platlib_split, tmp_path): project.wheel(tmp_path) +@pytest.mark.skipif(MESON_VERSION < (1, 2, 0), reason='meson too old to report excluded files') +@pytest.mark.parametrize('empty_first', [True, False]) +def test_purelib_platlib_empty_subdir(tmp_path, empty_first): + source = tmp_path / 'src' + source.mkdir() + (source / 'pyproject.toml').write_text('') + for name in ('excluded', 'included'): + (source / name).mkdir() + (source / name / 'module.py').write_text('value = 42\n') + installs = [ + "install_subdir('excluded', strip_directory: true, exclude_files: 'module.py', " + "install_dir: py.get_install_dir(pure: true) / 'example')", + "install_subdir('included', strip_directory: true, " + "install_dir: py.get_install_dir(pure: false) / 'example')", + ] + if not empty_first: + installs.reverse() + (source / 'meson.build').write_text( + "project('empty-subdir', version: '1.0')\n" + "py = import('python').find_installation()\n" + '\n'.join(installs)) + + project = mesonpy.Project(source, tmp_path / 'build') + filename = project.wheel(tmp_path) + artifact = wheel.wheelfile.WheelFile(tmp_path / filename) + assert wheel_contents(artifact) == { + 'empty_subdir-1.0.dist-info/METADATA', + 'empty_subdir-1.0.dist-info/RECORD', + 'empty_subdir-1.0.dist-info/WHEEL', + 'example/module.py', + } + + @pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test') @pytest.mark.parametrize('arch', ['x86_64', 'arm64']) def test_archflags_envvar(package_purelib_and_platlib, monkeypatch, tmp_path, arch): From b411038cb1862741a66c20842cb5aa68b9dbcbf5 Mon Sep 17 00:00:00 2001 From: jad-fahmi Date: Mon, 28 Sep 2026 04:12:38 +0800 Subject: [PATCH 2/6] BUG: compare platlib packages against purelib entries --- mesonpy/__init__.py | 22 ++++++------- .../purelib-platlib-split/meson.build | 16 ++++++---- .../purelib-platlib-split/meson_options.txt | 5 +++ .../purelib-platlib-split/{ => plat}/plat.py | 0 .../purelib-platlib-split/{ => pure}/pure.py | 0 tests/test_wheel.py | 32 ++++--------------- 6 files changed, 30 insertions(+), 45 deletions(-) create mode 100644 tests/packages/purelib-platlib-split/meson_options.txt rename tests/packages/purelib-platlib-split/{ => plat}/plat.py (100%) rename tests/packages/purelib-platlib-split/{ => pure}/pure.py (100%) diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index 76305c77d..50db30b9b 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -195,18 +195,16 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], wheel_files[path].append(_Entry(dst, src, install_rpath, build_rpath)) - packages: Dict[str, Tuple[str, pathlib.Path]] = {} - for path in ('purelib', 'platlib'): - for entry in wheel_files.get(path, []): - package = entry.dst.parts[0] - other, module = packages.setdefault(package, (path, entry.dst)) - if other != path: - this = os.fspath(path / entry.dst) - that = os.fspath(other / module) - raise BuildError( - f'The {package} package is split between {path} and {other}: ' - f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' - f'It is recommended to set it in "import(\'python\').find_installation()"') + purelib = {entry.dst.parts[0]: entry.dst for entry in wheel_files.get('purelib', [])} + for entry in wheel_files.get('platlib', []): + package = entry.dst.parts[0] + if package in purelib: + this = os.fspath('platlib' / entry.dst) + that = os.fspath('purelib' / purelib[package]) + raise BuildError( + f'The {package} package is split between platlib and purelib: ' + f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' + f'It is recommended to set it in "import(\'python\').find_installation()"') return wheel_files diff --git a/tests/packages/purelib-platlib-split/meson.build b/tests/packages/purelib-platlib-split/meson.build index 071d79d57..7db7a04bb 100644 --- a/tests/packages/purelib-platlib-split/meson.build +++ b/tests/packages/purelib-platlib-split/meson.build @@ -6,13 +6,15 @@ project('purelib-platlib-split', version: '1.0.0') py = import('python').find_installation() -py.install_sources( - 'pure.py', - subdir: 'purelib-platlib-split', +install_subdir( + 'pure', + strip_directory: true, + exclude_files: get_option('empty') ? ['pure.py'] : [], + install_dir: py.get_install_dir() / 'purelib-platlib-split', ) -py.install_sources( - 'plat.py', - subdir: 'purelib-platlib-split', - pure: false, +install_subdir( + 'plat', + strip_directory: true, + install_dir: py.get_install_dir(pure: false) / 'purelib-platlib-split', ) diff --git a/tests/packages/purelib-platlib-split/meson_options.txt b/tests/packages/purelib-platlib-split/meson_options.txt new file mode 100644 index 000000000..ba647f704 --- /dev/null +++ b/tests/packages/purelib-platlib-split/meson_options.txt @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2026 The meson-python developers +# +# SPDX-License-Identifier: MIT + +option('empty', type: 'boolean', value: false) diff --git a/tests/packages/purelib-platlib-split/plat.py b/tests/packages/purelib-platlib-split/plat/plat.py similarity index 100% rename from tests/packages/purelib-platlib-split/plat.py rename to tests/packages/purelib-platlib-split/plat/plat.py diff --git a/tests/packages/purelib-platlib-split/pure.py b/tests/packages/purelib-platlib-split/pure/pure.py similarity index 100% rename from tests/packages/purelib-platlib-split/pure.py rename to tests/packages/purelib-platlib-split/pure/pure.py diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 883a6fe05..5ca3cbc31 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -372,34 +372,14 @@ def test_purelib_platlib_split(package_purelib_platlib_split, tmp_path): @pytest.mark.skipif(MESON_VERSION < (1, 2, 0), reason='meson too old to report excluded files') -@pytest.mark.parametrize('empty_first', [True, False]) -def test_purelib_platlib_empty_subdir(tmp_path, empty_first): - source = tmp_path / 'src' - source.mkdir() - (source / 'pyproject.toml').write_text('') - for name in ('excluded', 'included'): - (source / name).mkdir() - (source / name / 'module.py').write_text('value = 42\n') - installs = [ - "install_subdir('excluded', strip_directory: true, exclude_files: 'module.py', " - "install_dir: py.get_install_dir(pure: true) / 'example')", - "install_subdir('included', strip_directory: true, " - "install_dir: py.get_install_dir(pure: false) / 'example')", - ] - if not empty_first: - installs.reverse() - (source / 'meson.build').write_text( - "project('empty-subdir', version: '1.0')\n" - "py = import('python').find_installation()\n" + '\n'.join(installs)) - - project = mesonpy.Project(source, tmp_path / 'build') - filename = project.wheel(tmp_path) +def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path): + filename = mesonpy.build_wheel(tmp_path, {'setup-args': ['-Dempty=true']}) artifact = wheel.wheelfile.WheelFile(tmp_path / filename) assert wheel_contents(artifact) == { - 'empty_subdir-1.0.dist-info/METADATA', - 'empty_subdir-1.0.dist-info/RECORD', - 'empty_subdir-1.0.dist-info/WHEEL', - 'example/module.py', + 'purelib_platlib_split-1.0.0.dist-info/METADATA', + 'purelib_platlib_split-1.0.0.dist-info/RECORD', + 'purelib_platlib_split-1.0.0.dist-info/WHEEL', + 'purelib-platlib-split/plat.py', } From 7eb8bb2a73249919a7e8fc3572adf8346c55ef4f Mon Sep 17 00:00:00 2001 From: jad-fahmi Date: Mon, 28 Sep 2026 04:30:54 +0800 Subject: [PATCH 3/6] BUG: preserve split-package errors for empty install directories --- mesonpy/__init__.py | 25 ++++++++++++++----------- tests/test_wheel.py | 11 +++-------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index 50db30b9b..f02750912 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -146,6 +146,7 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], exclude: List[str], include: List[str]) -> DefaultDict[str, List[_Entry]]: """Map files to the wheel, organized by wheel installation directory.""" wheel_files: DefaultDict[str, List[_Entry]] = collections.defaultdict(list) + packages: Dict[str, str] = {} excluded = _compile_patterns(exclude) included = _compile_patterns(include) @@ -164,6 +165,19 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], if path is None: raise BuildError(f'Could not map installation path to an equivalent wheel directory: {str(destination)!r}') + if path == 'purelib' or path == 'platlib': + package = destination.parts[1] + other = packages.setdefault(package, path) + if other != path: + this = os.fspath(pathlib.Path(path, *destination.parts[1:])) + module = next((entry.dst for entry in wheel_files[other] if entry.dst.parts[0] == destination.parts[1]), + pathlib.Path(package)) + that = os.fspath(other / module) + raise BuildError( + f'The {package} package is split between {path} and {other}: ' + f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' + f'It is recommended to set it in "import(\'python\').find_installation()"') + if key == 'install_subdirs' or key == 'targets' and os.path.isdir(src): exclude_files = {os.path.normpath(x) for x in target.get('exclude_files', [])} exclude_dirs = {os.path.normpath(x) for x in target.get('exclude_dirs', [])} @@ -195,17 +209,6 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], wheel_files[path].append(_Entry(dst, src, install_rpath, build_rpath)) - purelib = {entry.dst.parts[0]: entry.dst for entry in wheel_files.get('purelib', [])} - for entry in wheel_files.get('platlib', []): - package = entry.dst.parts[0] - if package in purelib: - this = os.fspath('platlib' / entry.dst) - that = os.fspath('purelib' / purelib[package]) - raise BuildError( - f'The {package} package is split between platlib and purelib: ' - f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' - f'It is recommended to set it in "import(\'python\').find_installation()"') - return wheel_files diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 5ca3cbc31..a550dc26a 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -373,14 +373,9 @@ def test_purelib_platlib_split(package_purelib_platlib_split, tmp_path): @pytest.mark.skipif(MESON_VERSION < (1, 2, 0), reason='meson too old to report excluded files') def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path): - filename = mesonpy.build_wheel(tmp_path, {'setup-args': ['-Dempty=true']}) - artifact = wheel.wheelfile.WheelFile(tmp_path / filename) - assert wheel_contents(artifact) == { - 'purelib_platlib_split-1.0.0.dist-info/METADATA', - 'purelib_platlib_split-1.0.0.dist-info/RECORD', - 'purelib_platlib_split-1.0.0.dist-info/WHEEL', - 'purelib-platlib-split/plat.py', - } + with pytest.raises(mesonpy.BuildError, match='The purelib-platlib-split package is split'): + with mesonpy._project({'setup-args': ['-Dempty=true']}) as project: + project.wheel(tmp_path) @pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test') From a51e36231a5f29d9bf52531d865619ad98239eb8 Mon Sep 17 00:00:00 2001 From: jad-fahmi Date: Mon, 28 Sep 2026 09:34:56 +0800 Subject: [PATCH 4/6] BUG: ignore empty directories when checking package splits --- mesonpy/__init__.py | 25 ++++++++----------- .../purelib-platlib-split/meson.build | 3 ++- .../purelib-platlib-split/meson_options.txt | 2 +- tests/test_wheel.py | 14 ++++++++--- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index f02750912..50db30b9b 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -146,7 +146,6 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], exclude: List[str], include: List[str]) -> DefaultDict[str, List[_Entry]]: """Map files to the wheel, organized by wheel installation directory.""" wheel_files: DefaultDict[str, List[_Entry]] = collections.defaultdict(list) - packages: Dict[str, str] = {} excluded = _compile_patterns(exclude) included = _compile_patterns(include) @@ -165,19 +164,6 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], if path is None: raise BuildError(f'Could not map installation path to an equivalent wheel directory: {str(destination)!r}') - if path == 'purelib' or path == 'platlib': - package = destination.parts[1] - other = packages.setdefault(package, path) - if other != path: - this = os.fspath(pathlib.Path(path, *destination.parts[1:])) - module = next((entry.dst for entry in wheel_files[other] if entry.dst.parts[0] == destination.parts[1]), - pathlib.Path(package)) - that = os.fspath(other / module) - raise BuildError( - f'The {package} package is split between {path} and {other}: ' - f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' - f'It is recommended to set it in "import(\'python\').find_installation()"') - if key == 'install_subdirs' or key == 'targets' and os.path.isdir(src): exclude_files = {os.path.normpath(x) for x in target.get('exclude_files', [])} exclude_dirs = {os.path.normpath(x) for x in target.get('exclude_dirs', [])} @@ -209,6 +195,17 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], wheel_files[path].append(_Entry(dst, src, install_rpath, build_rpath)) + purelib = {entry.dst.parts[0]: entry.dst for entry in wheel_files.get('purelib', [])} + for entry in wheel_files.get('platlib', []): + package = entry.dst.parts[0] + if package in purelib: + this = os.fspath('platlib' / entry.dst) + that = os.fspath('purelib' / purelib[package]) + raise BuildError( + f'The {package} package is split between platlib and purelib: ' + f'{this!r} and {that!r}, a "pure: false" argument may be missing in meson.build. ' + f'It is recommended to set it in "import(\'python\').find_installation()"') + return wheel_files diff --git a/tests/packages/purelib-platlib-split/meson.build b/tests/packages/purelib-platlib-split/meson.build index 7db7a04bb..ad7b0f779 100644 --- a/tests/packages/purelib-platlib-split/meson.build +++ b/tests/packages/purelib-platlib-split/meson.build @@ -9,12 +9,13 @@ py = import('python').find_installation() install_subdir( 'pure', strip_directory: true, - exclude_files: get_option('empty') ? ['pure.py'] : [], + exclude_files: get_option('empty') == 'pure' ? ['pure.py'] : [], install_dir: py.get_install_dir() / 'purelib-platlib-split', ) install_subdir( 'plat', strip_directory: true, + exclude_files: get_option('empty') == 'plat' ? ['plat.py'] : [], install_dir: py.get_install_dir(pure: false) / 'purelib-platlib-split', ) diff --git a/tests/packages/purelib-platlib-split/meson_options.txt b/tests/packages/purelib-platlib-split/meson_options.txt index ba647f704..2e096010e 100644 --- a/tests/packages/purelib-platlib-split/meson_options.txt +++ b/tests/packages/purelib-platlib-split/meson_options.txt @@ -2,4 +2,4 @@ # # SPDX-License-Identifier: MIT -option('empty', type: 'boolean', value: false) +option('empty', type: 'combo', choices: ['none', 'pure', 'plat'], value: 'none') diff --git a/tests/test_wheel.py b/tests/test_wheel.py index a550dc26a..c3cb622eb 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -372,10 +372,16 @@ def test_purelib_platlib_split(package_purelib_platlib_split, tmp_path): @pytest.mark.skipif(MESON_VERSION < (1, 2, 0), reason='meson too old to report excluded files') -def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path): - with pytest.raises(mesonpy.BuildError, match='The purelib-platlib-split package is split'): - with mesonpy._project({'setup-args': ['-Dempty=true']}) as project: - project.wheel(tmp_path) +@pytest.mark.parametrize('empty', ['pure', 'plat']) +def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path, empty): + filename = mesonpy.build_wheel(tmp_path, {'setup-args': [f'-Dempty={empty}']}) + artifact = wheel.wheelfile.WheelFile(tmp_path / filename) + assert wheel_contents(artifact) == { + 'purelib_platlib_split-1.0.0.dist-info/METADATA', + 'purelib_platlib_split-1.0.0.dist-info/RECORD', + 'purelib_platlib_split-1.0.0.dist-info/WHEEL', + f'purelib-platlib-split/{"plat" if empty == "pure" else "pure"}.py', + } @pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test') From 34fcc4f7ed807030337f3f6b7dd369aadedc11d5 Mon Sep 17 00:00:00 2001 From: jad-fahmi Date: Mon, 28 Sep 2026 09:45:38 +0800 Subject: [PATCH 5/6] TST: limit empty-directory regression to purelib --- tests/packages/purelib-platlib-split/meson.build | 11 +++++------ .../packages/purelib-platlib-split/meson_options.txt | 2 +- .../packages/purelib-platlib-split/{plat => }/plat.py | 0 tests/test_wheel.py | 7 +++---- 4 files changed, 9 insertions(+), 11 deletions(-) rename tests/packages/purelib-platlib-split/{plat => }/plat.py (100%) diff --git a/tests/packages/purelib-platlib-split/meson.build b/tests/packages/purelib-platlib-split/meson.build index ad7b0f779..31e2e2bcc 100644 --- a/tests/packages/purelib-platlib-split/meson.build +++ b/tests/packages/purelib-platlib-split/meson.build @@ -9,13 +9,12 @@ py = import('python').find_installation() install_subdir( 'pure', strip_directory: true, - exclude_files: get_option('empty') == 'pure' ? ['pure.py'] : [], + exclude_files: get_option('empty') ? ['pure.py'] : [], install_dir: py.get_install_dir() / 'purelib-platlib-split', ) -install_subdir( - 'plat', - strip_directory: true, - exclude_files: get_option('empty') == 'plat' ? ['plat.py'] : [], - install_dir: py.get_install_dir(pure: false) / 'purelib-platlib-split', +py.install_sources( + 'plat.py', + subdir: 'purelib-platlib-split', + pure: false, ) diff --git a/tests/packages/purelib-platlib-split/meson_options.txt b/tests/packages/purelib-platlib-split/meson_options.txt index 2e096010e..ba647f704 100644 --- a/tests/packages/purelib-platlib-split/meson_options.txt +++ b/tests/packages/purelib-platlib-split/meson_options.txt @@ -2,4 +2,4 @@ # # SPDX-License-Identifier: MIT -option('empty', type: 'combo', choices: ['none', 'pure', 'plat'], value: 'none') +option('empty', type: 'boolean', value: false) diff --git a/tests/packages/purelib-platlib-split/plat/plat.py b/tests/packages/purelib-platlib-split/plat.py similarity index 100% rename from tests/packages/purelib-platlib-split/plat/plat.py rename to tests/packages/purelib-platlib-split/plat.py diff --git a/tests/test_wheel.py b/tests/test_wheel.py index c3cb622eb..5ca3cbc31 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -372,15 +372,14 @@ def test_purelib_platlib_split(package_purelib_platlib_split, tmp_path): @pytest.mark.skipif(MESON_VERSION < (1, 2, 0), reason='meson too old to report excluded files') -@pytest.mark.parametrize('empty', ['pure', 'plat']) -def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path, empty): - filename = mesonpy.build_wheel(tmp_path, {'setup-args': [f'-Dempty={empty}']}) +def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path): + filename = mesonpy.build_wheel(tmp_path, {'setup-args': ['-Dempty=true']}) artifact = wheel.wheelfile.WheelFile(tmp_path / filename) assert wheel_contents(artifact) == { 'purelib_platlib_split-1.0.0.dist-info/METADATA', 'purelib_platlib_split-1.0.0.dist-info/RECORD', 'purelib_platlib_split-1.0.0.dist-info/WHEEL', - f'purelib-platlib-split/{"plat" if empty == "pure" else "pure"}.py', + 'purelib-platlib-split/plat.py', } From a5efc621d6c278ffb7151d75d8e000a454a45e0f Mon Sep 17 00:00:00 2001 From: jad-fahmi Date: Mon, 28 Sep 2026 09:57:16 +0800 Subject: [PATCH 6/6] TST: preserve install-plan order in empty-directory regression Meson lists install_sources() entries before install_subdir() entries. Use install_subdir() for platlib so the empty purelib entry is visited first and the test reproduces the StopIteration reported in #869. Run the regression from Meson 1.1, which already reports exclusions. --- tests/packages/purelib-platlib-split/meson.build | 9 +++++---- tests/packages/purelib-platlib-split/{ => plat}/plat.py | 0 tests/test_wheel.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) rename tests/packages/purelib-platlib-split/{ => plat}/plat.py (100%) diff --git a/tests/packages/purelib-platlib-split/meson.build b/tests/packages/purelib-platlib-split/meson.build index 31e2e2bcc..48529bc2b 100644 --- a/tests/packages/purelib-platlib-split/meson.build +++ b/tests/packages/purelib-platlib-split/meson.build @@ -13,8 +13,9 @@ install_subdir( install_dir: py.get_install_dir() / 'purelib-platlib-split', ) -py.install_sources( - 'plat.py', - subdir: 'purelib-platlib-split', - pure: false, +# Use install_subdir() so this entry follows purelib in the install plan. +install_subdir( + 'plat', + strip_directory: true, + install_dir: py.get_install_dir(pure: false) / 'purelib-platlib-split', ) diff --git a/tests/packages/purelib-platlib-split/plat.py b/tests/packages/purelib-platlib-split/plat/plat.py similarity index 100% rename from tests/packages/purelib-platlib-split/plat.py rename to tests/packages/purelib-platlib-split/plat/plat.py diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 5ca3cbc31..e9272d129 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -371,7 +371,7 @@ def test_purelib_platlib_split(package_purelib_platlib_split, tmp_path): project.wheel(tmp_path) -@pytest.mark.skipif(MESON_VERSION < (1, 2, 0), reason='meson too old to report excluded files') +@pytest.mark.skipif(MESON_VERSION < (1, 1, 0), reason='meson too old to report excluded files') def test_purelib_platlib_empty_subdir(package_purelib_platlib_split, tmp_path): filename = mesonpy.build_wheel(tmp_path, {'setup-args': ['-Dempty=true']}) artifact = wheel.wheelfile.WheelFile(tmp_path / filename)