diff --git a/advanced.py b/advanced.py index d53305a..9f81333 100644 --- a/advanced.py +++ b/advanced.py @@ -1,10 +1,9 @@ import time -import traceback from types import MethodType from calibre.constants import __version__ -from .lib.utils import uid +from .lib.utils import uid, traceback_error from .lib.config import get_config from .lib.encodings import encoding_list from .lib.cache import Paragraph, get_cache @@ -107,7 +106,7 @@ def prepare_ebook_data(self): except Exception: self.progress_message.emit( _('Failed to extract ebook content')) - self.progress_detail.emit('\n' + traceback.format_exc()) + self.progress_detail.emit('\n' + traceback_error()) self.progress.emit(100) self.clean_cache(cache) return diff --git a/components/engine.py b/components/engine.py index 85507e1..04e67fc 100644 --- a/components/engine.py +++ b/components/engine.py @@ -1,9 +1,8 @@ import time import uuid -import traceback from types import GeneratorType -from ..lib.utils import sorted_mixed_keys +from ..lib.utils import sorted_mixed_keys, traceback_error from ..lib.config import get_config from ..engines.custom import ( create_engine_template, load_engine_data, CustomTranslate) @@ -79,7 +78,7 @@ def translate_text(self, text): self.complete.emit() except Exception: self.clear.emit() - self.result.emit(traceback.format_exc(chain=False).strip()) + self.result.emit(traceback_error()) @pyqtSlot() def check_usage(self): diff --git a/engines/base.py b/engines/base.py index 2be704e..c91b740 100644 --- a/engines/base.py +++ b/engines/base.py @@ -1,11 +1,12 @@ import ssl import os.path -import traceback from mechanize import Browser, Request, HTTPError from calibre import get_proxies from calibre.utils.localization import lang_as_iso639_1 +from ..lib.utils import traceback_error + load_translations() @@ -201,7 +202,7 @@ def get_result(self, url, data=None, headers={}, method='GET', except Exception as e: if silence: return None - error = [traceback.format_exc(chain=False).strip()] + error = [traceback_error()] if isinstance(e, HTTPError): error.append(e.read().decode('utf-8')) elif result: diff --git a/engines/google.py b/engines/google.py index 32e62bf..d0ba817 100644 --- a/engines/google.py +++ b/engines/google.py @@ -4,9 +4,10 @@ import time import json import os.path -import traceback from subprocess import Popen, PIPE +from ..lib.utils import traceback_error + from .base import Base from .languages import google, gemini @@ -88,7 +89,7 @@ def _run_command(self, command, silence=False): if silence: return None raise Exception( - message.format(command, '\n\n%s' % traceback.format_exc())) + message.format(command, '\n\n%s' % traceback_error())) if process.wait() != 0: if silence: return None diff --git a/lib/async_handler.py b/lib/async_handler.py index 032c0d1..eee9861 100644 --- a/lib/async_handler.py +++ b/lib/async_handler.py @@ -1,8 +1,9 @@ import sys import asyncio -import traceback import concurrent.futures +from ..lib.utils import traceback_error + from .exception import TranslationCanceled @@ -50,7 +51,7 @@ async def translation_worker(self): self.done_queue.task_done() break except Exception: - paragraph.error = traceback.format_exc(chain=False).strip() + paragraph.error = traceback_error() self.done_queue.put_nowait(paragraph) self.queue.task_done() diff --git a/lib/thread_handler.py b/lib/thread_handler.py index 3844013..575adc5 100644 --- a/lib/thread_handler.py +++ b/lib/thread_handler.py @@ -1,7 +1,8 @@ import time -import traceback from threading import Thread +from ..lib.utils import traceback_error + from .exception import TranslationCanceled @@ -46,7 +47,7 @@ def translation_thread(self): self.done_queue.task_done() break except Exception: - paragraph.error = traceback.format_exc(chain=False).strip() + paragraph.error = traceback_error() self.done_queue.put(paragraph) self.queue.task_done() diff --git a/lib/translation.py b/lib/translation.py index dc73697..bc72ac1 100644 --- a/lib/translation.py +++ b/lib/translation.py @@ -8,7 +8,7 @@ from ..engines import GoogleFreeTranslate from ..engines.custom import CustomTranslate -from .utils import sep, trim, dummy +from .utils import sep, trim, dummy, traceback_error from .config import get_config from .exception import ( TranslationFailed, TranslationCanceled, NoAvailableApiKey) @@ -121,7 +121,7 @@ def need_stop(self): return self.translator.max_error_count > 0 and \ self.abort_count >= self.translator.max_error_count - def _translate_text(self, text, retry=0, interval=0): + def _translate_text(self, row, text, retry=0, interval=0): """Translation engine service error code documentation: * https://cloud.google.com/apis/design/errors * https://www.deepl.com/docs-api/api-access/error-handling/ @@ -155,11 +155,14 @@ def _translate_text(self, text, retry=0, interval=0): interval += 5 # Logging any errors that occur during translation. logged_text = text[:200] + '...' if len(text) > 200 else text - error_message = '{0}\n{2}\n{1}\n{3}\n{1}\n{4}'.format( - sep(), sep('┈'), _('Original: {}').format(logged_text), + error_messages = [ + sep(), _('Original: {}').format(logged_text), sep('┈'), _('Status: Failed {} times / Sleeping for {} seconds') - .format(retry, interval), _('Error: {}').format(str(e))) - self.log(error_message, True) + .format(retry, interval), sep('┈'), _('Error: {}') + .format(traceback_error())] + if row >= 0: + error_messages.insert(1, _('row: {}').format(row)) + self.log('\n'.join(error_messages), True) time.sleep(interval) return self._translate_text(text, retry, interval) @@ -171,7 +174,7 @@ def translate_paragraph(self, paragraph): return self.streaming('') self.streaming(_('Translating...')) - translation = self._translate_text(paragraph.original) + translation = self._translate_text(paragraph.row, paragraph.original) # Process streaming text if isinstance(translation, GeneratorType): if self.total == 1: @@ -203,21 +206,25 @@ def process_translation(self, paragraph): self.streaming(paragraph) self.callback(paragraph) + row = paragraph.row original = paragraph.original.strip() if paragraph.error is None: self.log(sep()) + if row >= 0: + self.log(_('Row: {}').format(row)) self.log(_('Original: {}').format(original)) self.log(sep('┈')) message = _('Translation: {}') if paragraph.is_cache: message = _('Translation (Cached): {}') self.log(message.format(paragraph.translation.strip())) - else: - self.log(sep(), True) - self.log(_('Original: {}').format(original), True) - self.log(sep('┈'), True) - self.log(_('Error: {}').format(paragraph.error.strip()), True) - # paragraph.error = None + # else: + # self.log(sep(), True) + # self.log(_('Row: {}').format(row)) + # self.log(_('Original: {}').format(original), True) + # self.log(sep('┈'), True) + # self.log(_('Error: {}').format(paragraph.error.strip()), True) + # # paragraph.error = None def handle(self, paragraphs=[]): start_time = time.time() diff --git a/lib/utils.py b/lib/utils.py index d170f22..aeacfe1 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -3,12 +3,11 @@ import codecs import socket import hashlib +import traceback from subprocess import Popen from ..lib.cssselect import GenericTranslator, SelectorError -from .encodings import encoding_list - ns = {'x': 'http://www.w3.org/1999/xhtml'} is_test = 'unittest' in sys.modules @@ -129,5 +128,12 @@ def open_file(path, encoding='utf-8'): return file.read().decode(encoding) +def traceback_error(): + try: + return traceback.format_exc(chain=False).strip() + except Exception: + return traceback.format_exc().strip() + + def dummy(*args, **kwargs): pass