def set_plugin(self, plugin: str) -> None: """Set the current plugin shown in the dropdown and text area. Parameters ---------- plugin : str name of a plugin that has created an error this session. """ self.github_button.hide() self.clipboard_button.hide() try: self.github_button.clicked.disconnect() # when disconnecting a non-existent signal # PySide2 raises runtimeError, PyQt5 raises TypeError except (RuntimeError, TypeError): pass if not plugin or (plugin == self.NULL_OPTION): self.plugin_meta.setText('') self.text_area.setHtml('') return if not self.plugin_manager.get_errors(plugin): raise ValueError(f"No errors reported for plugin '{plugin}'") self.plugin_combo.setCurrentText(plugin) err_string = format_exceptions(plugin, as_html=True) self.text_area.setHtml(err_string) self.clipboard_button.show() # set metadata and outbound links/buttons err0 = self.plugin_manager.get_errors(plugin)[0] meta = standard_metadata(err0.plugin) if err0.plugin else {} meta_text = '' if not meta: self.plugin_meta.setText(meta_text) return url = meta.get('url') if url: meta_text += ( '<span style="color:#999;">plugin home page: ' f'</span><a href="{url}" style="color:#999">{url}</a>') if 'github.com' in url: def onclick(): import webbrowser err = format_exceptions(plugin, as_html=False) err = ( "<!--Provide detail on the error here-->\n\n\n\n" "<details>\n<summary>Traceback from napari</summary>" f"\n\n```\n{err}\n```\n</details>") url = f'{meta.get("url")}/issues/new?&body={err}' webbrowser.open(url, new=2) self.github_button.clicked.connect(onclick) self.github_button.show() self.plugin_meta.setText(meta_text)
def format_exceptions(plugin_name: str, as_html: bool = False): """Return formatted tracebacks for all exceptions raised by plugin. Parameters ---------- plugin_name : str The name of a plugin for which to retrieve tracebacks. as_html : bool Whether to return the exception string as formatted html, defaults to False. Returns ------- str A formatted string with traceback information for every exception raised by ``plugin_name`` during this session. """ _plugin_errors = PluginError.get(plugin_name=plugin_name) if not _plugin_errors: return '' from napari import __version__ from ..utils._tracebacks import get_tb_formatter format_exc_info = get_tb_formatter() _linewidth = 80 _pad = (_linewidth - len(plugin_name) - 18) // 2 msg = [ trans._( "{pad} Errors for plugin '{plugin_name}' {pad}", deferred=True, pad='=' * _pad, plugin_name=plugin_name, ), '', f'{"napari version": >16}: {__version__}', ] err0 = _plugin_errors[0] if err0.plugin: package_meta = standard_metadata(err0.plugin) if package_meta: msg.extend([ f'{"plugin package": >16}: {package_meta["package"]}', f'{"version": >16}: {package_meta["version"]}', f'{"module": >16}: {err0.plugin}', ]) msg.append('') for n, err in enumerate(_plugin_errors): _pad = _linewidth - len(str(err)) - 10 msg += ['', f'ERROR #{n + 1}: {str(err)} {"-" * _pad}', ''] msg.append(format_exc_info(err.info(), as_html)) msg.append('=' * _linewidth) return ("<br>" if as_html else "\n").join(msg)