Skip to content

Commit

Permalink
Better exception handling (#397)
Browse files Browse the repository at this point in the history
  • Loading branch information
di authored and theacodes committed Sep 21, 2018
1 parent 9e850be commit 0191a22
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 21 deletions.
3 changes: 2 additions & 1 deletion tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from twine.commands import _find_dists, _group_wheel_files_first
from twine import exceptions


def test_ensure_wheel_files_uploaded_first():
Expand Down Expand Up @@ -34,7 +35,7 @@ def test_find_dists_expands_globs():


def test_find_dists_errors_on_invalid_globs():
with pytest.raises(ValueError):
with pytest.raises(exceptions.InvalidDistribution):
_find_dists(["twine/*.rb"])


Expand Down
7 changes: 5 additions & 2 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
# limitations under the License.

from twine import __main__ as dunder_main
from twine import exceptions

import pretend


def test_exception_handling(monkeypatch):
replaced_dispatch = pretend.raiser(KeyError('foo'))
replaced_dispatch = pretend.raiser(
exceptions.InvalidConfiguration('foo')
)
monkeypatch.setattr(dunder_main, 'dispatch', replaced_dispatch)
assert dunder_main.main() == 'KeyError: foo'
assert dunder_main.main() == 'InvalidConfiguration: foo'
5 changes: 4 additions & 1 deletion twine/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@

import sys

import requests

from twine import exceptions
from twine.cli import dispatch


def main():
try:
return dispatch(sys.argv[1:])
except Exception as exc:
except (exceptions.TwineException, requests.exceptions.HTTPError) as exc:
return '{0}: {1}'.format(
exc.__class__.__name__,
exc.args[0],
Expand Down
4 changes: 3 additions & 1 deletion twine/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import glob
import os.path

from twine import exceptions

__all__ = []


Expand All @@ -40,7 +42,7 @@ def _find_dists(dists):
files = glob.glob(filename)
# If nothing matches, files is []
if not files:
raise ValueError(
raise exceptions.InvalidDistribution(
"Cannot find file (or expand pattern): '%s'" % filename
)
# Otherwise, files will be filenames that exist
Expand Down
6 changes: 3 additions & 3 deletions twine/commands/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
import argparse
import os.path

from twine import exceptions as exc
from twine.package import PackageFile
from twine import exceptions
from twine import settings


Expand All @@ -28,7 +28,7 @@ def register(register_settings, package):
repository = register_settings.create_repository()

if not os.path.exists(package):
raise exc.PackageNotFound(
raise exceptions.PackageNotFound(
'"{0}" does not exist on the file system.'.format(package)
)

Expand All @@ -38,7 +38,7 @@ def register(register_settings, package):
repository.close()

if resp.is_redirect:
raise exc.RedirectDetected(
raise exceptions.RedirectDetected(
('"{0}" attempted to redirect to "{1}" during registration.'
' Aborting...').format(repository_url,
resp.headers["location"]))
Expand Down
4 changes: 2 additions & 2 deletions twine/commands/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
import argparse
import os.path

import twine.exceptions as exc
from twine.commands import _find_dists
from twine.package import PackageFile
from twine import exceptions
from twine import settings
from twine import utils

Expand Down Expand Up @@ -85,7 +85,7 @@ def upload(upload_settings, dists):
# by PyPI should never happen in reality. This should catch malicious
# redirects as well.
if resp.is_redirect:
raise exc.RedirectDetected(
raise exceptions.RedirectDetected(
('"{0}" attempted to redirect to "{1}" during upload.'
' Aborting...').format(repository_url,
resp.headers["location"]))
Expand Down
12 changes: 12 additions & 0 deletions twine/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,15 @@ class InvalidSigningConfiguration(TwineException):
"""Both the sign and identity parameters must be present."""

pass


class InvalidConfiguration(TwineException):
"""Raised when configuration is invalid."""

pass


class InvalidDistribution(TwineException):
"""Raised when a distribution is invalid."""

pass
7 changes: 5 additions & 2 deletions twine/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

from twine.wheel import Wheel
from twine.wininst import WinInst
from twine import exceptions

DIST_TYPES = {
"bdist_wheel": Wheel,
Expand Down Expand Up @@ -78,7 +79,7 @@ def from_filename(cls, filename, comment):
meta = DIST_TYPES[dtype](filename)
break
else:
raise ValueError(
raise exceptions.InvalidDistribution(
"Unknown distribution format: '%s'" %
os.path.basename(filename)
)
Expand Down Expand Up @@ -151,7 +152,9 @@ def metadata_dictionary(self):

def add_gpg_signature(self, signature_filepath, signature_filename):
if self.gpg_signature is not None:
raise ValueError('GPG Signature can only be added once')
raise exceptions.InvalidDistribution(
'GPG Signature can only be added once'
)

with open(signature_filepath, "rb") as gpg:
self.gpg_signature = (signature_filename, gpg.read())
Expand Down
6 changes: 3 additions & 3 deletions twine/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
except ImportError:
from urllib.parse import urlparse, urlunparse

import twine.exceptions
from twine import exceptions

# Shim for raw_input in python3
if sys.version_info > (3,):
Expand Down Expand Up @@ -109,7 +109,7 @@ def get_repository_from_config(config_file, repository, repository_url=None):
"password": None,
}
if repository_url and "://" not in repository_url:
raise twine.exceptions.UnreachableRepositoryURLDetected(
raise exceptions.UnreachableRepositoryURLDetected(
"Repository URL {0} has no protocol. Please add "
"'https://'. \n".format(repository_url))
try:
Expand All @@ -125,7 +125,7 @@ def get_repository_from_config(config_file, repository, repository_url=None):
repo=repository,
cfg=config_file
)
raise KeyError(msg)
raise exceptions.InvalidConfiguration(msg)


_HOSTNAMES = set(["pypi.python.org", "testpypi.python.org", "upload.pypi.org",
Expand Down
14 changes: 11 additions & 3 deletions twine/wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
from pkginfo import distribution
from pkginfo.distribution import Distribution

from twine import exceptions

# Monkeypatch Metadata 2.0 support
distribution.HEADER_ATTRS_2_0 = distribution.HEADER_ATTRS_1_2
distribution.HEADER_ATTRS.update({"2.0": distribution.HEADER_ATTRS_2_0})
Expand Down Expand Up @@ -69,7 +71,9 @@ def find_candidate_metadata_files(names):
def read(self):
fqn = os.path.abspath(os.path.normpath(self.filename))
if not os.path.exists(fqn):
raise ValueError('No such file: %s' % fqn)
raise exceptions.InvalidDistribution(
'No such file: %s' % fqn
)

if fqn.endswith('.whl'):
archive = zipfile.ZipFile(fqn)
Expand All @@ -78,7 +82,9 @@ def read(self):
def read_file(name):
return archive.read(name)
else:
raise ValueError('Not a known archive format: %s' % fqn)
raise exceptions.InvalidDistribution(
'Not a known archive format: %s' % fqn
)

try:
for path in self.find_candidate_metadata_files(names):
Expand All @@ -89,7 +95,9 @@ def read_file(name):
finally:
archive.close()

raise ValueError('No METADATA in archive: %s' % fqn)
raise exceptions.InvalidDistribution(
'No METADATA in archive: %s' % fqn
)

def parse(self, data):
super(Wheel, self).parse(data)
Expand Down
14 changes: 11 additions & 3 deletions twine/wininst.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from pkginfo.distribution import Distribution

from twine import exceptions

wininst_file_re = re.compile(r".*py(?P<pyver>\d+\.\d+)\.exe$")


Expand All @@ -28,7 +30,9 @@ def py_version(self):
def read(self):
fqn = os.path.abspath(os.path.normpath(self.filename))
if not os.path.exists(fqn):
raise ValueError('No such file: %s' % fqn)
raise exceptions.InvalidDistribution(
'No such file: %s' % fqn
)

if fqn.endswith('.exe'):
archive = zipfile.ZipFile(fqn)
Expand All @@ -37,7 +41,9 @@ def read(self):
def read_file(name):
return archive.read(name)
else:
raise ValueError('Not a known archive format: %s' % fqn)
raise exceptions.InvalidDistribution(
'Not a known archive format: %s' % fqn
)

try:
tuples = [x.split('/') for x in names
Expand All @@ -51,4 +57,6 @@ def read_file(name):
finally:
archive.close()

raise ValueError('No PKG-INFO/.egg-info in archive: %s' % fqn)
raise exceptions.InvalidDistribution(
'No PKG-INFO/.egg-info in archive: %s' % fqn
)

0 comments on commit 0191a22

Please sign in to comment.