def persist(self): # noinspection PyBroadException try: __class__.persist_cache(self.clients) except Exception: logger.exception('Query cache failed to persist') else: self.last_persist_time = time.time() self.unpersisted_count = 0 logger.debug('Query cache persisted successfully')
def on_speech_downloaded(self, query: str, path: str): logger.debug('on_speech_downloaded: query=%s, path=%s', repr(query), repr(path)) if not self.auto_play: return # 若窗口未显示,或查询内容已改变,不发音 if not self.is_visible( ) or not self.current_query_result or self.current_query_result.query != query: return # 避免重复发音 if not self.current_query_result.speech_path: self.pronounce(path) self.current_query_result.speech_path = path
def query(self, text: str) -> Optional[QueryResult]: start_time = time.time() logger.debug('[%s] Query started for query=%s', self.client.id, repr(text)) # noinspection PyBroadException try: result = self.cache.get(self.client.id, text) if result: # TODO 完善路径的协议检查 if result.speech_path and result.speech_path.startswith( '/') and not os.path.exists(result.speech_path): result.speech_path = None logger.debug('[%s] Cache hit for query=%s, result=%s', self.client.id, repr(text), repr(result)) return result result = self.client.query(text) logger.debug('[%s] Query finished for query=%s, result=%s', self.client.id, repr(text), repr(result)) if result: self.cache.put(self.client.id, text, result) return result except Exception: logger.exception('[%s] Query failed for query=%s', self.client.id, repr(text)) finally: time_spent = (time.time() - start_time) * 1000 logger.debug('[%s] Time spent: %fms', self.client.id, time_spent)
def load_cache(): if not os.path.exists( __class__.CACHE_VERSION_FILE) or not os.path.exists( __class__.CACHE_FILE): return # noinspection PyBroadException try: with open(__class__.CACHE_VERSION_FILE, 'r') as f: query_result_version = int(f.read().strip()) if query_result_version != QueryResult.VERSION: logger.debug( 'Ignore cache for version %d, current version is %d', query_result_version, QueryResult.VERSION) return with open(__class__.CACHE_FILE, 'rb') as f: data = pickle.load(f) return data except Exception: return
def redraw(self, selection: Selection, query_result: QueryResult): if not query_result: logger.debug('Redraw canceled, since query_result is invalid: %s', repr(query_result)) return # 若选中文本已经变化,不再显示旧的查询结果 if selection.text != Selection.current.text: logger.debug( 'Redraw canceled, since selection has changed: original=%s, current=%s', repr(selection.text), repr(Selection.current.text)) return logger.debug('Redraw started for query=%s', repr(selection.text)) self.current_query_result = query_result self.widgets.draw(query_result) minimum_height, natural_height = self.box.get_preferred_height() # Avoid warning: Allocating size to window without calling gtk_widget_get_preferred_width/height() # self.get_preferred_width() # self.get_preferred_height() self.resize(self.WINDOW_WIDTH, minimum_height) self.move_window(selection) self.show() self.time_to_hide = time.time() + self.popup_timeout if self.auto_play and query_result.speech_path: self.pronounce(query_result.speech_path)
def query(self, text: str) -> Optional[QueryResult]: try: res = requests.get(self.API, params=self._params(text), timeout=self.config.request_timeout) if not res.ok: logger.error( '[%s] Request failed for query=%s: status_code=%s, reason=%s, content=%s', self.id, repr(text), res.status_code, res.reason, repr(res.text)) return try: result = res.json() except json.decoder.JSONDecodeError: logger.error('[%s] Invalid JSON response for query=%s: ', self.id, repr(text), repr(res.text)) return if result['errorCode'] != '0': logger.error('[%s] Query failed for query=%s: errorCode=%s', self.id, repr(text), str(result['errorCode'])) return logger.debug('[%s] Request success for query=%s: %s', self.id, repr(text), result) language = result['l'].replace('2zh-CHS', '').lower() translation = result['translation'] != [ result['query'] ] and '; '.join(result['translation']) or None basic = result.get('basic') phrases = result.get('web') or None # 检查有无有效翻译结果。translation 和 explanations 至少要有其一 # 特例: # * 无 translation, 有 explanations: alt, github # * 有 translation, 无 explanations: 除英语外的其它语种 if not translation and (not basic or not basic.get('explains')): logger.debug('[%s] No translation for query=%s', self.id, repr(text)) return if phrases is not None: for phrase in phrases: phrase['value'] = '; '.join(phrase['value']) phrase['dict_link'] = __class__.dict_link( language, phrase['key']) # 小语种查询结果没有 'query' query_result = QueryResult( result.get('query', text), translation, dict_link=__class__.dict_link(language, result.get('query', text)), phonetic=basic and (basic.get('us-phonetic') or basic.get('uk-phonetic') or basic.get('phonetic')), explanations=basic and basic.get('explains'), phrases=phrases) return query_result except requests.exceptions.RequestException: logger.exception('[%s] Request failed for query=%s', self.id, repr(text))