Skip to content

Commit 49df2cb

Browse files
committed
Plan for verbose output
Signed-off-by: Philippe Ombredanne <pombredanne@nexb.com>
1 parent da7057f commit 49df2cb

1 file changed

Lines changed: 124 additions & 22 deletions

File tree

src/python_inspector/utils_pypi.py

Lines changed: 124 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ def get_python_dot_version(version):
164164

165165
CACHE_THIRDPARTY_DIR = ".cache/thirdparty"
166166

167-
168167
################################################################################
169168

170169
PYPI_SIMPLE_URL = "https://pypi.org/simple"
@@ -190,7 +189,15 @@ class DistributionNotFound(Exception):
190189
pass
191190

192191

193-
def download_wheel(name, version, environment, dest_dir=CACHE_THIRDPARTY_DIR, repos=tuple()):
192+
def download_wheel(
193+
name,
194+
version,
195+
environment,
196+
dest_dir=CACHE_THIRDPARTY_DIR,
197+
repos=tuple(),
198+
verbose=False,
199+
echo_func=None,
200+
):
194201
"""
195202
Download the wheels binary distribution(s) of package ``name`` and
196203
``version`` matching the ``environment`` Environment constraints into the
@@ -226,7 +233,11 @@ def download_wheel(name, version, environment, dest_dir=CACHE_THIRDPARTY_DIR, re
226233
print(
227234
f" download_wheel: Getting wheel from index (or cache): {wheel.download_url}"
228235
)
229-
fetched_wheel_filename = wheel.download(dest_dir=dest_dir)
236+
fetched_wheel_filename = wheel.download(
237+
dest_dir=dest_dir,
238+
verbose=verbose,
239+
echo_func=echo_func,
240+
)
230241
fetched_wheel_filenames.append(fetched_wheel_filename)
231242

232243
if fetched_wheel_filenames:
@@ -236,7 +247,14 @@ def download_wheel(name, version, environment, dest_dir=CACHE_THIRDPARTY_DIR, re
236247
return fetched_wheel_filenames
237248

238249

239-
def download_sdist(name, version, dest_dir=CACHE_THIRDPARTY_DIR, repos=tuple()):
250+
def download_sdist(
251+
name,
252+
version,
253+
dest_dir=CACHE_THIRDPARTY_DIR,
254+
repos=tuple(),
255+
verbose=False,
256+
echo_func=None,
257+
):
240258
"""
241259
Download the sdist source distribution of package ``name`` and ``version``
242260
into the ``dest_dir`` directory. Return a fetched filename or None.
@@ -267,7 +285,11 @@ def download_sdist(name, version, dest_dir=CACHE_THIRDPARTY_DIR, repos=tuple()):
267285

268286
if TRACE_DEEP:
269287
print(f" download_sdist: Getting sdist from index (or cache): {sdist.download_url}")
270-
fetched_sdist_filename = package.sdist.download(dest_dir=dest_dir)
288+
fetched_sdist_filename = package.sdist.download(
289+
dest_dir=dest_dir,
290+
verbose=verbose,
291+
echo_func=echo_func,
292+
)
271293

272294
if fetched_sdist_filename:
273295
# do not futher fetch from other repos if we find in first, typically PyPI
@@ -522,7 +544,12 @@ def get_best_download_url(self, repos=tuple()):
522544
f" get_best_download_url: {self.filename} not found in {repo.index_url}"
523545
)
524546

