def __init__(self): super(LyricsWikiaSearchThread, self).__init__() self.daemon = True self._queue = Queue() self._stopped = False self._current = None
class LyricsWikiaSearchThread(threading.Thread): TIMEOUT = 4.0 def __init__(self): super(LyricsWikiaSearchThread, self).__init__() self.daemon = True self._queue = Queue() self._stopped = False self._current = None def search_song(self, song, done_cb): """Trigger a new search, old ones will be canceled""" assert song assert done_cb if not self.is_alive(): self.start() self._current = song while not self._queue.empty(): self._queue.get_nowait() self._queue.put((song, done_cb)) def stop(self): """Stop all active searches, no callback will be called after this returns. """ self._stopped = True self._queue.put((None, None)) def __idle(self, song, func, *args, **kwargs): def delayed(): if self._stopped or song is not self._current: return func(song, *args, **kwargs) GLib.idle_add(delayed) def _do_search(self, song): """Returns a URL or None""" fetch_url = create_api_search_url(song) try: response = urlopen(fetch_url, timeout=self.TIMEOUT) except EnvironmentError: return try: xml = response.read() except IOError: return try: dom = minidom.parseString(xml) except Exception: # who knows... return page_id_nodes = dom.getElementsByTagName("page_id") if not page_id_nodes or not page_id_nodes[0].hasChildNodes(): return url_nodes = dom.getElementsByTagName("url") try: page = url_nodes[0].firstChild.data except (IndexError, AttributeError): return else: return page def run(self): while not self._stopped: song, cb = self._queue.get() if self._stopped: break result = self._do_search(song) self.__idle(song, cb, result)