|
16 | 16 | import contextlib
|
17 | 17 | import copy
|
18 | 18 | import difflib
|
| 19 | +import fnmatch |
19 | 20 | import functools
|
20 | 21 | import importlib.machinery
|
21 | 22 | import io
|
@@ -111,14 +112,32 @@ class InvalidLicenseExpression(Exception): # type: ignore[no-redef]
|
111 | 112 | }
|
112 | 113 |
|
113 | 114 |
|
114 |
| -def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]: |
| 115 | +def _compile_patterns(patterns: List[str]) -> Callable[[str], bool]: |
| 116 | + if not patterns: |
| 117 | + return lambda x: False |
| 118 | + func = re.compile('|'.join(fnmatch.translate(os.path.normpath(p)) for p in patterns)).match |
| 119 | + return typing.cast('Callable[[str], bool]', func) |
| 120 | + |
| 121 | + |
| 122 | +def _map_to_wheel( |
| 123 | + sources: Dict[str, Dict[str, Any]], |
| 124 | + exclude: List[str], |
| 125 | + include: List[str], |
| 126 | +) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]: |
115 | 127 | """Map files to the wheel, organized by wheel installation directory."""
|
116 | 128 | wheel_files: DefaultDict[str, List[Tuple[pathlib.Path, str]]] = collections.defaultdict(list)
|
117 | 129 | packages: Dict[str, str] = {}
|
| 130 | + excluded = _compile_patterns(exclude) |
| 131 | + included = _compile_patterns(include) |
118 | 132 |
|
119 | 133 | for key, group in sources.items():
|
120 | 134 | for src, target in group.items():
|
121 |
| - destination = pathlib.Path(target['destination']) |
| 135 | + target_destination = os.path.normpath(target['destination']) |
| 136 | + |
| 137 | + if excluded(target_destination) and not included(target_destination): |
| 138 | + continue |
| 139 | + |
| 140 | + destination = pathlib.Path(target_destination) |
122 | 141 | anchor = destination.parts[0]
|
123 | 142 | dst = pathlib.Path(*destination.parts[1:])
|
124 | 143 |
|
@@ -581,6 +600,10 @@ def _string_or_path(value: Any, name: str) -> str:
|
581 | 600 | 'args': _table({
|
582 | 601 | name: _strings for name in _MESON_ARGS_KEYS
|
583 | 602 | }),
|
| 603 | + 'wheel': _table({ |
| 604 | + 'exclude': _strings, |
| 605 | + 'include': _strings, |
| 606 | + }), |
584 | 607 | })
|
585 | 608 |
|
586 | 609 | table = pyproject.get('tool', {}).get('meson-python', {})
|
@@ -823,6 +846,10 @@ def __init__(
|
823 | 846 | # from the package, make sure the developers acknowledge this.
|
824 | 847 | self._allow_windows_shared_libs = pyproject_config.get('allow-windows-internal-shared-libs', False)
|
825 | 848 |
|
| 849 | + # Files to be excluded from the wheel |
| 850 | + self._excluded_files = pyproject_config.get('wheel', {}).get('exclude', []) |
| 851 | + self._included_files = pyproject_config.get('wheel', {}).get('include', []) |
| 852 | + |
826 | 853 | def _run(self, cmd: Sequence[str]) -> None:
|
827 | 854 | """Invoke a subprocess."""
|
828 | 855 | # Flush the line to ensure that the log line with the executed
|
@@ -906,7 +933,7 @@ def _manifest(self) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]:
|
906 | 933 | sources[key][target] = details
|
907 | 934 |
|
908 | 935 | # Map Meson installation locations to wheel paths.
|
909 |
| - return _map_to_wheel(sources) |
| 936 | + return _map_to_wheel(sources, self._excluded_files, self._included_files) |
910 | 937 |
|
911 | 938 | @property
|
912 | 939 | def _meson_name(self) -> str:
|
|
0 commit comments