1515import collections
1616import contextlib
1717import copy
18+ import dataclasses
1819import difflib
1920import fnmatch
2021import functools
@@ -120,13 +121,17 @@ def _compile_patterns(patterns: List[str]) -> Callable[[str], bool]:
120121 return typing .cast ('Callable[[str], bool]' , func )
121122
122123
124+ class _Entry (typing .NamedTuple ):
125+ dst : pathlib .Path
126+ src : str
127+
128+
123129def _map_to_wheel (
124130 sources : Dict [str , Dict [str , Any ]],
125- exclude : List [str ],
126- include : List [str ],
127- ) -> DefaultDict [str , List [Tuple [pathlib .Path , str ]]]:
131+ exclude : List [str ], include : List [str ]
132+ ) -> DefaultDict [str , List [_Entry ]]:
128133 """Map files to the wheel, organized by wheel installation directory."""
129- wheel_files : DefaultDict [str , List [Tuple [ pathlib . Path , str ] ]] = collections .defaultdict (list )
134+ wheel_files : DefaultDict [str , List [_Entry ]] = collections .defaultdict (list )
130135 packages : Dict [str , str ] = {}
131136 excluded = _compile_patterns (exclude )
132137 included = _compile_patterns (include )
@@ -151,7 +156,8 @@ def _map_to_wheel(
151156 other = packages .setdefault (package , path )
152157 if other != path :
153158 this = os .fspath (pathlib .Path (path , * destination .parts [1 :]))
154- that = os .fspath (other / next (d for d , s in wheel_files [other ] if d .parts [0 ] == destination .parts [1 ]))
159+ module = next (entry .dst for entry in wheel_files [other ] if entry .dst .parts [0 ] == destination .parts [1 ])
160+ that = os .fspath (other / module )
155161 raise BuildError (
156162 f'The { package } package is split between { path } and { other } : '
157163 f'{ this !r} and { that !r} , a "pure: false" argument may be missing in meson.build. '
@@ -174,9 +180,9 @@ def _map_to_wheel(
174180 if relpath in exclude_files :
175181 continue
176182 filedst = dst / relpath
177- wheel_files [path ].append ((filedst , filesrc ))
183+ wheel_files [path ].append (_Entry (filedst , filesrc ))
178184 else :
179- wheel_files [path ].append ((dst , src ))
185+ wheel_files [path ].append (_Entry (dst , src ))
180186
181187 return wheel_files
182188
@@ -323,20 +329,14 @@ def _is_native(file: Path) -> bool:
323329 return f .read (4 ) == b'\x7f ELF' # ELF
324330
325331
332+ @dataclasses .dataclass
326333class _WheelBuilder ():
327334 """Helper class to build wheels from projects."""
328335
329- def __init__ (
330- self ,
331- metadata : Metadata ,
332- manifest : Dict [str , List [Tuple [pathlib .Path , str ]]],
333- limited_api : bool ,
334- allow_windows_shared_libs : bool ,
335- ) -> None :
336- self ._metadata = metadata
337- self ._manifest = manifest
338- self ._limited_api = limited_api
339- self ._allow_windows_shared_libs = allow_windows_shared_libs
336+ _metadata : Metadata
337+ _manifest : Dict [str , List [_Entry ]]
338+ _limited_api : bool
339+ _allow_windows_shared_libs : bool
340340
341341 @property
342342 def _has_internal_libs (self ) -> bool :
@@ -352,8 +352,8 @@ def _pure(self) -> bool:
352352 """Whether the wheel is architecture independent"""
353353 if self ._manifest ['platlib' ] or self ._manifest ['mesonpy-libs' ]:
354354 return False
355- for _ , file in self ._manifest ['scripts' ]:
356- if _is_native (file ):
355+ for entry in self ._manifest ['scripts' ]:
356+ if _is_native (entry . src ):
357357 return False
358358 return True
359359
@@ -430,14 +430,14 @@ def _stable_abi(self) -> Optional[str]:
430430 # in {platlib} that look like extension modules, and raise
431431 # an exception if any of them has a Python version
432432 # specific extension filename suffix ABI tag.
433- for path , _ in self ._manifest ['platlib' ]:
434- match = _EXTENSION_SUFFIX_REGEX .match (path .name )
433+ for entry in self ._manifest ['platlib' ]:
434+ match = _EXTENSION_SUFFIX_REGEX .match (entry . dst .name )
435435 if match :
436436 abi = match .group ('abi' )
437437 if abi is not None and abi != 'abi3' :
438438 raise BuildError (
439439 f'The package declares compatibility with Python limited API but extension '
440- f'module { os .fspath (path )!r} is tagged for a specific Python version.' )
440+ f'module { os .fspath (entry . dst )!r} is tagged for a specific Python version.' )
441441 return 'abi3'
442442 return None
443443
@@ -519,8 +519,8 @@ class _EditableWheelBuilder(_WheelBuilder):
519519 def _top_level_modules (self ) -> Collection [str ]:
520520 modules = set ()
521521 for type_ in self ._manifest :
522- for path , _ in self ._manifest [type_ ]:
523- name , dot , ext = path .parts [0 ].partition ('.' )
522+ for entry in self ._manifest [type_ ]:
523+ name , dot , ext = entry . dst .parts [0 ].partition ('.' )
524524 if dot :
525525 # module
526526 suffix = dot + ext
@@ -912,7 +912,7 @@ def _info(self, name: str) -> Any:
912912 return json .loads (info .read_text (encoding = 'utf-8' ))
913913
914914 @property
915- def _manifest (self ) -> DefaultDict [str , List [Tuple [ pathlib . Path , str ] ]]:
915+ def _manifest (self ) -> DefaultDict [str , List [_Entry ]]:
916916 """The files to be added to the wheel, organized by wheel path."""
917917
918918 # Obtain the list of files Meson would install.
0 commit comments