From 52ae6d802eedb33b065886faa245da0fc294298d Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Wed, 10 Feb 2016 23:36:08 +0000 Subject: [PATCH 1/5] Add *.pyc and *.egg-info/ to .gitignore Tox creates `peep.egg-info/` and `.pyc` files. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a2cb03f..d65483a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /.tox +/*.egg-info /pip-log.txt +*.pyc From 0def721cd9eb54c610044fa982c10329ffe0669d Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Wed, 10 Feb 2016 23:37:10 +0000 Subject: [PATCH 2/5] Give handled and unhandled errors different exit codes To make it easier to test whether an unhandled exception has occurred. --- peep.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/peep.py b/peep.py index 41cfaf2..003624e 100755 --- a/peep.py +++ b/peep.py @@ -122,6 +122,7 @@ def iter(self, ret, *args, **kwargs): SOMETHING_WENT_WRONG = 1 # "Traditional" for command-line errors according to optparse docs: COMMAND_LINE_ERROR = 2 +UNHANDLED_EXCEPTION = 3 ARCHIVE_EXTENSIONS = ('.tar.bz2', '.tar.gz', '.tgz', '.tar', '.zip') @@ -965,4 +966,4 @@ def exception_handler(exc_type, exc_value, exc_tb): exit(main()) except Exception: exception_handler(*sys.exc_info()) - exit(SOMETHING_WENT_WRONG) + exit(UNHANDLED_EXCEPTION) From f7657f33f98f7d68a9edd001868f1e238b57ee3e Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 11 Feb 2016 00:42:27 +0000 Subject: [PATCH 3/5] Handle pip InstallationError exceptions more gracefully `InstallationError` covers various "not peep's fault" errors, including no valid distribution being found for the requested package version, the requirements file being missing, or the contents not being valid: https://github.com/pypa/pip/blob/8.0.2/pip/exceptions.py https://github.com/pypa/pip/search?q="raise+InstallationError"&type=Code Previously these would have resulted in the "peep had a problem" output, which requests that users file an issue - when these cases are not peep's fault. Now the original pip error is output as-is, without the peep traceback. The tests rely on the exit code for unhandled exceptions being different from that for handled exceptions (fixed in the previous commit). Fixes #117. --- README.rst | 5 +++++ peep.py | 3 ++- tests/__init__.py | 27 +++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9b78dd7..47643f6 100644 --- a/README.rst +++ b/README.rst @@ -264,6 +264,11 @@ If you're using pip 1.5, pass the ``--no-use-wheel`` argument. Version History =============== +Unreleased: + * The "peep had a problem" traceback is no longer output for several cases + of pip installation errors that were not peep's fault. (For instance the + specified package version or requirements file not existing.) + 3.1 * Print the name each new requirements file we encounter during ``peep port``. This helps untangle the mess if your files use includes. (pmac) diff --git a/peep.py b/peep.py index 003624e..33e1990 100755 --- a/peep.py +++ b/peep.py @@ -86,6 +86,7 @@ def activate(specifier): from pip.util import url_to_path # 0.7.0 except ImportError: from pip.util import url_to_filename as url_to_path # 0.6.2 +from pip.exceptions import InstallationError from pip.index import PackageFinder, Link try: from pip.log import logger @@ -885,7 +886,7 @@ def peep_install(argv): first_every_last(buckets[SatisfiedReq], *printers) return ITS_FINE_ITS_FINE - except (UnsupportedRequirementError, DownloadError) as exc: + except (UnsupportedRequirementError, InstallationError, DownloadError) as exc: out(str(exc)) return SOMETHING_WENT_WRONG finally: diff --git a/tests/__init__.py b/tests/__init__.py index 152c2fe..d81edb8 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -339,6 +339,33 @@ def test_missing(self): else: self.fail("Peep exited successfully but shouldn't have.") + def test_distribution_not_found(self): + """Check that pip's DistributionNotFound exception (when a non-existent + version is specified) is handled gracefully.""" + with running_setup_py(False): + try: + self.install_from_string("""useless==9.9.9""") + except CalledProcessError as exc: + eq_(exc.returncode, SOMETHING_WENT_WRONG) + else: + self.fail("Peep exited successfully but shouldn't have.") + + def test_missing_requirements_file(self): + """Check that pip's InstallationError exception (when the specified + requirements file doesn't exist) is handled gracefully.""" + try: + activate('pip>=0.8.3') + except RuntimeError: + raise SkipTest("This version of pip is so old that it doesn't even " + "handle the IOError opening the file itself properly.") + with running_setup_py(False): + try: + self.install_from_path('nonexistent.txt') + except CalledProcessError as exc: + eq_(exc.returncode, SOMETHING_WENT_WRONG) + else: + self.fail("Peep exited successfully but shouldn't have.") + def test_upgrade(self): """Make sure peep installing a GitHub-sourced tarball installs it, even if its version hasn't changed. From 7477689461518189675c46411a7045e3d930e993 Mon Sep 17 00:00:00 2001 From: jotes Date: Tue, 2 Feb 2016 00:13:52 +0100 Subject: [PATCH 4/5] The 'port' command returns a package name instead of the original link. --- peep.py | 2 +- tests/__init__.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/peep.py b/peep.py index 41cfaf2..aa983d3 100755 --- a/peep.py +++ b/peep.py @@ -920,7 +920,7 @@ def peep_port(paths): if not hashes: print(req.req) else: - print('%s' % req.req, end='') + print('%s' % (req.link if getattr(req, 'link', None) else req.req), end='') for hash in hashes: print(' \\') print(' --hash=sha256:%s' % hash, end='') diff --git a/tests/__init__.py b/tests/__init__.py index 152c2fe..69aa4ed 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -376,11 +376,16 @@ def test_port(self): # We can't get the package name from URL-based requirements before pip # 1.0. Tolerate it so we can at least test everything else: try: - activate('pip>=1.0.1') + activate('pip>=6.1.0') except RuntimeError: - schema_package_name = 'None' + try: + activate('pip>=1.0.1') + except RuntimeError: + schema_package_name = 'None' + else: + schema_package_name = 'schema' else: - schema_package_name = 'schema' + schema_package_name = 'https://github.com/erikrose/schema/archive/99dc4130f0f05fd3c2d4bc6663a2419851f3c90f.zip#egg=schema' reqs = """ # sha256: Jo-gDCfedW1xZj3WH3OkqNhydWm7G0dLLOYCBVOCaHI From fee44667067bc0b337cafef477dbcf842d422a81 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 16 Feb 2016 17:40:44 -0500 Subject: [PATCH 5/5] Bump version to 3.1.1, and bring version history up to date. --- README.rst | 8 +++++--- peep.py | 2 +- setup.py | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 47643f6..589fdc4 100644 --- a/README.rst +++ b/README.rst @@ -264,10 +264,12 @@ If you're using pip 1.5, pass the ``--no-use-wheel`` argument. Version History =============== -Unreleased: +3.1.1 * The "peep had a problem" traceback is no longer output for several cases - of pip installation errors that were not peep's fault. (For instance the - specified package version or requirements file not existing.) + of pip installation errors that were not peep's fault: for instance, the + specified package version or requirements file not existing. + * ``peep port`` now emits URLs for URL-based requirements, if you're using + pip 6.1.0 or greater. (jotes) 3.1 * Print the name each new requirements file we encounter during ``peep diff --git a/peep.py b/peep.py index 1bfaa94..eee823f 100755 --- a/peep.py +++ b/peep.py @@ -105,7 +105,7 @@ def iter(self, ret, *args, **kwargs): DownloadProgressBar = DownloadProgressSpinner = NullProgressBar -__version__ = 3, 1, 0 +__version__ = 3, 1, 1 try: from pip.index import FormatControl # noqa diff --git a/setup.py b/setup.py index 97f9c1c..610e242 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='peep', - version='3.1', + version='3.1.1', description='A "pip install" that is cryptographically guaranteed repeatable', long_description=open('README.rst').read(), author='Erik Rose',