def on_action_hovered(self, action): """ Fetch song.artists when artists_action is hovered. If it is already fetched, ignore. """ data = action.data() if data is None: # submenu action return def artists_fetched_cb(future): self._fetching_artists = False artists = future.result() # ignore the potential exception if artists: for artist in artists: artist_action = action.menu().addAction(artist.name) # create a closure to bind variable artist artist_action.triggered.connect( (lambda x: lambda: self._app.browser.goto(model=x) )(artist)) data['artists'] = artists or [] action.setData(data) # the action is artists_action if 'artists' in data: # artists value has not been fetched if data['artists'] is None and self._fetching_artists is False: logger.debug('fetch song.artists for actions') song = data['song'] self._fetching_artists = True task = aio.run_in_executor( None, lambda: self._app.library.song_upgrade(song).artists) task.add_done_callback(artists_fetched_cb)
async def a_search(self, keyword, source_in=None, timeout=None, type_in=None, **kwargs): """async version of search TODO: add Happy Eyeballs requesting strategy if needed """ type_in = SearchType.batch_parse(type_in) if type_in else [ SearchType.so ] fs = [] # future list for provider in self._filter(identifier_in=source_in): for type_ in type_in: future = aio.run_in_executor( None, partial(provider.search, keyword, type_=type_)) fs.append(future) results = [] # TODO: use async generator when we only support Python 3.6 or above for future in aio.as_completed(fs, timeout=timeout): try: result = await future except Exception as e: logger.exception(str(e)) else: if result is not None: results.append(result) return results
async def a_search(self, keyword, source_in=None, timeout=None, type_in=None, **kwargs): """async version of search TODO: add Happy Eyeballs requesting strategy if needed """ type_in = SearchType.batch_parse(type_in) if type_in else [SearchType.so] fs = [] # future list for provider in self._filter(identifier_in=source_in): for type_ in type_in: future = aio.run_in_executor( None, partial(provider.search, keyword, type_=type_)) fs.append(future) for future in aio.as_completed(fs, timeout=timeout): try: result = await future except: # noqa logger.exception('search task failed') continue else: yield result
def setEditorData(self, editor, index): super().setEditorData(editor, index) def cb(future): try: artists = future.result() except: # noqa logger.error('song.artists failed') else: model = ArtistsModel(artists) editor.setModel(model) editor.setCurrentIndex(QModelIndex()) if index.column() == Column.artist: song = index.data(role=Qt.UserRole) future = aio.run_in_executor(None, lambda: song.artists) future.add_done_callback(cb)
def on_song_changed(self, song): """bind song changed signal with this""" if song is None: self._set_lyric(None) return def cb(future): try: lyric = future.result() except: # noqa logger.exception('get lyric failed') lyric = None self._set_lyric(lyric) # TODO: use app.task_mgr instead future = aio.run_in_executor(None, lambda: song.lyric) future.add_done_callback(cb)