mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-03-25 08:55:50 +00:00
Improve errorhandling for enduser
This commit is contained in:
parent
8c7af4bfc9
commit
a90815f5df
9 changed files with 42 additions and 29 deletions
|
|
@ -6,6 +6,7 @@ from requests import Response
|
|||
|
||||
from tests import normalize_item
|
||||
|
||||
from vdirsyncer.exceptions import UserError
|
||||
from vdirsyncer.storage.http import HttpStorage, prepare_auth
|
||||
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ def test_prepare_auth_guess(monkeypatch, auth):
|
|||
|
||||
monkeypatch.delattr(requests_toolbelt.auth.guess, 'GuessAuth')
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
with pytest.raises(UserError) as excinfo:
|
||||
prepare_auth(auth, 'user', 'pwd')
|
||||
|
||||
assert 'requests_toolbelt is too old' in str(excinfo.value).lower()
|
||||
|
|
|
|||
|
|
@ -495,8 +495,9 @@ def handle_storage_init_error(cls, config):
|
|||
.format(cls.storage_name, u', '.join(invalid)))
|
||||
|
||||
if not problems:
|
||||
cli_logger.exception('')
|
||||
problems.append('Internal error, see above.')
|
||||
if not isinstance(e, exceptions.UserError):
|
||||
cli_logger.exception('')
|
||||
problems.append(str(e))
|
||||
|
||||
raise CliError(u'Failed to initialize {}'.format(config['instance_name']),
|
||||
problems=problems)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ class Error(Exception):
|
|||
super(Error, self).__init__(*args)
|
||||
|
||||
|
||||
class UserError(Error, ValueError):
|
||||
'''Wrapper exception to be used to signify the traceback should not be
|
||||
shown to the user.'''
|
||||
|
||||
|
||||
class CollectionNotFound(Error):
|
||||
'''Collection not found'''
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class Storage(with_metaclass(StorageMeta)):
|
|||
if read_only is None:
|
||||
read_only = self.read_only
|
||||
if self.read_only and not read_only:
|
||||
raise ValueError('This storage can only be read-only.')
|
||||
raise exceptions.UserError('This storage can only be read-only.')
|
||||
self.read_only = bool(read_only)
|
||||
|
||||
if collection and instance_name:
|
||||
|
|
|
|||
|
|
@ -591,12 +591,12 @@ class CaldavStorage(DavStorage):
|
|||
item_types=(), **kwargs):
|
||||
super(CaldavStorage, self).__init__(**kwargs)
|
||||
if not isinstance(item_types, (list, tuple)):
|
||||
raise ValueError('item_types must be a list.')
|
||||
raise exceptions.UserError('item_types must be a list.')
|
||||
|
||||
self.item_types = tuple(item_types)
|
||||
if (start_date is None) != (end_date is None):
|
||||
raise ValueError('If start_date is given, '
|
||||
'end_date has to be given too.')
|
||||
raise exceptions.UserError('If start_date is given, '
|
||||
'end_date has to be given too.')
|
||||
elif start_date is not None and end_date is not None:
|
||||
namespace = dict(datetime.__dict__)
|
||||
namespace['start_date'] = self.start_date = \
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .base import Item, Storage
|
||||
from ..exceptions import NotFoundError
|
||||
from .. import exceptions
|
||||
from ..utils import expand_path
|
||||
from ..utils.compat import iteritems, text_type, urlparse
|
||||
from ..utils.http import request
|
||||
|
|
@ -22,16 +22,19 @@ def prepare_auth(auth, username, password):
|
|||
try:
|
||||
from requests_toolbelt.auth.guess import GuessAuth
|
||||
except ImportError:
|
||||
raise RuntimeError('Your version of requests_toolbelt is too '
|
||||
'old for `guess` authentication. At least '
|
||||
'version 0.4.0 is required.')
|
||||
raise exceptions.UserError(
|
||||
'Your version of requests_toolbelt is too '
|
||||
'old for `guess` authentication. At least '
|
||||
'version 0.4.0 is required.'
|
||||
)
|
||||
else:
|
||||
return GuessAuth(username, password)
|
||||
else:
|
||||
raise ValueError('Unknown authentication method: {}'.format(auth))
|
||||
raise exceptions.UserError('Unknown authentication method: {}'
|
||||
.format(auth))
|
||||
elif auth:
|
||||
raise ValueError('For {} authentication, you need to specify username '
|
||||
'and password.'.format(auth))
|
||||
raise exceptions.UserError('You need to specify username and password '
|
||||
'for {} authentication.'.format(auth))
|
||||
else:
|
||||
return None
|
||||
|
||||
|
|
@ -40,20 +43,20 @@ def prepare_verify(verify, verify_fingerprint):
|
|||
if isinstance(verify, (text_type, bytes)):
|
||||
verify = expand_path(verify)
|
||||
elif not isinstance(verify, bool):
|
||||
raise ValueError('Invalid value for verify ({}), '
|
||||
'must be a path to a PEM-file or boolean.'
|
||||
.format(verify))
|
||||
raise exceptions.UserError('Invalid value for verify ({}), '
|
||||
'must be a path to a PEM-file or boolean.'
|
||||
.format(verify))
|
||||
|
||||
if verify_fingerprint is not None:
|
||||
if not isinstance(verify_fingerprint, str):
|
||||
raise ValueError('Invalid value for verify_fingerprint ({}), '
|
||||
'must be a string or null.'
|
||||
.format(verify_fingerprint))
|
||||
raise exceptions.UserError('Invalid value for verify_fingerprint '
|
||||
'({}), must be a string or null.'
|
||||
.format(verify_fingerprint))
|
||||
verify = False
|
||||
elif not verify:
|
||||
raise ValueError('verify = false is forbidden. Consider setting '
|
||||
'verify_fingerprint instead, which also disables '
|
||||
'validation against CAs.')
|
||||
raise exceptions.UserError('verify = false is forbidden. Consider '
|
||||
'setting verify_fingerprint instead, which '
|
||||
'also disables validation against CAs.')
|
||||
|
||||
return {
|
||||
'verify': verify,
|
||||
|
|
@ -161,4 +164,4 @@ class HttpStorage(Storage):
|
|||
try:
|
||||
return self._items[href]
|
||||
except KeyError:
|
||||
raise NotFoundError(href)
|
||||
raise exceptions.NotFoundError(href)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ class MemoryStorage(Storage):
|
|||
|
||||
def __init__(self, fileext='', **kwargs):
|
||||
if kwargs.get('collection') is not None:
|
||||
raise ValueError('MemoryStorage does not support collections.')
|
||||
raise exceptions.UserError('MemoryStorage does not support '
|
||||
'collections.')
|
||||
self.items = {} # href => (etag, item)
|
||||
self.fileext = fileext
|
||||
super(MemoryStorage, self).__init__(**kwargs)
|
||||
|
|
|
|||
|
|
@ -77,8 +77,10 @@ class SingleFileStorage(Storage):
|
|||
|
||||
collection = kwargs.get('collection')
|
||||
if collection is not None:
|
||||
raise ValueError('collection is not a valid argument for {}'
|
||||
.format(type(self).__name__))
|
||||
raise exceptions.UserError(
|
||||
'collection is not a valid argument for {}'
|
||||
.format(type(self).__name__)
|
||||
)
|
||||
|
||||
checkfile(path, create=False)
|
||||
|
||||
|
|
|
|||
|
|
@ -278,8 +278,8 @@ def _action_conflict_resolve(ident):
|
|||
sync_logger.info('...{} wins.'.format(b.storage))
|
||||
_action_update(ident, b, a)(a, b, conflict_resolution)
|
||||
else:
|
||||
raise ValueError('Invalid conflict resolution mode: {}'
|
||||
.format(conflict_resolution))
|
||||
raise exceptions.UserError('Invalid conflict resolution mode: {}'
|
||||
.format(conflict_resolution))
|
||||
|
||||
return inner
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue