correctly handle BrowserUnavailable and BrowserIncorrectPassword exceptions in repl applications (closes #302)
It asks user to reconfigure backend when BrowserIncorrectPassword is raised.
This commit is contained in:
parent
ccc663be70
commit
6dfbda042c
4 changed files with 67 additions and 31 deletions
|
|
@ -19,7 +19,6 @@ from __future__ import with_statement
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import weboob
|
|
||||||
from weboob.capabilities.bank import ICapBank
|
from weboob.capabilities.bank import ICapBank
|
||||||
from weboob.tools.application.repl import ReplApplication
|
from weboob.tools.application.repl import ReplApplication
|
||||||
|
|
||||||
|
|
@ -44,18 +43,11 @@ class Boobank(ReplApplication):
|
||||||
tot_balance = 0.0
|
tot_balance = 0.0
|
||||||
tot_coming = 0.0
|
tot_coming = 0.0
|
||||||
self.accounts = []
|
self.accounts = []
|
||||||
try:
|
for backend, account in self.do('iter_accounts'):
|
||||||
for backend, account in self.do('iter_accounts'):
|
self.format(account)
|
||||||
self.format(account)
|
tot_balance += account.balance
|
||||||
tot_balance += account.balance
|
tot_coming += account.coming
|
||||||
tot_coming += account.coming
|
self.accounts.append(account)
|
||||||
self.accounts.append(account)
|
|
||||||
except weboob.core.CallErrors, errors:
|
|
||||||
for backend, error, backtrace in errors:
|
|
||||||
if isinstance(error, weboob.tools.browser.BrowserIncorrectPassword):
|
|
||||||
logging.error(u'Error: Incorrect password for backend %s' % backend.name)
|
|
||||||
else:
|
|
||||||
logging.error(u'Error[%s]: %s\n%s' % (backend.name, error, backtrace))
|
|
||||||
else:
|
else:
|
||||||
self.format((('label', 'Total'),
|
self.format((('label', 'Total'),
|
||||||
('balance', tot_balance),
|
('balance', tot_balance),
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class CallErrors(Exception):
|
||||||
def __init__(self, errors):
|
def __init__(self, errors):
|
||||||
Exception.__init__(self, u'These errors have been raised in backend threads '\
|
Exception.__init__(self, u'These errors have been raised in backend threads '\
|
||||||
'(use --debug option to print backtraces):\n%s' % (
|
'(use --debug option to print backtraces):\n%s' % (
|
||||||
u'\n'.join((u' * %s: %s%s' % (backend, repr(error), backtrace.decode('utf-8') + '\n'
|
u'\n'.join((u' * %s: %s%s' % (backend.name, repr(error), backtrace.decode('utf-8') + '\n'
|
||||||
if logging.root.level == logging.DEBUG else ''))
|
if logging.root.level == logging.DEBUG else ''))
|
||||||
for backend, error, backtrace in errors)))
|
for backend, error, backtrace in errors)))
|
||||||
self.errors = copy(errors)
|
self.errors = copy(errors)
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ class Weboob(object):
|
||||||
return loaded
|
return loaded
|
||||||
|
|
||||||
def unload_backends(self, names=None):
|
def unload_backends(self, names=None):
|
||||||
|
unloaded = {}
|
||||||
if isinstance(names, basestring):
|
if isinstance(names, basestring):
|
||||||
names = [names]
|
names = [names]
|
||||||
elif names is None:
|
elif names is None:
|
||||||
|
|
@ -106,6 +107,9 @@ class Weboob(object):
|
||||||
backend = self.backend_instances.pop(name)
|
backend = self.backend_instances.pop(name)
|
||||||
with backend:
|
with backend:
|
||||||
backend.deinit()
|
backend.deinit()
|
||||||
|
unloaded[backend.name] = backend
|
||||||
|
|
||||||
|
return unloaded
|
||||||
|
|
||||||
def get_backend(self, name):
|
def get_backend(self, name):
|
||||||
return self.backend_instances[name]
|
return self.backend_instances[name]
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ from weboob.capabilities.base import FieldNotFound
|
||||||
from weboob.core import CallErrors
|
from weboob.core import CallErrors
|
||||||
from weboob.core.backendscfg import BackendsConfig, BackendAlreadyExists
|
from weboob.core.backendscfg import BackendsConfig, BackendAlreadyExists
|
||||||
from weboob.tools.misc import iter_fields
|
from weboob.tools.misc import iter_fields
|
||||||
|
from weboob.tools.browser import BrowserUnavailable, BrowserIncorrectPassword
|
||||||
|
|
||||||
from .base import BackendNotFound, BaseApplication
|
from .base import BackendNotFound, BaseApplication
|
||||||
from .formatters.load import formatters as available_formatters, load_formatter
|
from .formatters.load import formatters as available_formatters, load_formatter
|
||||||
|
|
@ -119,7 +120,7 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
atexit.register(savehist)
|
atexit.register(savehist)
|
||||||
|
|
||||||
self._interactive = False
|
self._interactive = False
|
||||||
self.enabled_backends = []
|
self.enabled_backends = set()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def interactive(self):
|
def interactive(self):
|
||||||
|
|
@ -134,10 +135,20 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_backend(self, name, params=None):
|
def edit_backend(self, name, params=None):
|
||||||
|
return self.add_backend(name, params, True)
|
||||||
|
|
||||||
|
def add_backend(self, name, params=None, edit=False):
|
||||||
if params is None:
|
if params is None:
|
||||||
params = {}
|
params = {}
|
||||||
backend = self.weboob.modules_loader.get_or_load_module(name)
|
|
||||||
|
if not edit:
|
||||||
|
backend = self.weboob.modules_loader.get_or_load_module(name)
|
||||||
|
else:
|
||||||
|
bname, items = self.weboob.backends_config.get_backend(name)
|
||||||
|
backend = self.weboob.modules_loader.get_or_load_module(bname)
|
||||||
|
items.update(params)
|
||||||
|
params = items
|
||||||
if not backend:
|
if not backend:
|
||||||
print 'Backend "%s" does not exist.' % name
|
print 'Backend "%s" does not exist.' % name
|
||||||
return None
|
return None
|
||||||
|
|
@ -149,9 +160,9 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
asked_config = True
|
asked_config = True
|
||||||
print 'Configuration of backend'
|
print 'Configuration of backend'
|
||||||
print '------------------------'
|
print '------------------------'
|
||||||
if key not in params:
|
if key not in params or edit:
|
||||||
params[key] = self.ask(' [%s] %s' % (key, value.description),
|
params[key] = self.ask(' [%s] %s' % (key, value.description),
|
||||||
default=value.default,
|
default=params[key] if (edit and key in params) else value.default,
|
||||||
masked=value.is_masked,
|
masked=value.is_masked,
|
||||||
choices=value.choices,
|
choices=value.choices,
|
||||||
regexp=value.regexp)
|
regexp=value.regexp)
|
||||||
|
|
@ -161,10 +172,10 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
print '------------------------'
|
print '------------------------'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.weboob.backends_config.add_backend(name, name, params)
|
self.weboob.backends_config.add_backend(name, name, params, edit=edit)
|
||||||
print 'Backend "%s" successfully added.' % name
|
print 'Backend "%s" successfully %s.' % (name, 'updated' if edit else 'added')
|
||||||
return name
|
return name
|
||||||
except BackendAlreadyExists:#ConfigParser.DuplicateSectionError:
|
except BackendAlreadyExists:
|
||||||
print 'Backend "%s" is already configured in file "%s"' % (name, self.weboob.backends_config.confpath)
|
print 'Backend "%s" is already configured in file "%s"' % (name, self.weboob.backends_config.confpath)
|
||||||
while self.ask('Add new instance of "%s" backend?' % name, default=False):
|
while self.ask('Add new instance of "%s" backend?' % name, default=False):
|
||||||
new_name = self.ask('Please give new instance name (could be "%s_1")' % name, regexp=u'^[\d\w_-]+$')
|
new_name = self.ask('Please give new instance name (could be "%s_1")' % name, regexp=u'^[\d\w_-]+$')
|
||||||
|
|
@ -175,10 +186,19 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
except BackendAlreadyExists:
|
except BackendAlreadyExists:
|
||||||
print 'Instance "%s" already exists for backend "%s".' % (new_name, name)
|
print 'Instance "%s" already exists for backend "%s".' % (new_name, name)
|
||||||
|
|
||||||
|
def unload_backends(self, *args, **kwargs):
|
||||||
|
unloaded = self.weboob.unload_backends(*args, **kwargs)
|
||||||
|
for backend in unloaded.itervalues():
|
||||||
|
try:
|
||||||
|
self.enabled_backends.remove(backend)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return unloaded
|
||||||
|
|
||||||
def load_backends(self, *args, **kwargs):
|
def load_backends(self, *args, **kwargs):
|
||||||
ret = super(ReplApplication, self).load_backends(*args, **kwargs)
|
ret = super(ReplApplication, self).load_backends(*args, **kwargs)
|
||||||
for name, backend in ret.iteritems():
|
for name, backend in ret.iteritems():
|
||||||
self.enabled_backends.append(backend)
|
self.enabled_backends.add(backend)
|
||||||
while len(self.enabled_backends) == 0:
|
while len(self.enabled_backends) == 0:
|
||||||
print 'Warning: there is currently no configured backend for %s' % self.APPNAME
|
print 'Warning: there is currently no configured backend for %s' % self.APPNAME
|
||||||
if not self.ask('Do you want to configure backends?', default=True):
|
if not self.ask('Do you want to configure backends?', default=True):
|
||||||
|
|
@ -264,7 +284,31 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
try:
|
try:
|
||||||
return super(ReplApplication, self).onecmd(_cmd)
|
return super(ReplApplication, self).onecmd(_cmd)
|
||||||
except CallErrors, e:
|
except CallErrors, e:
|
||||||
print >>sys.stderr, '%s' % e
|
ask_debug_mode = False
|
||||||
|
for backend, error, backtrace in e.errors:
|
||||||
|
if isinstance(error, BrowserIncorrectPassword):
|
||||||
|
msg = unicode(error)
|
||||||
|
if not msg:
|
||||||
|
msg = 'invalid login/password.'
|
||||||
|
print >>sys.stderr, 'Error(%s): %s' % (backend.name, msg)
|
||||||
|
if self.ask('Do you want to reconfigure this backend?', default=True):
|
||||||
|
self.unload_backends(names=[backend.name])
|
||||||
|
self.edit_backend(backend.name)
|
||||||
|
self.load_backends(names=[backend.name])
|
||||||
|
elif isinstance(error, BrowserUnavailable):
|
||||||
|
msg = unicode(error)
|
||||||
|
if not msg:
|
||||||
|
msg = 'website is unavailable.'
|
||||||
|
print >>sys.stderr, 'Error(%s): %s' % (backend.name, msg)
|
||||||
|
else:
|
||||||
|
common_errors = True
|
||||||
|
print >>sys.stderr, 'Error(%s): %s' % (backend.name, error)
|
||||||
|
if logging.root.level == logging.DEBUG:
|
||||||
|
print >>sys.stderr, backtrace
|
||||||
|
else:
|
||||||
|
ask_debug_mode = True
|
||||||
|
if ask_debug_mode:
|
||||||
|
print >>sys.stderr, 'Use --debug option to print backtraces.'
|
||||||
except NotEnoughArguments, e:
|
except NotEnoughArguments, e:
|
||||||
print >>sys.stderr, 'Error: no enough arguments.'
|
print >>sys.stderr, 'Error: no enough arguments.'
|
||||||
except (KeyboardInterrupt,EOFError):
|
except (KeyboardInterrupt,EOFError):
|
||||||
|
|
@ -507,11 +551,7 @@ class ReplApplication(Cmd, BaseApplication):
|
||||||
elif action == 'remove':
|
elif action == 'remove':
|
||||||
for backend in given_backends:
|
for backend in given_backends:
|
||||||
self.weboob.backends_config.remove_backend(backend.name)
|
self.weboob.backends_config.remove_backend(backend.name)
|
||||||
self.weboob.unload_backends(backend.name)
|
self.unload_backends(backend.name)
|
||||||
try:
|
|
||||||
self.enabled_backends.remove(backend)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
print 'Unknown action: "%s"' % action
|
print 'Unknown action: "%s"' % action
|
||||||
return 1
|
return 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue