Esempio n. 1
0
    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:&nbsp;&nbsp;'
                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)
Esempio n. 2
0
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)