3
3
import functools
4
4
import hashlib
5
5
6
- from collections import defaultdict
7
6
from contextlib import contextmanager
8
7
from pathlib import Path
9
8
from typing import TYPE_CHECKING
16
15
17
16
from poetry .core .constraints .version import parse_constraint
18
17
from poetry .core .packages .dependency import Dependency
19
- from poetry .core .packages .utils .link import Link
20
18
from poetry .core .utils .helpers import temporary_directory
21
19
from poetry .core .version .markers import parse_marker
22
20
33
31
34
32
if TYPE_CHECKING :
35
33
from packaging .utils import NormalizedName
34
+ from poetry .core .packages .utils .link import Link
36
35
37
36
from poetry .config .config import Config
38
37
from poetry .repositories .link_sources .base import LinkSource
@@ -86,41 +85,77 @@ def _cached_or_downloaded_file(self, link: Link) -> Iterator[Path]:
86
85
self ._download (link .url , filepath )
87
86
yield filepath
88
87
89
- def _get_info_from_wheel (self , url : str ) -> PackageInfo :
88
+ def _get_info_from_wheel (self , link : Link ) -> PackageInfo :
90
89
from poetry .inspection .info import PackageInfo
91
90
92
- with self ._cached_or_downloaded_file (Link ( url ) ) as filepath :
91
+ with self ._cached_or_downloaded_file (link ) as filepath :
93
92
return PackageInfo .from_wheel (filepath )
94
93
95
- def _get_info_from_sdist (self , url : str ) -> PackageInfo :
94
+ def _get_info_from_sdist (self , link : Link ) -> PackageInfo :
96
95
from poetry .inspection .info import PackageInfo
97
96
98
- with self ._cached_or_downloaded_file (Link ( url ) ) as filepath :
97
+ with self ._cached_or_downloaded_file (link ) as filepath :
99
98
return PackageInfo .from_sdist (filepath )
100
99
101
- @staticmethod
102
- def _get_info_from_metadata (
103
- url : str , metadata : dict [str , pkginfo .Distribution ]
104
- ) -> PackageInfo | None :
105
- if url in metadata :
106
- dist = metadata [url ]
107
- return PackageInfo (
108
- name = dist .name ,
109
- version = dist .version ,
110
- summary = dist .summary ,
111
- requires_dist = list (dist .requires_dist ),
112
- requires_python = dist .requires_python ,
113
- )
100
+ def _get_info_from_metadata (self , link : Link ) -> PackageInfo | None :
101
+ if link .has_metadata :
102
+ try :
103
+ assert link .metadata_url is not None
104
+ response = self .session .get (link .metadata_url )
105
+ distribution = pkginfo .Distribution ()
106
+ if link .metadata_hash_name is not None :
107
+ metadata_hash = getattr (hashlib , link .metadata_hash_name )(
108
+ response .text .encode ()
109
+ ).hexdigest ()
110
+
111
+ if metadata_hash != link .metadata_hash :
112
+ self ._log (
113
+ f"Metadata file hash ({ metadata_hash } ) does not match"
114
+ f" expected hash ({ link .metadata_hash } )."
115
+ f" Metadata file for { link .filename } will be ignored." ,
116
+ level = "warning" ,
117
+ )
118
+ return None
119
+
120
+ distribution .parse (response .content )
121
+ return PackageInfo (
122
+ name = distribution .name ,
123
+ version = distribution .version ,
124
+ summary = distribution .summary ,
125
+ requires_dist = list (distribution .requires_dist ),
126
+ requires_python = distribution .requires_python ,
127
+ )
128
+
129
+ except requests .HTTPError :
130
+ self ._log (
131
+ f"Failed to retrieve metadata at { link .metadata_url } " ,
132
+ level = "warning" ,
133
+ )
134
+
114
135
return None
115
136
116
- def _get_info_from_urls (
137
+ def _get_info_from_links (
117
138
self ,
118
- urls : dict [str , list [str ]],
119
- metadata : dict [str , pkginfo .Distribution ] | None = None ,
139
+ links : list [Link ],
140
+ * ,
141
+ ignore_yanked : bool = True ,
120
142
) -> PackageInfo :
121
- metadata = metadata or {}
143
+ # Sort links by distribution type
144
+ wheels : list [Link ] = []
145
+ sdists : list [Link ] = []
146
+ for link in links :
147
+ if link .yanked and ignore_yanked :
148
+ # drop yanked files unless the entire release is yanked
149
+ continue
150
+ if link .is_wheel :
151
+ wheels .append (link )
152
+ elif link .filename .endswith (
153
+ (".tar.gz" , ".zip" , ".bz2" , ".xz" , ".Z" , ".tar" )
154
+ ):
155
+ sdists .append (link )
156
+
122
157
# Prefer to read data from wheels: this is faster and more reliable
123
- if wheels := urls . get ( "bdist_wheel" ) :
158
+ if wheels :
124
159
# We ought just to be able to look at any of the available wheels to read
125
160
# metadata, they all should give the same answer.
126
161
#
@@ -135,8 +170,7 @@ def _get_info_from_urls(
135
170
universal_python3_wheel = None
136
171
platform_specific_wheels = []
137
172
for wheel in wheels :
138
- link = Link (wheel )
139
- m = wheel_file_re .match (link .filename )
173
+ m = wheel_file_re .match (wheel .filename )
140
174
if not m :
141
175
continue
142
176
@@ -157,17 +191,17 @@ def _get_info_from_urls(
157
191
158
192
if universal_wheel is not None :
159
193
return self ._get_info_from_metadata (
160
- universal_wheel , metadata
194
+ universal_wheel
161
195
) or self ._get_info_from_wheel (universal_wheel )
162
196
163
197
info = None
164
198
if universal_python2_wheel and universal_python3_wheel :
165
199
info = self ._get_info_from_metadata (
166
- universal_python2_wheel , metadata
200
+ universal_python2_wheel
167
201
) or self ._get_info_from_wheel (universal_python2_wheel )
168
202
169
203
py3_info = self ._get_info_from_metadata (
170
- universal_python3_wheel , metadata
204
+ universal_python3_wheel
171
205
) or self ._get_info_from_wheel (universal_python3_wheel )
172
206
173
207
if info .requires_python or py3_info .requires_python :
@@ -219,71 +253,23 @@ def _get_info_from_urls(
219
253
# Prefer non platform specific wheels
220
254
if universal_python3_wheel :
221
255
return self ._get_info_from_metadata (
222
- universal_python3_wheel , metadata
256
+ universal_python3_wheel
223
257
) or self ._get_info_from_wheel (universal_python3_wheel )
224
258
225
259
if universal_python2_wheel :
226
260
return self ._get_info_from_metadata (
227
- universal_python2_wheel , metadata
261
+ universal_python2_wheel
228
262
) or self ._get_info_from_wheel (universal_python2_wheel )
229
263
230
264
if platform_specific_wheels :
231
265
first_wheel = platform_specific_wheels [0 ]
232
266
return self ._get_info_from_metadata (
233
- first_wheel , metadata
267
+ first_wheel
234
268
) or self ._get_info_from_wheel (first_wheel )
235
269
236
- return self ._get_info_from_metadata (
237
- urls ["sdist" ][0 ], metadata
238
- ) or self ._get_info_from_sdist (urls ["sdist" ][0 ])
239
-
240
- def _get_info_from_links (
241
- self ,
242
- links : list [Link ],
243
- * ,
244
- ignore_yanked : bool = True ,
245
- ) -> PackageInfo :
246
- urls = defaultdict (list )
247
- metadata : dict [str , pkginfo .Distribution ] = {}
248
- for link in links :
249
- if link .yanked and ignore_yanked :
250
- # drop yanked files unless the entire release is yanked
251
- continue
252
- if link .has_metadata :
253
- try :
254
- assert link .metadata_url is not None
255
- response = self .session .get (link .metadata_url )
256
- distribution = pkginfo .Distribution ()
257
- if link .metadata_hash_name is not None :
258
- metadata_hash = getattr (hashlib , link .metadata_hash_name )(
259
- response .text .encode ()
260
- ).hexdigest ()
261
-
262
- if metadata_hash != link .metadata_hash :
263
- self ._log (
264
- f"Metadata file hash ({ metadata_hash } ) does not match"
265
- f" expected hash ({ link .metadata_hash } )."
266
- f" Metadata file for { link .filename } will be ignored." ,
267
- level = "warning" ,
268
- )
269
- continue
270
-
271
- distribution .parse (response .content )
272
- metadata [link .url ] = distribution
273
- except requests .HTTPError :
274
- self ._log (
275
- f"Failed to retrieve metadata at { link .metadata_url } " ,
276
- level = "warning" ,
277
- )
278
-
279
- if link .is_wheel :
280
- urls ["bdist_wheel" ].append (link .url )
281
- elif link .filename .endswith (
282
- (".tar.gz" , ".zip" , ".bz2" , ".xz" , ".Z" , ".tar" )
283
- ):
284
- urls ["sdist" ].append (link .url )
285
-
286
- return self ._get_info_from_urls (urls , metadata )
270
+ return self ._get_info_from_metadata (sdists [0 ]) or self ._get_info_from_sdist (
271
+ sdists [0 ]
272
+ )
287
273
288
274
def _links_to_data (self , links : list [Link ], data : PackageInfo ) -> dict [str , Any ]:
289
275
if not links :
0 commit comments