1
- from __future__ import print_function
1
+ from __future__ import annotations
2
2
3
3
import itertools
4
4
import os
8
8
from contextlib import contextmanager
9
9
10
10
from ..wheelfile import WheelFile
11
- from .pack import pack
11
+ from .pack import pack , read_tags , set_build_number
12
12
from .unpack import unpack
13
13
14
14
try :
@@ -84,14 +84,13 @@ def compute_tags(original_tags, new_tags):
84
84
85
85
86
86
def tags (
87
- wheels ,
88
- python_tags = None ,
89
- abi_tags = None ,
90
- platform_tags = None ,
91
- build_number = None ,
92
- remove = False ,
93
- ):
94
- # type: (List[str], Optional[List[str]], Optional[List[str]], Optional[List[str]], Optional[int], bool) -> Iterator[str] # noqa: E501
87
+ wheels : list [str ],
88
+ python_tags : list [str ] | None = None ,
89
+ abi_tags : list [str ] | None = None ,
90
+ platform_tags : list [str ] = None ,
91
+ build_number : int | None = None ,
92
+ remove : bool = False ,
93
+ ) -> Iterator [str ]:
95
94
"""Change the tags on a wheel file.
96
95
97
96
The tags are left unchanged if they are not specified. To specify "none",
@@ -106,54 +105,103 @@ def tags(
106
105
"""
107
106
108
107
for wheel in wheels :
109
- with temporary_directory () as tmpdir , InWheelCtx (wheel , tmpdir ) as wfctx :
110
- namever = wfctx .parsed_filename .group ("namever" )
111
- build = wfctx .parsed_filename .group ("build" )
112
- original_python_tags = wfctx .parsed_filename .group ("pyver" ).split ("." )
113
- original_abi_tags = wfctx .parsed_filename .group ("abi" ).split ("." )
114
- orignial_plat_tags = wfctx .parsed_filename .group ("plat" ).split ("." )
115
-
116
- if build_number is not None :
117
- build = str (build_number )
118
-
119
- final_python_tags = compute_tags (original_python_tags , python_tags )
120
- final_abi_tags = compute_tags (original_abi_tags , abi_tags )
121
- final_plat_tags = compute_tags (orignial_plat_tags , platform_tags )
122
-
123
- final_tags = [
124
- "." .join (sorted (final_python_tags )),
125
- "." .join (sorted (final_abi_tags )),
126
- "." .join (sorted (final_plat_tags )),
108
+ with WheelFile (wheel , "r" ) as f :
109
+ wheel_info = f .read (f .dist_info_path + "/WHEEL" )
110
+
111
+ original_wheel_name = os .path .basename (f .filename )
112
+ namever = f .parsed_filename .group ("namever" )
113
+ build = f .parsed_filename .group ("build" )
114
+ original_python_tags = f .parsed_filename .group ("pyver" ).split ("." )
115
+ original_abi_tags = f .parsed_filename .group ("abi" ).split ("." )
116
+ orignial_plat_tags = f .parsed_filename .group ("plat" ).split ("." )
117
+
118
+ tags , existing_build_number = read_tags (wheel_info )
119
+
120
+ impls = {tag .split ("-" )[0 ] for tag in tags }
121
+ abivers = {tag .split ("-" )[1 ] for tag in tags }
122
+ platforms = {tag .split ("-" )[2 ] for tag in tags }
123
+
124
+ if impls != set (original_python_tags ):
125
+ raise AssertionError (f"{ impls } != { original_python_tags } " )
126
+
127
+ if abivers != set (original_abi_tags ):
128
+ raise AssertionError (f"{ abivers } != { original_abi_tags } " )
129
+
130
+ if platforms != set (orignial_plat_tags ):
131
+ raise AssertionError (f"{ platforms } != { orignial_plat_tags } " )
132
+
133
+ if existing_build_number != build :
134
+ raise AssertionError (
135
+ f"Incorrect filename '{ build } ' & "
136
+ f"*.dist-info/WHEEL '{ existing_build_number } ' build numbers"
137
+ )
138
+
139
+ # Start changing as needed
140
+ if build_number is not None :
141
+ build = str (build_number )
142
+
143
+ final_python_tags = compute_tags (original_python_tags , python_tags )
144
+ final_abi_tags = compute_tags (original_abi_tags , abi_tags )
145
+ final_plat_tags = compute_tags (orignial_plat_tags , platform_tags )
146
+
147
+ final_tags = [
148
+ "." .join (sorted (final_python_tags )),
149
+ "." .join (sorted (final_abi_tags )),
150
+ "." .join (sorted (final_plat_tags )),
151
+ ]
152
+
153
+ if build :
154
+ final_tags .insert (0 , build )
155
+ final_tags .insert (0 , namever )
156
+
157
+ final_wheel_name = "-" .join (final_tags ) + ".whl"
158
+
159
+ if original_wheel_name != final_wheel_name :
160
+ tags = [
161
+ f"{ a } -{ b } -{ c } "
162
+ for a , b , c in itertools .product (
163
+ final_python_tags , final_abi_tags , final_plat_tags
164
+ )
127
165
]
128
166
129
- if build :
130
- final_tags .insert (0 , build )
131
- final_tags .insert (0 , namever )
167
+ original_wheel_path = os .path .join (
168
+ os .path .dirname (f .filename ), original_wheel_name
169
+ )
170
+ final_wheel_path = os .path .join (
171
+ os .path .dirname (f .filename ), final_wheel_name
172
+ )
173
+
174
+ with WheelFile (original_wheel_path , "r" ) as fin , WheelFile (
175
+ final_wheel_path , "w"
176
+ ) as fout :
177
+ fout .comment = fin .comment # preserve the comment
178
+ for item in fin .infolist ():
179
+ if item .filename == f .dist_info_path + "/RECORD" :
180
+ continue
181
+ if item .filename == f .dist_info_path + "/WHEEL" :
182
+ content = fin .read (item )
183
+ content = set_tags (content , tags )
184
+ content = set_build_number (content , build )
185
+ fout .writestr (item , content )
186
+ else :
187
+ fout .writestr (item , fin .read (item ))
188
+
189
+ if remove :
190
+ os .remove (original_wheel_path )
132
191
133
- original_wheel_name = os .path .basename (wfctx .filename )
134
- final_wheel_name = "-" .join (final_tags ) + ".whl"
192
+ yield final_wheel_name
135
193
136
- if original_wheel_name != final_wheel_name :
137
194
138
- wheelinfo = os .path .join (
139
- tmpdir , namever , wfctx .wheel .dist_info_path , "WHEEL"
140
- )
141
- with open (wheelinfo , "rb+" ) as f :
142
- lines = [line for line in f if not line .startswith (b"Tag:" )]
143
- for a , b , c in itertools .product (
144
- final_python_tags , final_abi_tags , final_plat_tags
145
- ):
146
- lines .append (
147
- "Tag: {}-{}-{}\r \n " .format (a , b , c ).encode ("ascii" )
148
- )
149
- f .seek (0 )
150
- f .truncate ()
151
- f .write (b"" .join (lines ))
152
-
153
- wfctx .build_number = build
154
- wfctx .dirname = os .path .dirname (wheel )
155
-
156
- if remove :
157
- os .remove (wheel )
195
+ def set_tags (in_string : bytes , tags : list [str ]) -> bytes :
196
+ """Set the tags in the .dist-info/WHEEL file contents.
158
197
159
- yield final_wheel_name
198
+ :param in_string: The string to modify.
199
+ :param tags: The tags to set.
200
+ """
201
+
202
+ lines = [line for line in in_string .splitlines () if not line .startswith (b"Tag:" )]
203
+ for tag in tags :
204
+ lines .append (b"Tag: " + tag .encode ("ascii" ))
205
+ in_string = b"\r \n " .join (lines ) + b"\r \n "
206
+
207
+ return in_string
0 commit comments