Skip to content

Commit

Permalink
87 rewrap 404 errors from pypiorg (#89)
Browse files Browse the repository at this point in the history
* Rewrap 404 errors from pypi.org

Fixes #87

* changelog

* cleanup
  • Loading branch information
Peter Bengtsson authored Oct 26, 2018
1 parent 8c0de87 commit 82aa784
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ Version History

next

* In Python 3, if the package can't be found you get a more explicit exception
pointing out which package (URL) that failed.
See https://github.com/peterbe/hashin/issues/87

* New flag ``--update-all`` (alias ``-u``) will parse the requirements file,
ignore the version, and update all packages that have new versions.
See https://github.com/peterbe/hashin/pull/88
Expand Down
18 changes: 16 additions & 2 deletions hashin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

if sys.version_info >= (3,):
from urllib.request import urlopen
from urllib.error import HTTPError
else:
from urllib import urlopen

Expand Down Expand Up @@ -99,12 +100,23 @@ class NoVersionsError(Exception):
"""When there are no valid versions found."""


class PackageNotFoundError(Exception):
"""When the package can't be found on pypi.org."""


def _verbose(*args):
print("* " + " ".join(args))


def _download(url, binary=False):
r = urlopen(url)
try:
r = urlopen(url)
except HTTPError as exception:
status_code = exception.getcode()
if status_code == 404:
raise PackageNotFoundError(url)
raise PackageError("Download error. {0} on {1}".format(status_code, url))

# Note that urlopen will, by default, follow redirects.
status_code = r.getcode()

Expand All @@ -115,8 +127,10 @@ def _download(url, binary=False):
"No 'Location' header on {0} ({1})".format(url, status_code)
)
return _download(location)
elif status_code == 404:
raise PackageNotFoundError(url)
elif status_code != 200:
raise PackageError("Package not found. {0} on {1}".format(status_code, url))
raise PackageError("Download error. {0} on {1}".format(status_code, url))
if binary:
return r.read()
_, params = cgi.parse_header(r.headers.get("Content-Type", ""))
Expand Down
36 changes: 36 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
if sys.version_info >= (3,):
# As in, Python 3
from io import StringIO
from urllib.error import HTTPError

STR_TYPE = str
else: # Python 2
from StringIO import StringIO

FileNotFoundError = IOError # ugly but necessary
# Python 2 does not have this exception.
HTTPError = None


@contextmanager
Expand Down Expand Up @@ -1282,6 +1285,39 @@ def mocked_get(url, **options):

self.assertEqual(result, expected)

@cleanup_tmpdir("hashin*")
@mock.patch("hashin.urlopen")
def test_get_package_hashes_package_not_found(self, murlopen):
def mocked_get(url, **options):
if url == "https://pypi.org/pypi/gobblygook/json":
if HTTPError:
raise HTTPError(url, 404, "Page not found", {}, None)
else:
return _Response({}, status_code=404)

if url == "https://pypi.org/pypi/troublemaker/json":
if HTTPError:
raise HTTPError(url, 500, "Something went wrong", {}, None)
else:
return _Response({}, status_code=500)

raise NotImplementedError(url)

murlopen.side_effect = mocked_get

with self.assertRaises(hashin.PackageNotFoundError) as cm:
hashin.get_package_hashes(
package="gobblygook", version="0.10", algorithm="sha256"
)
exception = cm.exception
self.assertEqual(str(exception), "https://pypi.org/pypi/gobblygook/json")

# Errors left as is if not a 404
with self.assertRaises(hashin.PackageError):
hashin.get_package_hashes(
package="troublemaker", version="0.10", algorithm="sha256"
)

@cleanup_tmpdir("hashin*")
@mock.patch("hashin.urlopen")
def test_get_package_hashes_unknown_algorithm(self, murlopen):
Expand Down

0 comments on commit 82aa784

Please sign in to comment.