@@ -22,6 +22,7 @@ load("//python/private:envsubst.bzl", "envsubst")
2222load ("//python/private:normalize_name.bzl" , "normalize_name" )
2323load ("//python/private:text_util.bzl" , "render" )
2424load (":parse_simpleapi_html.bzl" , "parse_simpleapi_html" )
25+ load (":urllib.bzl" , "urllib" )
2526
2627def simpleapi_download (
2728 ctx ,
@@ -92,13 +93,14 @@ def simpleapi_download(
9293 sources = [pkg for pkg in attr .sources if pkg not in found_on_index ]
9394 for pkg in sources :
9495 pkg_normalized = normalize_name (pkg )
96+ url = urllib .strip_empty_path_segments ("{index_url}/{distribution}/" .format (
97+ index_url = index_url_overrides .get (pkg_normalized , index_url ).rstrip ("/" ),
98+ distribution = pkg ,
99+ ))
95100 result = read_simpleapi (
96101 ctx = ctx ,
97- url = "{}/{}/" .format (
98- index_url_overrides .get (pkg_normalized , index_url ).rstrip ("/" ),
99- pkg ,
100- ),
101102 attr = attr ,
103+ url = url ,
102104 cache = cache ,
103105 get_auth = get_auth ,
104106 ** download_kwargs
@@ -108,9 +110,10 @@ def simpleapi_download(
108110 async_downloads [pkg ] = struct (
109111 pkg_normalized = pkg_normalized ,
110112 wait = result .wait ,
113+ url = url ,
111114 )
112115 elif result .success :
113- contents [pkg_normalized ] = result .output
116+ contents [pkg_normalized ] = _with_index_url ( url , result .output )
114117 found_on_index [pkg ] = index_url
115118
116119 if not async_downloads :
@@ -122,7 +125,7 @@ def simpleapi_download(
122125 result = download .wait ()
123126
124127 if result .success :
125- contents [download .pkg_normalized ] = result .output
128+ contents [download .pkg_normalized ] = _with_index_url ( download . url , result .output )
126129 found_on_index [pkg ] = index_url
127130
128131 failed_sources = [pkg for pkg in attr .sources if pkg not in found_on_index ]
@@ -168,14 +171,14 @@ def _read_simpleapi(ctx, url, attr, cache, get_auth = None, **download_kwargs):
168171
169172 Args:
170173 ctx: The module_ctx or repository_ctx.
171- url: str, the url parameter that can be passed to ctx.download.
174+ url: {type}` str` , the url parameter that can be passed to ctx.download.
172175 attr: The attribute that contains necessary info for downloading. The
173176 following attributes must be present:
174- * envsubst: The envsubst values for performing substitutions in the URL.
175- * netrc: The netrc parameter for ctx.download, see http_file for docs.
177+ * envsubst: {type}`dict[str, str]` for performing substitutions in the URL.
178+ * netrc: The netrc parameter for ctx.download, see {obj}` http_file` for docs.
176179 * auth_patterns: The auth_patterns parameter for ctx.download, see
177- http_file for docs.
178- cache: A dict for storing the results .
180+ {obj}` http_file` for docs.
181+ cache: {type}`struct` the `pypi_cache` instance .
179182 get_auth: A function to get auth information. Used in tests.
180183 **download_kwargs: Any extra params to ctx.download.
181184 Note that output and auth will be passed for you.
@@ -189,9 +192,9 @@ def _read_simpleapi(ctx, url, attr, cache, get_auth = None, **download_kwargs):
189192 # them to ctx.download if we want to correctly handle the relative URLs.
190193 # TODO: Add a test that env subbed index urls do not leak into the lock file.
191194
192- real_url = strip_empty_path_segments (envsubst (url , attr .envsubst , ctx .getenv ))
195+ real_url = urllib . strip_empty_path_segments (envsubst (url , attr .envsubst , ctx .getenv ))
193196
194- cache_key = real_url
197+ cache_key = ( url , real_url )
195198 cached_result = cache .get (cache_key )
196199 if cached_result :
197200 return struct (success = True , output = cached_result )
@@ -225,41 +228,43 @@ def _read_simpleapi(ctx, url, attr, cache, get_auth = None, **download_kwargs):
225228 if download_kwargs .get ("block" ) == False :
226229 # Simulate the same API as ctx.download has
227230 return struct (
228- wait = lambda : _read_index_result (ctx , download .wait (), output , real_url , cache , cache_key ),
231+ wait = lambda : _read_index_result (
232+ ctx ,
233+ result = download .wait (),
234+ output = output ,
235+ cache = cache ,
236+ cache_key = cache_key ,
237+ ),
229238 )
230239
231- return _read_index_result (ctx , download , output , real_url , cache , cache_key )
232-
233- def strip_empty_path_segments (url ):
234- """Removes empty path segments from a URL. Does nothing for urls with no scheme.
235-
236- Public only for testing.
237-
238- Args:
239- url: The url to remove empty path segments from
240-
241- Returns:
242- The url with empty path segments removed and any trailing slash preserved.
243- If the url had no scheme it is returned unchanged.
244- """
245- scheme , _ , rest = url .partition ("://" )
246- if rest == "" :
247- return url
248- stripped = "/" .join ([p for p in rest .split ("/" ) if p ])
249- if url .endswith ("/" ):
250- return "{}://{}/" .format (scheme , stripped )
251- else :
252- return "{}://{}" .format (scheme , stripped )
240+ return _read_index_result (
241+ ctx ,
242+ result = download ,
243+ output = output ,
244+ cache = cache ,
245+ cache_key = cache_key ,
246+ )
253247
254- def _read_index_result (ctx , result , output , url , cache , cache_key ):
248+ def _read_index_result (ctx , * , result , output , cache , cache_key ):
255249 if not result .success :
256250 return struct (success = False )
257251
258252 content = ctx .read (output )
259253
260- output = parse_simpleapi_html (url = url , content = content )
254+ output = parse_simpleapi_html (content = content )
261255 if output :
262256 cache .setdefault (cache_key , output )
263- return struct (success = True , output = output , cache_key = cache_key )
257+ return struct (success = True , output = output )
264258 else :
265259 return struct (success = False )
260+
261+ def _with_index_url (index_url , values ):
262+ if not values :
263+ return values
264+
265+ return struct (
266+ sdists = values .sdists ,
267+ whls = values .whls ,
268+ sha256s_by_version = values .sha256s_by_version ,
269+ index_url = index_url ,
270+ )
0 commit comments