525-
def download(self, dest_dir=CACHE_THIRDPARTY_DIR):
547+
def download(
548+
self,
549+
dest_dir=CACHE_THIRDPARTY_DIR,
550+
verbose=False,
551+
echo_func=None,
552+
):
526553
"""
527554
Download this distribution into `dest_dir` directory.
528555
Return the fetched filename.
@@ -540,6 +567,8 @@ def download(self, dest_dir=CACHE_THIRDPARTY_DIR):
540567
dest_dir=dest_dir,
541568
filename=self.filename,
542569
as_text=False,
570+
verbose=verbose,
571+
echo_func=echo_func,
543572
)
544573
return self.filename
545574

@@ -1358,7 +1387,12 @@ class PypiSimpleRepository:
13581387
repr=False,
13591388
)
13601389

1361-
def _get_package_versions_map(self, name):
1390+
def _get_package_versions_map(
1391+
self,
1392+
name,
1393+
verbose=False,
1394+
echo_func=None,
1395+
):
13621396
"""
13631397
Return a mapping of all available PypiPackage version for this package name.
13641398
The mapping may be empty. It is ordered by version from oldest to newest
@@ -1369,8 +1403,12 @@ def _get_package_versions_map(self, name):
13691403
if not versions and normalized_name not in self.fetched_package_normalized_names:
13701404
self.fetched_package_normalized_names.add(normalized_name)
13711405
try:
1372-
links = self.fetch_links(normalized_name=normalized_name)
1373-
# note that thsi is sorted so the mapping is also sorted
1406+
links = self.fetch_links(
1407+
normalized_name=normalized_name,
1408+
verbose=verbose,
1409+
echo_func=echo_func,
1410+
)
1411+
# note that this is sorted so the mapping is also sorted
13741412
versions = {
13751413
package.version: package
13761414
for package in PypiPackage.packages_from_many_paths_or_urls(paths_or_urls=links)
@@ -1385,27 +1423,59 @@ def _get_package_versions_map(self, name):
13851423

13861424
return versions
13871425

1388-
def get_package_versions(self, name):
1426+
def get_package_versions(
1427+
self,
1428+
name,
1429+
verbose=False,
1430+
echo_func=None,
1431+
):
13891432
"""
13901433
Return a mapping of all available PypiPackage version as{version:
13911434
package} for this package name. The mapping may be empty but not None.
13921435
It is sorted by version from oldest to newest.
13931436
"""
1394-
return dict(self._get_package_versions_map(name))
1437+
return dict(
1438+
self._get_package_versions_map(
1439+
name=name,
1440+
verbose=verbose,
1441+
echo_func=echo_func,
1442+
)
1443+
)
13951444

1396-
def get_package_version(self, name, version=None):
1445+
def get_package_version(
1446+
self,
1447+
name,
1448+
version=None,
1449+
verbose=False,
1450+
echo_func=None,
1451+
):
13971452
"""
13981453
Return the PypiPackage with name and version or None.
13991454
Return the latest PypiPackage version if version is None.
14001455
"""
14011456
if not version:
1402-
versions = list(self._get_package_versions_map(name).values())
1457+
versions = list(
1458+
self._get_package_versions_map(
1459+
name=name,
1460+
verbose=verbose,
1461+
echo_func=echo_func,
1462+
).values()
1463+
)
14031464
# return the latest version
14041465
return versions and versions[-1]
14051466
else:
1406-
return self._get_package_versions_map(name).get(version)
1407-
1408-
def fetch_links(self, normalized_name):
1467+
return self._get_package_versions_map(
1468+
name=name,
1469+
verbose=verbose,
1470+
echo_func=echo_func,
1471+
).get(version)
1472+
1473+
def fetch_links(
1474+
self,
1475+
normalized_name,
1476+
verbose=False,
1477+
echo_func=None,
1478+
):
14091479
"""
14101480
Return a list of download link URLs found in a PyPI simple index for package
14111481
name using the `index_url` of this repository.
@@ -1415,6 +1485,8 @@ def fetch_links(self, normalized_name):
14151485
path_or_url=package_url,
14161486
as_text=True,
14171487
force=not self.use_cached_index,
1488+
verbose=verbose,
1489+
echo_func=echo_func,
14181490
)
14191491
links = collect_urls(text)
14201492
# TODO: keep sha256
@@ -1427,7 +1499,6 @@ def fetch_links(self, normalized_name):
14271499
DEFAULT_PYPI_REPOS = (PYPI_PUBLIC_REPO,)
14281500
DEFAULT_PYPI_REPOS_BY_URL = {r.index_url: r for r in DEFAULT_PYPI_REPOS}
14291501

1430-
14311502
################################################################################
14321503
#
14331504
# Basic file and URL-based operations using a persistent file-based Cache
@@ -1447,7 +1518,14 @@ class Cache:
14471518
def __attrs_post_init__(self):
14481519
os.makedirs(self.directory, exist_ok=True)
14491520

1450-
def get(self, path_or_url, as_text=True, force=False):
1521+
def get(
1522+
self,
1523+
path_or_url,
1524+
as_text=True,
1525+
force=False,
1526+
verbose=False,
1527+
echo_func=None,
1528+
):
14511529
"""
14521530
Return the content fetched from a ``path_or_url`` through the cache.
14531531
Raise an Exception on errors. Treats the content as text if as_text is
@@ -1460,7 +1538,12 @@ def get(self, path_or_url, as_text=True, force=False):
14601538
if force or not os.path.exists(cached):
14611539
if TRACE_DEEP:
14621540
print(f" FILE CACHE MISS: {path_or_url}")
1463-
content = get_file_content(path_or_url=path_or_url, as_text=as_text)
1541+
content = get_file_content(
1542+
path_or_url=path_or_url,
1543+
as_text=as_text,
1544+
verbose=verbose,
1545+
echo_func=echo_func,
1546+
)
14641547
wmode = "w" if as_text else "wb"
14651548
with open(cached, wmode) as fo:
14661549
fo.write(content)
@@ -1474,15 +1557,25 @@ def get(self, path_or_url, as_text=True, force=False):
14741557
CACHE = Cache()
14751558

14761559

1477-
def get_file_content(path_or_url, as_text=True):
1560+
def get_file_content(
1561+
path_or_url,
1562+
as_text=True,
1563+
verbose=False,
1564+
echo_func=None,
1565+
):
14781566
"""
14791567
Fetch and return the content at `path_or_url` from either a local path or a
14801568
remote URL. Return the content as bytes is `as_text` is False.
14811569
"""
14821570
if path_or_url.startswith("https://"):
14831571
if TRACE_DEEP:
14841572
print(f"Fetching: {path_or_url}")
1485-
_headers, content = get_remote_file_content(url=path_or_url, as_text=as_text)
1573+
_headers, content = get_remote_file_content(
1574+
url=path_or_url,
1575+
as_text=as_text,
1576+
verbose=verbose,
1577+
echo_func=echo_func,
1578+
)
14861579
return content
14871580

14881581
elif path_or_url.startswith("file://") or (
@@ -1517,6 +1610,8 @@ def get_remote_file_content(
15171610
headers_only=False,
15181611
headers=None,
15191612
_delay=0,
1613+
verbose=False,
1614+
echo_func=None,
15201615
):
15211616
"""
15221617
Fetch and return a tuple of (headers, content) at `url`. Return content as a
@@ -1532,7 +1627,10 @@ def get_remote_file_content(
15321627
# using a GET with stream=True ensure we get the the final header from
15331628
# several redirects and that we can ignore content there. A HEAD request may
15341629
# not get us this last header
1535-
print(f" DOWNLOADING: {url}")
1630+
if verbose and not echo_func:
1631+
echo_func = print
1632+
if verbose:
1633+
echo_func(f"DOWNLOADING: {url}")
15361634
with requests.get(url, allow_redirects=True, stream=True, headers=headers) as response:
15371635
status = response.status_code
15381636
if status != requests.codes.ok: # NOQA
@@ -1561,6 +1659,8 @@ def fetch_and_save(
15611659
dest_dir,
15621660
filename,
15631661
as_text=True,
1662+
verbose=False,
1663+
echo_func=None,
15641664
):
15651665
"""
15661666
Fetch content at ``path_or_url`` URL or path and save this to
@@ -1571,6 +1671,8 @@ def fetch_and_save(
15711671
content = CACHE.get(
15721672
path_or_url=path_or_url,
15731673
as_text=as_text,
1674+
verbose=verbose,
1675+
echo_func=echo_func,
15741676
)
15751677
output = os.path.join(dest_dir, filename)
15761678
wmode = "w" if as_text else "wb"

0 commit comments

Comments
 (0)