From d8d83e6475b42810849c6df36692037e7137669d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 24 Mar 2011 12:57:00 -0600 Subject: [PATCH] Start implementing the identify() method using the new plugin architecture --- .../ebooks/metadata/sources/identify.py | 107 ++++++++++++++++++ src/calibre/utils/logging.py | 10 +- 2 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 src/calibre/ebooks/metadata/sources/identify.py diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py new file mode 100644 index 0000000000..53fb3a9ea4 --- /dev/null +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import time +from Queue import Queue, Empty +from threading import Thread +from io import BytesIO + +from calibre.customize.ui import metadata_plugins +from calibre.ebooks.metadata.sources.base import create_log + +# How long to wait for more results after first result is found +WAIT_AFTER_FIRST_RESULT = 30 # seconds + +class Worker(Thread): + + def __init__(self, plugin, kwargs, abort): + Thread.__init__(self) + self.daemon = True + + self.plugin, self.kwargs, self.rq = plugin, kwargs, Queue() + self.abort = abort + self.buf = BytesIO() + self.log = create_log(self.buf) + + def run(self): + try: + self.plugin.identify(self.log, self.rq, self.abort, **self.kwargs) + except: + self.log.exception('Plugin', self.plugin.name, 'failed') + +def is_worker_alive(workers): + for w in workers: + if w.is_alive(): + return True + return False + +def identify(log, abort, title=None, authors=None, identifiers=[], timeout=30): + plugins = list(metadata_plugins['identify']) + + kwargs = { + 'title': title, + 'authors': authors, + 'identifiers': identifiers, + 'timeout': timeout, + } + + log('Running identify query with parameters:') + log(kwargs) + log('Using plugins:', ', '.join([p.name for p in plugins])) + log('The log (if any) from individual plugins is below') + + workers = [Worker(p, kwargs, abort) for p in plugins] + for w in workers: + w.start() + + first_result_at = None + results = dict.fromkeys(plugins, []) + + def get_results(): + found = False + for w in workers: + try: + result = w.rq.get_nowait() + except Empty: + pass + else: + results[w.plugin].append(result) + found = True + return found + + while True: + time.sleep(0.2) + + if get_results() and first_result_at is None: + first_result_at = time.time() + + if not is_worker_alive(workers): + break + + if (first_result_at is not None and time.time() - first_result_at < + WAIT_AFTER_FIRST_RESULT): + log('Not waiting any longer for more results') + abort.set() + break + + get_results() + sort_kwargs = dict(kwargs) + for k in list(sort_kwargs.iterkeys()): + if k not in ('title', 'authors', 'identifiers'): + sort_kwargs.pop(k) + + for plugin, results in results.iteritems(): + results.sort(key=plugin.identify_results_keygen(**sort_kwargs)) + plog = plugin.buf.getvalue().strip() + if plog: + log('\n'+'*'*35, plugin.name, '*'*35) + log('Found %d results'%len(results)) + log(plog) + log('\n'+'*'*80) + diff --git a/src/calibre/utils/logging.py b/src/calibre/utils/logging.py index e7d8774b85..f4b2e6f0b6 100644 --- a/src/calibre/utils/logging.py +++ b/src/calibre/utils/logging.py @@ -36,12 +36,12 @@ class ANSIStream(Stream): from calibre.utils.terminfo import TerminalController tc = TerminalController(stream) self.color = { - DEBUG: tc.GREEN, - INFO:'', - WARN: tc.YELLOW, - ERROR: tc.RED + DEBUG: bytes(tc.GREEN), + INFO: bytes(''), + WARN: bytes(tc.YELLOW), + ERROR: bytes(tc.RED) } - self.normal = tc.NORMAL + self.normal = bytes(tc.NORMAL) def prints(self, level, *args, **kwargs): self.stream.write(self.color[level])