display a message when more results are available (closes #1038)

This commit is contained in:
Romain Bignon 2013-07-27 21:58:50 +02:00
commit 46d9acd37e
6 changed files with 84 additions and 57 deletions

View file

@ -574,22 +574,18 @@ class Cineoob(ReplApplication):
if dest is None:
dest = '%s' % _id
try:
for backend, buf in self.do('get_subtitle_file', _id, backends=backend_name, caps=ICapSubtitle):
if buf:
if dest == '-':
print buf
else:
try:
with open(dest, 'w') as f:
f.write(buf)
except IOError as e:
print >>sys.stderr, 'Unable to write file in "%s": %s' % (dest, e)
return 1
return
except CallErrors as errors:
for backend, error, backtrace in errors:
self.bcall_error_handler(backend, error, backtrace)
for backend, buf in self.do('get_subtitle_file', _id, backends=backend_name, caps=ICapSubtitle):
if buf:
if dest == '-':
print buf
else:
try:
with open(dest, 'w') as f:
f.write(buf)
except IOError as e:
print >>sys.stderr, 'Unable to write file in "%s": %s' % (dest, e)
return 1
return
print >>sys.stderr, 'Subtitle "%s" not found' % id
return 3

View file

@ -56,10 +56,12 @@ class ResultsConditionError(Exception):
class BackendsCall(object):
def __init__(self, backends, condition, function, *args, **kwargs):
"""
@param backends list of backends to call.
@param condition a IResultsCondition object. Can be None.
@param function backends' method name, or callable object.
@param args, kwargs arguments given to called functions.
:param backends: List of backends to call
:type backends: list[:class:`BaseBackend`]
:param condition: Condition applied on results (can be None)
:type condition: :class:`IResultsCondition`
:param function: backends' method name, or callable object.
:type function: :class:`str` or :class:`callable`
"""
self.logger = getLogger('bcall')
# Store if a backend is finished

View file

@ -37,6 +37,9 @@ from weboob.tools.misc import to_unicode
__all__ = ['BaseApplication']
class MoreResultsAvailable(Exception):
pass
class ApplicationStorage(object):
def __init__(self, name, storage):
self.name = name
@ -164,10 +167,13 @@ class BaseApplication(object):
"""
Create a storage object.
@param path [str] an optional specific path.
@param klass [IStorage] what klass to instance.
@param localonly [bool] if True, do not set it on the Weboob object.
@return a IStorage object
:param path: An optional specific path
:type path: :class:`str`
:param klass: What class to instance
:type klass: :class:`weboob.tools.storage.IStorage`
:param localonly: If True, do not set it on the :class:`Weboob` object.
:type localonly: :class:`bool`
:rtype: :class:`weboob.tools.storage.IStorage`
"""
if klass is None:
from weboob.tools.storage import StandardStorage
@ -191,9 +197,11 @@ class BaseApplication(object):
"""
Load a configuration file and get his object.
@param path [str] an optional specific path.
@param klass [IConfig] what klass to instance.
@return a IConfig object
:param path: An optional specific path
:type path: :class:`str`
:param klass: What class to instance
:type klass: :class:`weboob.tools.config.iconfig.IConfig`
:rtype: :class:`weboob.tools.config.iconfig.IConfig`
"""
if klass is None:
from weboob.tools.config.iniconfig import INIConfig
@ -242,7 +250,7 @@ class BaseApplication(object):
def _do_complete_iter(self, backend, count, fields, res):
for i, sub in enumerate(res):
if count and i == count:
break
raise MoreResultsAvailable()
sub = self._do_complete_obj(backend, fields, sub)
yield sub
@ -264,18 +272,39 @@ class BaseApplication(object):
This method can be overrided to support more exceptions types.
"""
# Ignore this error.
if isinstance(error, MoreResultsAvailable):
return False
print >>sys.stderr, u'Error(%s): %s' % (backend.name, error)
if logging.root.level == logging.DEBUG:
print >>sys.stderr, backtrace
else:
return True
def bcall_errors_handler(self, errors):
def bcall_errors_handler(self, errors, debugmsg='Use --debug option to print backtraces', ignore=()):
"""
Handler for the CallErrors exception.
It calls `bcall_error_handler` for each error.
:param errors: Object containing errors from backends
:type errors: :class:`weboob.core.bcall.CallErrors`
:param debugmsg: Default message asking to enable the debug mode
:type debugmsg: :class:`basestring`
:param ignore: Exceptions to ignore
:type ignore: tuple[:class:`Exception`]
"""
ask_debug_mode = False
for backend, error, backtrace in errors.errors:
self.bcall_error_handler(backend, error, backtrace)
if logging.root.level != logging.DEBUG:
print >>sys.stderr, 'Use --debug option to print backtraces.'
if isinstance(error, ignore):
continue
elif self.bcall_error_handler(backend, error, backtrace):
ask_debug_mode = True
if ask_debug_mode:
print >>sys.stderr, debugmsg
def parse_args(self, args):
self.options, args = self._parser.parse_args(args)
@ -372,6 +401,7 @@ class BaseApplication(object):
a call to sys.exit().
For example:
>>> from weboob.application.myapplication import MyApplication
>>> MyApplication.run()
"""

View file

@ -37,7 +37,7 @@ from weboob.tools.browser import BrowserUnavailable, BrowserIncorrectPassword, B
from weboob.tools.value import Value, ValueBool, ValueFloat, ValueInt
from weboob.tools.misc import to_unicode
from .base import BaseApplication
from .base import BaseApplication, MoreResultsAvailable
__all__ = ['ConsoleApplication', 'BackendNotGiven']
@ -497,6 +497,8 @@ class ConsoleApplication(BaseApplication):
print >>sys.stderr, u' %s please contact: %s <%s>' % (' ' * len(backend.name), backend.MAINTAINER, backend.EMAIL)
elif isinstance(error, UserError):
print >>sys.stderr, u'Error(%s): %s' % (backend.name, to_unicode(error))
elif isinstance(error, MoreResultsAvailable):
print >>sys.stderr, u'Hint: There are more results for backend %s' % (backend.name)
elif isinstance(error, SSLError):
print >>sys.stderr, u'FATAL(%s): ' % backend.name + self.BOLD + '/!\ SERVER CERTIFICATE IS INVALID /!\\' + self.NC
else:
@ -519,14 +521,21 @@ class ConsoleApplication(BaseApplication):
else:
return True
def bcall_errors_handler(self, errors, debugmsg='Use --debug option to print backtraces'):
def bcall_errors_handler(self, errors, debugmsg='Use --debug option to print backtraces', ignore=()):
"""
Handler for the CallErrors exception.
"""
ask_debug_mode = False
more_results = set()
for backend, error, backtrace in errors.errors:
if self.bcall_error_handler(backend, error, backtrace):
if isinstance(error, MoreResultsAvailable):
more_results.add(backend.name)
elif isinstance(error, ignore):
continue
elif self.bcall_error_handler(backend, error, backtrace):
ask_debug_mode = True
if ask_debug_mode:
print >>sys.stderr, debugmsg
elif len(more_results) > 0:
print >>sys.stderr, 'Hint: There are more results available for %s' % (', '.join(more_results))

View file

@ -37,7 +37,7 @@ from weboob.tools.value import ValueInt, ValueBool, ValueBackendPassword
from weboob.tools.misc import to_unicode
from weboob.capabilities import UserError
from ..base import BaseApplication
from ..base import BaseApplication, MoreResultsAvailable
__all__ = ['QtApplication', 'QtMainWindow', 'QtDo', 'HTMLDelegate']
@ -201,6 +201,10 @@ class QtDo(QObject):
self.process.callback_thread(self.thread_cb, self.thread_eb)
def default_eb(self, backend, error, backtrace):
if isinstance(error, MoreResultsAvailable):
# This is not an error, ignore.
return
msg = unicode(error)
if isinstance(error, BrowserIncorrectPassword):
if not msg:
@ -247,9 +251,6 @@ class QtDo(QObject):
def local_eb(self, backend, error, backtrace):
self.eb(backend, error, backtrace)
self.disconnect(self, SIGNAL('cb'), self.local_cb)
self.disconnect(self, SIGNAL('eb'), self.local_eb)
self.process = None
def thread_cb(self, backend, data):
self.emit(SIGNAL('cb'), backend, data)

View file

@ -453,11 +453,11 @@ class ReplApplication(Cmd, ConsoleApplication):
else:
return super(ReplApplication, self).bcall_error_handler(backend, error, backtrace)
def bcall_errors_handler(self, errors):
def bcall_errors_handler(self, errors, ignore=()):
if self.interactive:
ConsoleApplication.bcall_errors_handler(self, errors, 'Use "logging debug" option to print backtraces.')
ConsoleApplication.bcall_errors_handler(self, errors, 'Use "logging debug" option to print backtraces.', ignore)
else:
ConsoleApplication.bcall_errors_handler(self, errors)
ConsoleApplication.bcall_errors_handler(self, errors, ignore=ignore)
# -- options related methods -------------
def _handle_options(self):
@ -998,11 +998,8 @@ class ReplApplication(Cmd, ConsoleApplication):
if res:
collections.append(res)
except CallErrors as errors:
for backend, error, backtrace in errors.errors:
if isinstance(error, CollectionNotFound):
pass
else:
self.bcall_error_handler(backend, error, backtrace)
self.bcall_errors_handler(errors, CollectionNotFound)
if len(collections):
# update the path from the collection if possible
if len(collections) == 1:
@ -1027,11 +1024,7 @@ class ReplApplication(Cmd, ConsoleApplication):
else:
objects.append(res)
except CallErrors as errors:
for backend, error, backtrace in errors.errors:
if isinstance(error, CollectionNotFound):
pass
else:
self.bcall_error_handler(backend, error, backtrace)
self.bcall_errors_handler(errors, CollectionNotFound)
return (objects, collections)
@ -1055,11 +1048,7 @@ class ReplApplication(Cmd, ConsoleApplication):
try:
self.objects, self.collections = self._fetch_objects(objs=self.COLLECTION_OBJECTS)
except CallErrors as errors:
for backend, error, backtrace in errors.errors:
if isinstance(error, CollectionNotFound):
pass
else:
self.bcall_error_handler(backend, error, backtrace)
self.bcall_errors_handler(errors, CollectionNotFound)
collections = self.all_collections()
for collection in collections: