Skip to content

Commit 9630d01

Browse files
committed
Add support for download URLs
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 2b8134a commit 9630d01

7 files changed

Lines changed: 294 additions & 74 deletions

src/python_inspector/resolution.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,27 @@ def get_dependencies(self, candidate):
384384
return list(self._iter_dependencies(candidate))
385385

386386

387+
def get_wheel_download_urls(purl, repos, environment, python_version):
388+
"""
389+
Return a list of download urls for the given purl.
390+
"""
391+
for repo in repos:
392+
for wheel in utils_pypi.get_supported_and_valid_wheels(
393+
repo, purl.name, purl.version, environment, python_version
394+
):
395+
yield wheel.download_url
396+
397+
398+
def get_sdist_download_url(purl, repos, python_version):
399+
"""
400+
Return a list of download urls for the given purl.
401+
"""
402+
for repo in repos:
403+
sdist = utils_pypi.get_valid_sdist(repo, purl.name, purl.version, python_version)
404+
if sdist:
405+
return sdist.download_url
406+
407+
387408
def get_all_srcs(mapping, graph):
388409
"""
389410
Return a list of all sources in the graph.
@@ -412,7 +433,7 @@ def dfs(mapping, graph, src):
412433
)
413434

414435

415-
def format_resolution(results, as_tree=False):
436+
def format_resolution(results, environment, repos, as_tree=False):
416437
"""
417438
Return a formatted resolution either as a tree or parent/children.
418439
"""
@@ -437,7 +458,17 @@ def format_resolution(results, as_tree=False):
437458
)
438459
dependencies.append(str(dep_purl))
439460
dependencies.sort()
440-
parent_children = dict(package=str(parent_purl), dependencies=dependencies)
461+
python_version = get_python_version_from_env_tag(environment.python_version)
462+
wheel_urls = list(
463+
get_wheel_download_urls(parent_purl, repos, environment, python_version)
464+
)
465+
sdist_url = get_sdist_download_url(parent_purl, repos, python_version)
466+
parent_children = dict(
467+
package=str(parent_purl),
468+
dependencies=dependencies,
469+
wheel_urls=list(dict.fromkeys(wheel_urls)),
470+
sdist_url=sdist_url,
471+
)
441472
as_parent_children.append(parent_children)
442473
as_parent_children.sort(key=lambda d: d["package"])
443474
return as_parent_children
@@ -477,5 +508,5 @@ def get_resolved_dependencies(
477508
reporter=BaseReporter(),
478509
)
479510
results = resolver.resolve(requirements=requirements, max_rounds=max_rounds)
480-
results = format_resolution(results, as_tree=as_tree)
511+
results = format_resolution(results, as_tree=as_tree, environment=environment, repos=repos)
481512
return results

src/python_inspector/utils_pypi.py

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -219,28 +219,17 @@ def download_wheel(
219219
repos = DEFAULT_PYPI_REPOS
220220

221221
fetched_wheel_filenames = []
222-
223222
for repo in repos:
224-
package = repo.get_package_version(name=name, version=version)
225-
if not package:
226-
if TRACE_DEEP:
227-
print(f" download_wheel: No package in {repo.index_url} for {name}=={version}")
228-
continue
229-
supported_wheels = list(package.get_supported_wheels(environment=environment))
230-
if not supported_wheels:
223+
supported_and_valid_wheels = get_supported_and_valid_wheels(
224+
repo, name, version, environment, python_version
225+
)
226+
if not supported_and_valid_wheels:
231227
if TRACE_DEEP:
232228
print(
233-
f" download_wheel: No supported wheel for {name}=={version}: {environment} "
229+
f" download_wheel: No supported and valid wheel for {name}=={version}: {environment} "
234230
)
235231
continue
236-
237-
for wheel in supported_wheels:
238-
if not valid_distribution(wheel, python_version):
239-
continue
240-
if TRACE_DEEP:
241-
print(
242-
f" download_wheel: Getting wheel from index (or cache): {wheel.download_url}"
243-
)
232+
for wheel in supported_and_valid_wheels:
244233
fetched_wheel_filename = wheel.download(
245234
dest_dir=dest_dir,
246235
verbose=verbose,
@@ -251,10 +240,62 @@ def download_wheel(
251240
if fetched_wheel_filenames:
252241
# do not futher fetch from other repos if we find in first, typically PyPI
253242
break
254-
255243
return fetched_wheel_filenames
256244

257245

246+
def get_valid_sdist(repo, name, version, python_version=DEFAULT_PYTHON_VERSION):
247+
package = repo.get_package_version(name=name, version=version)
248+
if not package:
249+
if TRACE_DEEP:
250+
print(
251+
print(f" get_valid_sdist: No package in {repo.index_url} for {name}=={version}")
252+
)
253+
return
254+
sdist = package.sdist
255+
if not sdist:
256+
if TRACE_DEEP:
257+
print(f" get_valid_sdist: No sdist for {name}=={version}")
258+
return
259+
if not valid_distribution(sdist, python_version):
260+
return
261+
if TRACE_DEEP:
262+
print(f" get_valid_sdist: Getting sdist from index (or cache): {sdist.download_url}")
263+
return sdist
264+
265+
266+
def get_supported_and_valid_wheels(
267+
repo, name, version, environment, python_version=DEFAULT_PYTHON_VERSION
268+
) -> List:
269+
"""
270+
Return a list of wheels matching the ``environment`` Environment constraints.
271+
"""
272+
package = repo.get_package_version(name=name, version=version)
273+
if not package:
274+
if TRACE_DEEP:
275+
print(
276+
f" get_supported_and_valid_wheels: No package in {repo.index_url} for {name}=={version}"
277+
)
278+
return []
279+
supported_wheels = list(package.get_supported_wheels(environment=environment))
280+
if not supported_wheels:
281+
if TRACE_DEEP:
282+
print(
283+
f" get_supported_and_valid_wheels: No supported wheel for {name}=={version}: {environment}"
284+
)
285+
return []
286+
wheels = []
287+
for wheel in supported_wheels:
288+
if not valid_distribution(wheel, python_version):
289+
continue
290+
if TRACE_DEEP:
291+
print(
292+
f""" get_supported_and_valid_wheels: Getting wheel from index (or cache):
293+
{wheel.download_url}"""
294+
)
295+
wheels.append(wheel)
296+
return wheels
297+
298+
258299
def valid_distribution(distribution, python_version):
259300
"""
260301
Return True if distribution is a valid distribution for the given Python version.
@@ -289,22 +330,12 @@ def download_sdist(
289330
fetched_sdist_filename = None
290331

291332
for repo in repos:
292-
package = repo.get_package_version(name=name, version=version)
293-
294-
if not package:
295-
if TRACE_DEEP:
296-
print(f" download_sdist: No package in {repo.index_url} for {name}=={version}")
297-
continue
298-
sdist = package.sdist
333+
sdist = get_valid_sdist(repo, name, version, python_version=DEFAULT_PYTHON_VERSION)
299334
if not sdist:
300335
if TRACE_DEEP:
301-
print(f" download_sdist: No sdist for {name}=={version}")
336+
print(f" download_sdist: No valid sdist for {name}=={version}")
302337
continue
303-
if not valid_distribution(sdist, python_version):
304-
continue
305-
if TRACE_DEEP:
306-
print(f" download_sdist: Getting sdist from index (or cache): {sdist.download_url}")
307-
fetched_sdist_filename = package.sdist.download(
338+
fetched_sdist_filename = sdist.download(
308339
dest_dir=dest_dir,
309340
verbose=verbose,
310341
echo_func=echo_func,

tests/data/default-url-expected.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
"resolved_dependencies": [
2929
{
3030
"package": "pkg:pypi/zipp@3.8.0",
31-
"dependencies": []
31+
"dependencies": [],
32+
"wheel_urls": [],
33+
"sdist_url": null
3234
}
3335
]
3436
}

0 commit comments

Comments
 (0)