def test_logs(tmp): log = getLogger(__name__) with Manager(tmp()) as manager: log.info("Strange encoding \xe8 \xe9") # Crafted problematic logRecord try: raise ValueError("[Mock] folder/\xeatre ou ne pas \xeatre.odt") except ValueError as e: log.exception("Oups!") log.exception(repr(e)) log.exception(str(e)) log.exception(e) # Test raw report (calling the Report class manually) report = Report(manager) report.generate() path = report.get_path() assert path.is_file() assert path.suffix == ".zip" # Test the report managed by the Manager path_managed = manager.generate_report() assert path_managed.is_file() assert path_managed.suffix == ".zip"
def test_logs(): log = get_logger(__name__) folder = tempfile.mkdtemp(u'-nxdrive-tests') Options.nxdrive_home = folder manager = Manager() try: log.debug("Strange encoding \xe9") log.debug(u"Unicode encoding \xe8") # Crafted problematic logRecord try: raise ValueError(u'[tests] folder/\xeatre ou ne pas \xeatre.odt') except ValueError as e: log.exception('Oups!') log.exception(repr(e)) log.exception(unicode(e)) # Works but not recommended with pytest.raises(UnicodeEncodeError): log.exception(str(e)) # Using the syntax below will raise the same UnicodeEncodeError # but the logging module takes care of it and just prints out # the exception without raising it. So I let it there FI. # log.exception(e) report = Report(manager, os.path.join(folder, 'report')) report.generate() finally: manager.dispose_db() Manager._singleton = None
def testLogs(self): from nxdrive.osi import AbstractOSIntegration if AbstractOSIntegration.is_windows(): raise SkipTest("Temporarily skipped, need to investigate") # NXDRIVE-358 report = Report(self.manager, os.path.join(self.folder, "report.zip")) log.debug("Strange encoding \xe9") log.debug(u"Unicode encoding \xe8") report.generate()
def test_logs(): log = getLogger(__name__) folder = tempfile.mkdtemp("-nxdrive-tests") Options.nxdrive_home = folder manager = Manager() try: log.debug("Strange encoding \xe8 \xe9") # Crafted problematic logRecord try: raise ValueError("[tests] folder/\xeatre ou ne pas \xeatre.odt") except ValueError as e: log.exception("Oups!") log.exception(repr(e)) log.exception(str(e)) log.exception(e) report = Report(manager, os.path.join(folder, "report")) report.generate() finally: manager.dispose_db() Manager._singleton = None
def fatal_error_qt(exc_formatted: str) -> None: """Display a "friendly" dialog box on fatal error using Qt.""" from PyQt5.QtCore import Qt, QUrl from PyQt5.QtGui import QDesktopServices, QIcon from PyQt5.QtWidgets import ( QApplication, QDialog, QDialogButtonBox, QLabel, QTextEdit, QVBoxLayout, ) from nxdrive.translator import Translator from nxdrive.utils import find_icon, find_resource def section(header: str, content: str) -> str: """Format a "section" of information.""" return f"{header}\n```\n{content.strip()}\n```" Translator(find_resource("i18n")) tr = Translator.get app = QApplication([]) app.setQuitOnLastWindowClosed(True) dialog = QDialog() dialog.setWindowTitle(tr("FATAL_ERROR_TITLE", [APP_NAME])) dialog.setWindowIcon(QIcon(str(find_icon("app_icon.svg")))) dialog.resize(800, 600) layout = QVBoxLayout() css = "font-family: monospace; font-size: 12px;" details = [] # Display a little message to apologize info = QLabel(tr("FATAL_ERROR_MSG", [APP_NAME, COMPANY])) info.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) layout.addWidget(info) # Display CLI arguments if sys.argv[1:]: text = tr("FATAL_ERROR_CLI_ARGS") label_cli = QLabel(text) label_cli.setAlignment(Qt.AlignVCenter) cli_args = QTextEdit() cli_args.setStyleSheet(css) cli_args.setReadOnly(True) args = "\n".join(arg for arg in sys.argv[1:]) details.append(section(text, args)) cli_args.setText(args) cli_args.setSizeAdjustPolicy(QTextEdit.AdjustToContents) layout.addWidget(label_cli) layout.addWidget(cli_args) # Display the exception text = tr("FATAL_ERROR_EXCEPTION") label_exc = QLabel(text) label_exc.setAlignment(Qt.AlignVCenter) exception = QTextEdit() exception.setStyleSheet(css) exception.setReadOnly(True) details.append(section(text, exc_formatted)) exception.setText(exc_formatted) layout.addWidget(label_exc) layout.addWidget(exception) # Display last lines from the memory log with suppress(Exception): from nxdrive.report import Report # Last 20th lines raw_lines = Report.export_logs(-20) lines = b"\n".join(raw_lines).decode(errors="replace") if lines: text = tr("FATAL_ERROR_LOGS") label_log = QLabel(text) details.append(section(text, lines)) label_log.setAlignment(Qt.AlignVCenter) layout.addWidget(label_log) logs = QTextEdit() logs.setStyleSheet(css) logs.setReadOnly(True) logs.setLineWrapColumnOrWidth(4096) logs.setLineWrapMode(QTextEdit.FixedPixelWidth) logs.setText(lines) layout.addWidget(logs) def open_update_site() -> None: """Open the update web site.""" with suppress(Exception): QDesktopServices.openUrl(QUrl(Options.update_site_url)) # Buttons buttons = QDialogButtonBox() buttons.setStandardButtons(QDialogButtonBox.Ok) buttons.accepted.connect(dialog.close) update_button = buttons.addButton(tr("FATAL_ERROR_UPDATE_BTN"), QDialogButtonBox.ActionRole) update_button.setToolTip(tr("FATAL_ERROR_UPDATE_TOOLTIP", [APP_NAME])) update_button.clicked.connect(open_update_site) layout.addWidget(buttons) def copy() -> None: """Copy details to the clipboard and change the text of the button. """ osi.cb_set("\n".join(details)) copy_paste.setText(tr("FATAL_ERROR_DETAILS_COPIED")) # "Copy details" button with suppress(Exception): from nxdrive.osi import AbstractOSIntegration osi = AbstractOSIntegration.get(None) copy_paste = buttons.addButton(tr("FATAL_ERROR_DETAILS_COPY"), QDialogButtonBox.ActionRole) copy_paste.clicked.connect(copy) dialog.setLayout(layout) dialog.show() app.exec_()
def generate_report(self, path=None): from nxdrive.report import Report report = Report(self, path) report.generate() return report.get_path()
def testLogs(self): # NXDRIVE-358 report = Report(self.manager, os.path.join(self.folder, "report.zip")) log.debug("Strange encoding \xe9") log.debug(u"Unicode encoding \xe8") report.generate()
def show_critical_error() -> None: """ Display a "friendly" dialog box on fatal error. """ import traceback from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import ( QApplication, QDialog, QDialogButtonBox, QLabel, QTextEdit, QVBoxLayout, ) app = QApplication([]) app.setQuitOnLastWindowClosed(True) dialog = QDialog() dialog.setWindowTitle("Nuxeo Drive - Fatal error") dialog.resize(600, 400) layout = QVBoxLayout() css = "font-family: monospace; font-size: 12px;" details = ["Exception:"] with suppress(Exception): from nxdrive.utils import find_icon dialog.setWindowIcon(QIcon(find_icon("app_icon.svg"))) # Display a little message to apologize text = f"""Ooops! Unfortunately, a fatal error occurred and Nuxeo Drive has stopped. Please share the following informations with Nuxeo support : we’ll do our best to fix it! """ info = QLabel(text) info.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) layout.addWidget(info) # Display the the exception label_exc = QLabel("Exception:") label_exc.setAlignment(Qt.AlignVCenter) exception = QTextEdit() exception.setStyleSheet(css) exception.setReadOnly(True) exc_formatted = traceback.format_exception(*sys.exc_info()) details += exc_formatted exception.setText("".join(exc_formatted)) layout.addWidget(label_exc) layout.addWidget(exception) # Display last lines from the memory log with suppress(Exception): from nxdrive.report import Report # Last 20th lines lines = Report.export_logs(-20) lines = b"\n".join(lines).decode(errors="replace") details += ["Logs before the crash:", lines] label_log = QLabel("Logs before the crash:") label_log.setAlignment(Qt.AlignVCenter) layout.addWidget(label_log) logs = QTextEdit() logs.setStyleSheet(css) logs.setReadOnly(True) logs.setLineWrapColumnOrWidth(4096) logs.setLineWrapMode(QTextEdit.FixedPixelWidth) logs.setText(lines) layout.addWidget(logs) # Buttons buttons = QDialogButtonBox() buttons.setStandardButtons(QDialogButtonBox.Ok) buttons.accepted.connect(dialog.close) layout.addWidget(buttons) def copy() -> None: """Copy details to the clipboard and change the text of the button. """ copy_to_clipboard("\n".join(details)) copy_paste.setText("Details copied!") # "Copy details" button with suppress(Exception): from nxdrive.utils import copy_to_clipboard copy_paste = buttons.addButton("Copy details", QDialogButtonBox.ActionRole) copy_paste.clicked.connect(copy) dialog.setLayout(layout) dialog.show() app.exec_()