Skip to content

EHN: add tool.meson-python.wheel.exclude setting #766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/reference/pyproject-settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ use them and examples.

Extra arguments to be passed to the ``meson install`` command.

.. option:: tool.meson-python.wheel.exclude

List of glob patterns matching paths of files that must be excluded from
the Python wheel. The accepted glob patterns are the ones implemented by
the Python :mod:`fnmatch` with case sensitive matching. The paths to be
matched are as they appear in the Meson introspection data, namely they are
rooted in one of the Meson install locations: ``{bindir}``, ``{datadir}``,
``{includedir}``, ``{libdir_shared}``, ``{libdir_static}``, et cetera.

This configuration setting is measure of last resort to exclude installed
files from a Python wheel. It is to be used when the project includes
subprojects that do not allow fine control on the installed files. Better
solutions include the use of Meson install tags and excluding subprojects
to be installed via :option:`tool.meson-python.args.install`.


__ https://docs.python.org/3/c-api/stable.html?highlight=limited%20api#stable-application-binary-interface
__ https://mesonbuild.com/Python-module.html#extension_module
Expand Down
25 changes: 23 additions & 2 deletions mesonpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import contextlib
import copy
import difflib
import fnmatch
import functools
import importlib.machinery
import io
Expand Down Expand Up @@ -111,13 +112,27 @@ class InvalidLicenseExpression(Exception): # type: ignore[no-redef]
}


def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]:
def _compile_patterns(patterns: List[str]) -> Callable[[str], bool]:
if not patterns:
return lambda x: False
func = re.compile('|'.join(fnmatch.translate(os.path.normpath(p)) for p in patterns)).match
return typing.cast('Callable[[str], bool]', func)


def _map_to_wheel(
sources: Dict[str, Dict[str, Any]],
exclude: List[str]
) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]:
"""Map files to the wheel, organized by wheel installation directory."""
wheel_files: DefaultDict[str, List[Tuple[pathlib.Path, str]]] = collections.defaultdict(list)
packages: Dict[str, str] = {}
excluded = _compile_patterns(exclude)

for key, group in sources.items():
for src, target in group.items():
if excluded(target['destination']):
continue

destination = pathlib.Path(target['destination'])
anchor = destination.parts[0]
dst = pathlib.Path(*destination.parts[1:])
Expand Down Expand Up @@ -581,6 +596,9 @@ def _string_or_path(value: Any, name: str) -> str:
'args': _table({
name: _strings for name in _MESON_ARGS_KEYS
}),
'wheel': _table({
'exclude': _strings,
}),
})

table = pyproject.get('tool', {}).get('meson-python', {})
Expand Down Expand Up @@ -823,6 +841,9 @@ def __init__(
# from the package, make sure the developers acknowledge this.
self._allow_windows_shared_libs = pyproject_config.get('allow-windows-internal-shared-libs', False)

# Files to be excluded from the wheel
self._excluded_files = pyproject_config.get('wheel', {}).get('exclude', [])

def _run(self, cmd: Sequence[str]) -> None:
"""Invoke a subprocess."""
# Flush the line to ensure that the log line with the executed
Expand Down Expand Up @@ -906,7 +927,7 @@ def _manifest(self) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]:
sources[key][target] = details

# Map Meson installation locations to wheel paths.
return _map_to_wheel(sources)
return _map_to_wheel(sources, self._excluded_files)

@property
def _meson_name(self) -> str:
Expand Down
5 changes: 5 additions & 0 deletions tests/packages/subproject/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
[build-system]
build-backend = 'mesonpy'
requires = ['meson-python']

[tool.meson-python.wheel]
# Meson versions before 1.3.0 install data files in {datadir}/{project name}/,
# later versions install in the more correct {datadir}/{dubproject name}/
exclude = ['{datadir}/*/data.txt']
1 change: 1 addition & 0 deletions tests/packages/subproject/subprojects/dep/data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
excluded via tool.meson-python.wheel.exclude
2 changes: 2 additions & 0 deletions tests/packages/subproject/subprojects/dep/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ project('dep')
py = import('python').find_installation()

py.install_sources('dep.py')

install_data('data.txt')
Loading