From 3fe5061682ed805db18a4104cd186b5e9eea9a8a Mon Sep 17 00:00:00 2001 From: Adam Goldschmidt Date: Sun, 20 Jan 2019 13:09:28 +0200 Subject: [PATCH 1/3] conservative check for known exceptions in subprocess stderr. --- pipenv/core.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 768e7ee73a..9dd2784ec3 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -925,9 +925,17 @@ def do_create_virtualenv(python=None, site_packages=False, pypi_mirror=None): ) click.echo(crayons.blue("{0}".format(c.out)), err=True) if c.returncode != 0: - sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(u"Failed creating virtual environment")) + sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Failed creating virtual environment")) + known_exceptions = { + "PermissionError": "Permission denied:", + } + # PermissionError - hide the traceback for better UX + for partition in (part + for e, part in known_exceptions.items() if e in c.err): + known_exceptions_partition = c.err.rpartition(partition) + c.err = "{} {}".format(known_exceptions_partition[1], known_exceptions_partition[2]) raise exceptions.VirtualenvCreationException( - extra=[crayons.blue("{0}".format(c.err)),] + extra=[crayons.red("{0}".format(c.err)),] ) else: From f52abe32bce46de4991a6376a0a1ec0a8bf0d73f Mon Sep 17 00:00:00 2001 From: Adam Goldschmidt Date: Fri, 25 Jan 2019 11:35:22 +0200 Subject: [PATCH 2/3] add behavior rst --- news/2553.behavior.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/2553.behavior.rst diff --git a/news/2553.behavior.rst b/news/2553.behavior.rst new file mode 100644 index 0000000000..d66edfa2fa --- /dev/null +++ b/news/2553.behavior.rst @@ -0,0 +1 @@ +Make conservative checks of known exceptions when subprocess returns output, so user won't see the whole traceback - just the error. \ No newline at end of file From 2d75f1af53238a89d5eddbe1f83fb2ed244e6d4f Mon Sep 17 00:00:00 2001 From: Adam Goldschmidt Date: Mon, 11 Mar 2019 09:35:17 +0200 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20prettify=5Fexc?= =?UTF-8?q?=20method=20to=20handle=20known=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit catch known errors in stderr and display them correctly --- pipenv/core.py | 11 ++--------- pipenv/exceptions.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 9dd2784ec3..76ce7e8b47 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -926,16 +926,9 @@ def do_create_virtualenv(python=None, site_packages=False, pypi_mirror=None): click.echo(crayons.blue("{0}".format(c.out)), err=True) if c.returncode != 0: sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Failed creating virtual environment")) - known_exceptions = { - "PermissionError": "Permission denied:", - } - # PermissionError - hide the traceback for better UX - for partition in (part - for e, part in known_exceptions.items() if e in c.err): - known_exceptions_partition = c.err.rpartition(partition) - c.err = "{} {}".format(known_exceptions_partition[1], known_exceptions_partition[2]) + error = c.err if environments.is_verbose() else exceptions.prettify_exc(c.err) raise exceptions.VirtualenvCreationException( - extra=[crayons.red("{0}".format(c.err)),] + extra=[crayons.red("{0}".format(error)),] ) else: diff --git a/pipenv/exceptions.py b/pipenv/exceptions.py index 000c57153d..495a46bfbb 100644 --- a/pipenv/exceptions.py +++ b/pipenv/exceptions.py @@ -18,7 +18,11 @@ ) from .vendor.click.types import Path from .vendor.click.utils import echo as click_echo +import vistir +KNOWN_EXCEPTIONS = { + "PermissionError": "Permission denied:", +} def handle_exception(exc_type, exception, traceback, hook=sys.excepthook): if environments.is_verbose() or not issubclass(exc_type, ClickException): @@ -402,3 +406,18 @@ def __init__(self, req=None): ) extra = [crayons.normal(decode_for_output(str(req)))] super(RequirementError, self).__init__(message, extra=extra) + super(ResolutionFailure, self).__init__(fix_utf8(message), extra=extra) + + +def prettify_exc(error): + """Catch known errors and prettify them instead of showing the + entire traceback, for better UX""" + matched_exceptions = [k for k in KNOWN_EXCEPTIONS.keys() if k in error] + if not matched_exceptions: + return "{}".format(vistir.misc.decode_for_output(error)) + errors = [] + for match in matched_exceptions: + _, error, info = error.rpartition(KNOWN_EXCEPTIONS[match]) + errors.append("{} {}".format(error, info)) + + return "\n".join(errors)