1515import collections
1616import contextlib
1717import copy
18+ import dataclasses
1819import difflib
1920import fnmatch
2021import functools
@@ -120,13 +121,14 @@ def _compile_patterns(patterns: List[str]) -> Callable[[str], bool]:
120121 return typing .cast ('Callable[[str], bool]' , func )
121122
122123
123- def _map_to_wheel (
124- sources : Dict [str , Dict [str , Any ]],
125- exclude : List [str ],
126- include : List [str ],
127- ) -> DefaultDict [str , List [Tuple [pathlib .Path , str ]]]:
124+ class _Entry (typing .NamedTuple ):
125+ dst : pathlib .Path
126+ src : str
127+
128+
129+ def _map_to_wheel (sources : Dict [str , Dict [str , Any ]], exclude : List [str ], include : List [str ]) -> DefaultDict [str , List [_Entry ]]:
128130 """Map files to the wheel, organized by wheel installation directory."""
129- wheel_files : DefaultDict [str , List [Tuple [ pathlib . Path , str ] ]] = collections .defaultdict (list )
131+ wheel_files : DefaultDict [str , List [_Entry ]] = collections .defaultdict (list )
130132 packages : Dict [str , str ] = {}
131133 excluded = _compile_patterns (exclude )
132134 included = _compile_patterns (include )
@@ -151,7 +153,8 @@ def _map_to_wheel(
151153 other = packages .setdefault (package , path )
152154 if other != path :
153155 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 ]))
156+ module = next (entry .dst for entry in wheel_files [other ] if entry .dst .parts [0 ] == destination .parts [1 ])
157+ that = os .fspath (other / module )
155158 raise BuildError (
156159 f'The { package } package is split between { path } and { other } : '
157160 f'{ this !r} and { that !r} , a "pure: false" argument may be missing in meson.build. '
@@ -174,9 +177,9 @@ def _map_to_wheel(
174177 if relpath in exclude_files :
175178 continue
176179 filedst = dst / relpath
177- wheel_files [path ].append ((filedst , filesrc ))
180+ wheel_files [path ].append (_Entry (filedst , filesrc ))
178181 else :
179- wheel_files [path ].append ((dst , src ))
182+ wheel_files [path ].append (_Entry (dst , src ))
180183
181184 return wheel_files
182185
@@ -323,20 +326,14 @@ def _is_native(file: Path) -> bool:
323326 return f .read (4 ) == b'\x7f ELF' # ELF
324327
325328
329+ @dataclasses .dataclass
326330class _WheelBuilder ():
327331 """Helper class to build wheels from projects."""
328332
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
333+ _metadata : Metadata
334+ _manifest : Dict [str , List [Entry ]]
335+ _limited_api : bool
336+ _allow_windows_shared_libs : bool
340337
341338 @property
342339 def _has_internal_libs (self ) -> bool :
@@ -352,8 +349,8 @@ def _pure(self) -> bool:
352349 """Whether the wheel is architecture independent"""
353350 if self ._manifest ['platlib' ] or self ._manifest ['mesonpy-libs' ]:
354351 return False
355- for _ , file in self ._manifest ['scripts' ]:
356- if _is_native (file ):
352+ for entry in self ._manifest ['scripts' ]:
353+ if _is_native (entry . src ):
357354 return False
358355 return True
359356
@@ -430,14 +427,14 @@ def _stable_abi(self) -> Optional[str]:
430427 # in {platlib} that look like extension modules, and raise
431428 # an exception if any of them has a Python version
432429 # specific extension filename suffix ABI tag.
433- for path , _ in self ._manifest ['platlib' ]:
434- match = _EXTENSION_SUFFIX_REGEX .match (path .name )
430+ for entry in self ._manifest ['platlib' ]:
431+ match = _EXTENSION_SUFFIX_REGEX .match (entry . dst .name )
435432 if match :
436433 abi = match .group ('abi' )
437434 if abi is not None and abi != 'abi3' :
438435 raise BuildError (
439436 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.' )
437+ f'module { os .fspath (entry . dst )!r} is tagged for a specific Python version.' )
441438 return 'abi3'
442439 return None
443440
@@ -519,8 +516,8 @@ class _EditableWheelBuilder(_WheelBuilder):
519516 def _top_level_modules (self ) -> Collection [str ]:
520517 modules = set ()
521518 for type_ in self ._manifest :
522- for path , _ in self ._manifest [type_ ]:
523- name , dot , ext = path .parts [0 ].partition ('.' )
519+ for entry in self ._manifest [type_ ]:
520+ name , dot , ext = entry . dst .parts [0 ].partition ('.' )
524521 if dot :
525522 # module
526523 suffix = dot + ext
@@ -912,7 +909,7 @@ def _info(self, name: str) -> Any:
912909 return json .loads (info .read_text (encoding = 'utf-8' ))
913910
914911 @property
915- def _manifest (self ) -> DefaultDict [str , List [Tuple [ pathlib . Path , str ] ]]:
912+ def _manifest (self ) -> DefaultDict [str , List [Entry ]]:
916913 """The files to be added to the wheel, organized by wheel path."""
917914
918915 # Obtain the list of files Meson would install.
0 commit comments