@@ -94,13 +94,18 @@ def normalize_pep440(version):
9494 substituted = re .sub (r"\{\w+\}" , "0" , version )
9595 delimiter = "." if "+" in substituted else "+"
9696 try :
97- return str (packaging .version .Version (f"{ substituted } { delimiter } { sanitized } " ))
97+ return str (
98+ packaging .version .Version (f"{ substituted } { delimiter } { sanitized } " )
99+ )
98100 except packaging .version .InvalidVersion :
99101 return str (packaging .version .Version (f"0+{ sanitized } " ))
100102
101103
102104def arcname_from (
103- name : str , distribution_prefix : str , strip_path_prefixes : Sequence [str ] = ()
105+ name : str ,
106+ distribution_prefix : str ,
107+ strip_path_prefixes : Sequence [str ] = (),
108+ add_path_prefix : str = "" ,
104109) -> str :
105110 """Return the within-archive name for a given file path name.
106111
@@ -110,17 +115,20 @@ def arcname_from(
110115 name: The file path eg 'mylib/a/b/c/file.py'
111116 distribution_prefix: The
112117 strip_path_prefixes: Remove these prefixes from names.
118+ add_path_prefix: Add prefix after stripping the path from names.
113119 """
114120 # Always use unix path separators.
115121 normalized_arcname = name .replace (os .path .sep , "/" )
116122 # Don't manipulate names filenames in the .distinfo or .data directories.
117- if distribution_prefix and normalized_arcname .startswith (distribution_prefix ):
123+ if distribution_prefix and normalized_arcname .startswith (
124+ distribution_prefix
125+ ):
118126 return normalized_arcname
119127 for prefix in strip_path_prefixes :
120128 if normalized_arcname .startswith (prefix ):
121- return normalized_arcname [len (prefix ) :]
129+ return add_path_prefix + normalized_arcname [len (prefix ) :]
122130
123- return normalized_arcname
131+ return add_path_prefix + normalized_arcname
124132
125133
126134class _WhlFile (zipfile .ZipFile ):
@@ -131,13 +139,15 @@ def __init__(
131139 mode ,
132140 distribution_prefix : str ,
133141 strip_path_prefixes = None ,
142+ add_path_prefix = None ,
134143 compression = zipfile .ZIP_DEFLATED ,
135144 quote_all_filenames : bool = False ,
136145 ** kwargs ,
137146 ):
138147 self ._distribution_prefix = distribution_prefix
139148
140149 self ._strip_path_prefixes = strip_path_prefixes or []
150+ self ._add_path_prefix = add_path_prefix or ""
141151 # Entries for the RECORD file as (filename, digest, size) tuples.
142152 self ._record : list [tuple [str , str , str ]] = []
143153 # Whether to quote filenames in the RECORD file (for compatibility with
@@ -168,6 +178,7 @@ def add_file(self, package_filename, real_filename):
168178 package_filename ,
169179 distribution_prefix = self ._distribution_prefix ,
170180 strip_path_prefixes = self ._strip_path_prefixes ,
181+ add_path_prefix = self ._add_path_prefix ,
171182 )
172183 zinfo = self ._zipinfo (arcname )
173184
@@ -194,7 +205,9 @@ def add_string(self, filename, contents):
194205 self .writestr (zinfo , contents )
195206 hash = hashlib .sha256 ()
196207 hash .update (contents )
197- self ._add_to_record (filename , self ._serialize_digest (hash ), len (contents ))
208+ self ._add_to_record (
209+ filename , self ._serialize_digest (hash ), len (contents )
210+ )
198211
199212 def _serialize_digest (self , hash ) -> str :
200213 # https://www.python.org/dev/peps/pep-0376/#record
@@ -231,7 +244,9 @@ def _quote_filename(self, filename: str) -> str:
231244 filename = filename .lstrip ("/" )
232245 # Some RECORDs like torch have *all* filenames quoted and we must minimize diff.
233246 # Otherwise, we quote only when necessary (e.g. for filenames with commas).
234- quoting = csv .QUOTE_ALL if self .quote_all_filenames else csv .QUOTE_MINIMAL
247+ quoting = (
248+ csv .QUOTE_ALL if self .quote_all_filenames else csv .QUOTE_MINIMAL
249+ )
235250 with io .StringIO () as buf :
236251 csv .writer (buf , quoting = quoting ).writerow ([filename ])
237252 return buf .getvalue ().strip ()
@@ -261,6 +276,7 @@ def __init__(
261276 compress ,
262277 outfile = None ,
263278 strip_path_prefixes = None ,
279+ add_path_prefix = None ,
264280 ):
265281 self ._name = name
266282 self ._version = normalize_pep440 (version )
@@ -270,9 +286,10 @@ def __init__(
270286 self ._platform = platform
271287 self ._outfile = outfile
272288 self ._strip_path_prefixes = strip_path_prefixes
289+ self ._add_path_prefix = add_path_prefix
273290 self ._compress = compress
274- self ._wheelname_fragment_distribution_name = escape_filename_distribution_name (
275- self ._name
291+ self ._wheelname_fragment_distribution_name = (
292+ escape_filename_distribution_name ( self ._name )
276293 )
277294
278295 self ._distribution_prefix = (
@@ -287,7 +304,10 @@ def __enter__(self):
287304 mode = "w" ,
288305 distribution_prefix = self ._distribution_prefix ,
289306 strip_path_prefixes = self ._strip_path_prefixes ,
290- compression = zipfile .ZIP_DEFLATED if self ._compress else zipfile .ZIP_STORED ,
307+ add_path_prefix = self ._add_path_prefix ,
308+ compression = (
309+ zipfile .ZIP_DEFLATED if self ._compress else zipfile .ZIP_STORED
310+ ),
291311 )
292312 return self
293313
@@ -330,7 +350,9 @@ def add_wheelfile(self):
330350 Wheel-Version: 1.0
331351Generator: bazel-wheelmaker 1.0
332352Root-Is-Purelib: {}
333- """ .format ("true" if self ._platform == "any" else "false" )
353+ """ .format (
354+ "true" if self ._platform == "any" else "false"
355+ )
334356 for tag in self .disttags ():
335357 wheel_contents += "Tag: %s\n " % tag
336358 self ._whlfile .add_string (self .distinfo_path ("WHEEL" ), wheel_contents )
@@ -339,7 +361,9 @@ def add_metadata(self, metadata, name, description):
339361 """Write METADATA file to the distribution."""
340362 # https://www.python.org/dev/peps/pep-0566/
341363 # https://packaging.python.org/specifications/core-metadata/
342- metadata = re .sub ("^Name: .*$" , "Name: %s" % name , metadata , flags = re .MULTILINE )
364+ metadata = re .sub (
365+ "^Name: .*$" , "Name: %s" % name , metadata , flags = re .MULTILINE
366+ )
343367 metadata += "Version: %s\n \n " % self ._version
344368 # setuptools seems to insert UNKNOWN as description when none is
345369 # provided.
@@ -418,7 +442,9 @@ def resolve_argument_stamp(
418442
419443def parse_args () -> argparse .Namespace :
420444 parser = argparse .ArgumentParser (description = "Builds a python wheel" )
421- metadata_group = parser .add_argument_group ("Wheel name, version and platform" )
445+ metadata_group = parser .add_argument_group (
446+ "Wheel name, version and platform"
447+ )
422448 metadata_group .add_argument (
423449 "--name" , required = True , type = str , help = "Name of the distribution"
424450 )
@@ -465,6 +491,13 @@ def parse_args() -> argparse.Namespace:
465491 help = "Path prefix to be stripped from input package files' path. "
466492 "Can be supplied multiple times. Evaluated in order." ,
467493 )
494+ output_group .add_argument (
495+ "--path_prefix" ,
496+ type = str ,
497+ default = "" ,
498+ help = "Path prefix to be prepended to input package files' path. "
499+ "It is prepended after stripping any specified path prefixes first." ,
500+ )
468501
469502 wheel_group = parser .add_argument_group ("Wheel metadata" )
470503 wheel_group .add_argument (
@@ -477,7 +510,8 @@ def parse_args() -> argparse.Namespace:
477510 "--description_file" , help = "Path to the file with package description"
478511 )
479512 wheel_group .add_argument (
480- "--description_content_type" , help = "Content type of the package description"
513+ "--description_content_type" ,
514+ help = "Content type of the package description" ,
481515 )
482516 wheel_group .add_argument (
483517 "--entry_points_file" ,
@@ -579,6 +613,7 @@ def main() -> None:
579613 platform = arguments .platform ,
580614 outfile = arguments .out ,
581615 strip_path_prefixes = strip_prefixes ,
616+ add_path_prefix = arguments .path_prefix ,
582617 compress = not arguments .no_compress ,
583618 ) as maker :
584619 for package_filename , real_filename in all_files :
@@ -608,7 +643,9 @@ def main() -> None:
608643
609644 if not meta_line [len ("Requires-Dist: " ) :].startswith ("@" ):
610645 # This is a normal requirement.
611- package , _ , extra = meta_line [len ("Requires-Dist: " ) :].rpartition (";" )
646+ package , _ , extra = meta_line [
647+ len ("Requires-Dist: " ) :
648+ ].rpartition (";" )
612649 if not package :
613650 # This is when the package requirement does not have markers.
614651 continue
@@ -623,7 +660,9 @@ def main() -> None:
623660 extra = extra .strip ()
624661
625662 reqs = []
626- for reqs_line in Path (file ).read_text (encoding = "utf-8" ).splitlines ():
663+ for reqs_line in (
664+ Path (file ).read_text (encoding = "utf-8" ).splitlines ()
665+ ):
627666 reqs_text = reqs_line .strip ()
628667 if not reqs_text or reqs_text .startswith (("#" , "-" )):
629668 continue
@@ -650,7 +689,8 @@ def main() -> None:
650689
651690 if arguments .entry_points_file :
652691 maker .add_file (
653- maker .distinfo_path ("entry_points.txt" ), arguments .entry_points_file
692+ maker .distinfo_path ("entry_points.txt" ),
693+ arguments .entry_points_file ,
654694 )
655695
656696 # Sort the files for reproducible order in the archive.
0 commit comments