14
14
import argparse
15
15
import collections
16
16
import contextlib
17
+ import dataclasses
17
18
import difflib
18
19
import functools
19
20
import importlib .machinery
@@ -109,9 +110,14 @@ class InvalidLicenseExpression(Exception): # type: ignore[no-redef]
109
110
}
110
111
111
112
112
- def _map_to_wheel (sources : Dict [str , Dict [str , Any ]]) -> DefaultDict [str , List [Tuple [pathlib .Path , str ]]]:
113
+ class Entry (typing .NamedTuple ):
114
+ dst : pathlib .Path
115
+ src : str
116
+
117
+
118
+ def _map_to_wheel (sources : Dict [str , Dict [str , Any ]]) -> DefaultDict [str , List [Entry ]]:
113
119
"""Map files to the wheel, organized by wheel installation directory."""
114
- wheel_files : DefaultDict [str , List [Tuple [ pathlib . Path , str ] ]] = collections .defaultdict (list )
120
+ wheel_files : DefaultDict [str , List [Entry ]] = collections .defaultdict (list )
115
121
packages : Dict [str , str ] = {}
116
122
117
123
for key , group in sources .items ():
@@ -129,7 +135,8 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[T
129
135
other = packages .setdefault (package , path )
130
136
if other != path :
131
137
this = os .fspath (pathlib .Path (path , * destination .parts [1 :]))
132
- that = os .fspath (other / next (d for d , s in wheel_files [other ] if d .parts [0 ] == destination .parts [1 ]))
138
+ module = next (entry .dst for entry in wheel_files [other ] if entry .dst .parts [0 ] == destination .parts [1 ])
139
+ that = os .fspath (other / module )
133
140
raise BuildError (
134
141
f'The { package } package is split between { path } and { other } : '
135
142
f'{ this !r} and { that !r} , a "pure: false" argument may be missing in meson.build. '
@@ -152,9 +159,9 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]]) -> DefaultDict[str, List[T
152
159
if relpath in exclude_files :
153
160
continue
154
161
filedst = dst / relpath
155
- wheel_files [path ].append ((filedst , filesrc ))
162
+ wheel_files [path ].append (Entry (filedst , filesrc ))
156
163
else :
157
- wheel_files [path ].append ((dst , src ))
164
+ wheel_files [path ].append (Entry (dst , src ))
158
165
159
166
return wheel_files
160
167
@@ -301,20 +308,14 @@ def _is_native(file: Path) -> bool:
301
308
return f .read (4 ) == b'\x7f ELF' # ELF
302
309
303
310
311
+ @dataclasses .dataclass
304
312
class _WheelBuilder ():
305
313
"""Helper class to build wheels from projects."""
306
314
307
- def __init__ (
308
- self ,
309
- metadata : Metadata ,
310
- manifest : Dict [str , List [Tuple [pathlib .Path , str ]]],
311
- limited_api : bool ,
312
- allow_windows_shared_libs : bool ,
313
- ) -> None :
314
- self ._metadata = metadata
315
- self ._manifest = manifest
316
- self ._limited_api = limited_api
317
- self ._allow_windows_shared_libs = allow_windows_shared_libs
315
+ _metadata : Metadata
316
+ _manifest : Dict [str , List [Entry ]]
317
+ _limited_api : bool
318
+ _allow_windows_shared_libs : bool
318
319
319
320
@property
320
321
def _has_internal_libs (self ) -> bool :
@@ -330,8 +331,8 @@ def _pure(self) -> bool:
330
331
"""Whether the wheel is architecture independent"""
331
332
if self ._manifest ['platlib' ] or self ._manifest ['mesonpy-libs' ]:
332
333
return False
333
- for _ , file in self ._manifest ['scripts' ]:
334
- if _is_native (file ):
334
+ for entry in self ._manifest ['scripts' ]:
335
+ if _is_native (entry . src ):
335
336
return False
336
337
return True
337
338
@@ -408,14 +409,14 @@ def _stable_abi(self) -> Optional[str]:
408
409
# in {platlib} that look like extension modules, and raise
409
410
# an exception if any of them has a Python version
410
411
# specific extension filename suffix ABI tag.
411
- for path , _ in self ._manifest ['platlib' ]:
412
- match = _EXTENSION_SUFFIX_REGEX .match (path .name )
412
+ for entry in self ._manifest ['platlib' ]:
413
+ match = _EXTENSION_SUFFIX_REGEX .match (entry . dst .name )
413
414
if match :
414
415
abi = match .group ('abi' )
415
416
if abi is not None and abi != 'abi3' :
416
417
raise BuildError (
417
418
f'The package declares compatibility with Python limited API but extension '
418
- f'module { os .fspath (path )!r} is tagged for a specific Python version.' )
419
+ f'module { os .fspath (entry . dst )!r} is tagged for a specific Python version.' )
419
420
return 'abi3'
420
421
return None
421
422
@@ -497,8 +498,8 @@ class _EditableWheelBuilder(_WheelBuilder):
497
498
def _top_level_modules (self ) -> Collection [str ]:
498
499
modules = set ()
499
500
for type_ in self ._manifest :
500
- for path , _ in self ._manifest [type_ ]:
501
- name , dot , ext = path .parts [0 ].partition ('.' )
501
+ for entry in self ._manifest [type_ ]:
502
+ name , dot , ext = entry . dst .parts [0 ].partition ('.' )
502
503
if dot :
503
504
# module
504
505
suffix = dot + ext
@@ -854,7 +855,7 @@ def _info(self, name: str) -> Any:
854
855
return json .loads (info .read_text (encoding = 'utf-8' ))
855
856
856
857
@property
857
- def _manifest (self ) -> DefaultDict [str , List [Tuple [ pathlib . Path , str ] ]]:
858
+ def _manifest (self ) -> DefaultDict [str , List [Entry ]]:
858
859
"""The files to be added to the wheel, organized by wheel path."""
859
860
860
861
# Obtain the list of files Meson would install.
0 commit comments