From f69d4b7e41b8d40342133d5c8e43df7316e73993 Mon Sep 17 00:00:00 2001 From: Brian Rutledge Date: Sun, 27 Feb 2022 08:40:17 -0500 Subject: [PATCH] Use Rich for `print()` output (#878) * Use rich for print * Log warnings for retries * Log warning for gpg * Log warning for skipped packages --- tests/test_repository.py | 22 ++++++++-------------- twine/commands/register.py | 2 ++ twine/commands/upload.py | 11 ++++++----- twine/package.py | 11 +++++++---- twine/repository.py | 14 +++++--------- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/tests/test_repository.py b/tests/test_repository.py index 0c0098c7..11a8c4b3 100644 --- a/tests/test_repository.py +++ b/tests/test_repository.py @@ -230,7 +230,7 @@ def dictfunc(): default_repo.upload(package) -def test_upload_retry(tmpdir, default_repo, capsys): +def test_upload_retry(tmpdir, default_repo, caplog): """Print retry messages when the upload response indicates a server error.""" default_repo.disable_progress_bar = True @@ -254,33 +254,27 @@ def test_upload_retry(tmpdir, default_repo, capsys): # Upload with default max_redirects of 5 default_repo.upload(package) - msg = [ + assert caplog.messages == [ ( - "Uploading fake.whl\n" - 'Received "500: Internal server error" ' - f"Package upload appears to have failed. Retry {i} of 5" + 'Received "500: Internal server error"\n' + f"Package upload appears to have failed. Retry {i} of 5." ) for i in range(1, 6) ] - captured = capsys.readouterr() - assert captured.out == "\n".join(msg) + "\n" + caplog.clear() # Upload with custom max_redirects of 3 default_repo.upload(package, 3) - msg = [ + assert caplog.messages == [ ( - "Uploading fake.whl\n" - 'Received "500: Internal server error" ' - f"Package upload appears to have failed. Retry {i} of 3" + 'Received "500: Internal server error"\n' + f"Package upload appears to have failed. Retry {i} of 3." ) for i in range(1, 4) ] - captured = capsys.readouterr() - assert captured.out == "\n".join(msg) + "\n" - @pytest.mark.parametrize( "package_meta,repository_url,release_urls", diff --git a/twine/commands/register.py b/twine/commands/register.py index 19a6c3e2..69828640 100644 --- a/twine/commands/register.py +++ b/twine/commands/register.py @@ -16,6 +16,8 @@ import os.path from typing import List, cast +from rich import print + from twine import exceptions from twine import package as package_file from twine import settings diff --git a/twine/commands/upload.py b/twine/commands/upload.py index 47d3410b..d3e4b92d 100644 --- a/twine/commands/upload.py +++ b/twine/commands/upload.py @@ -18,6 +18,7 @@ from typing import Dict, List, cast import requests +from rich import print from twine import commands from twine import exceptions @@ -127,15 +128,15 @@ def upload(upload_settings: settings.Settings, dists: List[str]) -> None: uploaded_packages = [] for package in packages_to_upload: - skip_message = " Skipping {} because it appears to already exist".format( - package.basefilename + skip_message = ( + f"Skipping {package.basefilename} because it appears to already exist" ) # Note: The skip_existing check *needs* to be first, because otherwise # we're going to generate extra HTTP requests against a hardcoded # URL for no reason. if upload_settings.skip_existing and repository.package_is_uploaded(package): - print(skip_message) + logger.warning(skip_message) continue resp = repository.upload(package) @@ -154,7 +155,7 @@ def upload(upload_settings: settings.Settings, dists: List[str]) -> None: ) if skip_upload(resp, upload_settings.skip_existing, package): - print(skip_message) + logger.warning(skip_message) continue utils.check_status_code(resp, upload_settings.verbose) @@ -163,7 +164,7 @@ def upload(upload_settings: settings.Settings, dists: List[str]) -> None: release_urls = repository.release_urls(uploaded_packages) if release_urls: - print("\nView at:") + print("\n[green]View at:") for url in release_urls: print(url) diff --git a/twine/package.py b/twine/package.py index 0619ba6e..168f9665 100644 --- a/twine/package.py +++ b/twine/package.py @@ -13,6 +13,7 @@ # limitations under the License. import hashlib import io +import logging import os import re import subprocess @@ -20,6 +21,7 @@ import importlib_metadata import pkginfo +from rich import print from twine import exceptions from twine import wheel @@ -43,6 +45,8 @@ MetadataValue = Union[str, Sequence[str]] +logger = logging.getLogger(__name__) + def _safe_name(name: str) -> str: """Convert an arbitrary string to a standard distribution name. @@ -222,16 +226,15 @@ def run_gpg(cls, gpg_args: Tuple[str, ...]) -> None: except FileNotFoundError: if gpg_args[0] != "gpg": raise exceptions.InvalidSigningExecutable( - "{} executable not available.".format(gpg_args[0]) + f"{gpg_args[0]} executable not available." ) - print("gpg executable not available. Attempting fallback to gpg2.") + logger.warning("gpg executable not available. Attempting fallback to gpg2.") try: subprocess.check_call(("gpg2",) + gpg_args[1:]) except FileNotFoundError: - print("gpg2 executable not available.") raise exceptions.InvalidSigningExecutable( - "'gpg' or 'gpg2' executables not available. " + "'gpg' or 'gpg2' executables not available.\n" "Try installing one of these or specifying an executable " "with the --sign-with flag." ) diff --git a/twine/repository.py b/twine/repository.py index 087a2f31..ebc82bf1 100644 --- a/twine/repository.py +++ b/twine/repository.py @@ -21,6 +21,7 @@ import urllib3 from requests import adapters from requests_toolbelt.utils import user_agent +from rich import print import twine from twine import package as package_file @@ -192,15 +193,10 @@ def upload( return resp if 500 <= resp.status_code < 600: number_of_redirects += 1 - print( - 'Received "{status_code}: {reason}" Package upload ' - "appears to have failed. Retry {retry} of " - "{max_redirects}".format( - status_code=resp.status_code, - reason=resp.reason, - retry=number_of_redirects, - max_redirects=max_redirects, - ) + logger.warning( + f'Received "{resp.status_code}: {resp.reason}"' + "\nPackage upload appears to have failed." + f" Retry {number_of_redirects} of {max_redirects}." ) else: return resp