Skip to content

Commit

Permalink
MAINT: refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
dnicolodi committed Feb 13, 2025
1 parent 726aafc commit 8b61d26
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 25 deletions.
49 changes: 25 additions & 24 deletions mesonpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import argparse
import collections
import contextlib
import dataclasses
import difflib
import functools
import importlib.machinery
Expand Down Expand Up @@ -109,9 +110,14 @@ class InvalidLicenseExpression(Exception): # type: ignore[no-redef]
}


def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]:
class Entry(typing.NamedTuple):
dst: pathlib.Path
src: str


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

for key, group in sources.items():
Expand All @@ -129,7 +135,8 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[T
other = packages.setdefault(package, path)
if other != path:
this = os.fspath(pathlib.Path(path, *destination.parts[1:]))
that = os.fspath(other / next(d for d, s in wheel_files[other] if d.parts[0] == 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. '
Expand All @@ -152,9 +159,9 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[T
if relpath in exclude_files:
continue
filedst = dst / relpath
wheel_files[path].append((filedst, filesrc))
wheel_files[path].append(Entry(filedst, filesrc))
else:
wheel_files[path].append((dst, src))
wheel_files[path].append(Entry(dst, src))

return wheel_files

Expand Down Expand Up @@ -301,20 +308,14 @@ def _is_native(file: Path) -> bool:
return f.read(4) == b'\x7fELF' # ELF


@dataclasses.dataclass
class _WheelBuilder():
"""Helper class to build wheels from projects."""

def __init__(
self,
metadata: Metadata,
manifest: Dict[str, List[Tuple[pathlib.Path, str]]],
limited_api: bool,
allow_windows_shared_libs: bool,
) -> None:
self._metadata = metadata
self._manifest = manifest
self._limited_api = limited_api
self._allow_windows_shared_libs = allow_windows_shared_libs
_metadata: Metadata
_manifest: Dict[str, List[Entry]]
_limited_api: bool
_allow_windows_shared_libs: bool

@property
def _has_internal_libs(self) -> bool:
Expand All @@ -330,8 +331,8 @@ def _pure(self) -> bool:
"""Whether the wheel is architecture independent"""
if self._manifest['platlib'] or self._manifest['mesonpy-libs']:
return False
for _, file in self._manifest['scripts']:
if _is_native(file):
for entry in self._manifest['scripts']:
if _is_native(entry.src):
return False
return True

Expand Down Expand Up @@ -408,14 +409,14 @@ def _stable_abi(self) -> Optional[str]:
# in {platlib} that look like extension modules, and raise
# an exception if any of them has a Python version
# specific extension filename suffix ABI tag.
for path, _ in self._manifest['platlib']:
match = _EXTENSION_SUFFIX_REGEX.match(path.name)
for entry in self._manifest['platlib']:
match = _EXTENSION_SUFFIX_REGEX.match(entry.dst.name)
if match:
abi = match.group('abi')
if abi is not None and abi != 'abi3':
raise BuildError(
f'The package declares compatibility with Python limited API but extension '
f'module {os.fspath(path)!r} is tagged for a specific Python version.')
f'module {os.fspath(entry.dst)!r} is tagged for a specific Python version.')
return 'abi3'
return None

Expand Down Expand Up @@ -497,8 +498,8 @@ class _EditableWheelBuilder(_WheelBuilder):
def _top_level_modules(self) -> Collection[str]:
modules = set()
for type_ in self._manifest:
for path, _ in self._manifest[type_]:
name, dot, ext = path.parts[0].partition('.')
for entry in self._manifest[type_]:
name, dot, ext = entry.dst.parts[0].partition('.')
if dot:
# module
suffix = dot + ext
Expand Down Expand Up @@ -854,7 +855,7 @@ def _info(self, name: str) -> Any:
return json.loads(info.read_text(encoding='utf-8'))

@property
def _manifest(self) -> DefaultDict[str, List[Tuple[pathlib.Path, str]]]:
def _manifest(self) -> DefaultDict[str, List[Entry]]:
"""The files to be added to the wheel, organized by wheel path."""

# Obtain the list of files Meson would install.
Expand Down
3 changes: 2 additions & 1 deletion tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ def test_python_host_platform(monkeypatch):

def wheel_builder_test_factory(content, pure=True, limited_api=False):
manifest = defaultdict(list)
manifest.update({key: [(pathlib.Path(x), os.path.join('build', x)) for x in value] for key, value in content.items()})
for key, value in content.items():
manifest[key] = [mesonpy.Entry(pathlib.Path(x), os.path.join('build', x)) for x in value]
return mesonpy._WheelBuilder(None, manifest, limited_api, False)


Expand Down

0 comments on commit 8b61d26

Please sign in to comment.