Esempio n. 1
0
    def _format_warning(self, warning, last):
        title = rst_utils.escape(warning["msg"].splitlines()[0])
        if warning.get("lineno") is not None:
            url = self._format_file_url(warning)
            if warning.get("lineno"):
                title = "`Line %d <%s>`__ : %s" % (warning["lineno"], url,
                                                   title)

        if warning.get("explanation_rst"):
            explanation_rst = warning["explanation_rst"]
        elif warning.get("explanation"):
            explanation_rst = rst_utils.escape(warning["explanation"])
        else:
            explanation_rst = ""

        if warning.get("more_info_url"):
            explanation_rst += "\n\n`More info online <%s>`__" % warning[
                "more_info_url"]

        explanation_rst = explanation_rst.strip()
        topic_class = "toggle" if explanation_rst else "empty"
        if not explanation_rst:
            explanation_rst = "n/a"

        return (".. topic:: %s\n" % title + "    :class: " + topic_class +
                ("" if last else ", tight") + "\n" + "    \n" +
                textwrap.indent(explanation_rst, "    ") + "\n\n")
Esempio n. 2
0
    def __init__(self, error_info):
        super().__init__(error_info)

        self.intro_text = "No specific suggestions for this error (yet)."
        self.intro_confidence = 1
        self.suggestions = [
            Suggestion(
                "ask-for-specific-support",
                "Let Thonny developers know",
                "Click on the feedback link at the bottom of this panel to let Thonny developers know "
                + "about your problem. They may add support for " +
                "such cases in future Thonny versions.",
                1,
            )
        ]

        if error_info["message"].lower() != "invalid syntax":
            self.suggestions.append(
                Suggestion(
                    "generic-search-the-web",
                    "Search the web",
                    "Try performing a web search for\n\n``Python %s: %s``" % (
                        self.error_info["type_name"],
                        rst_utils.escape(self.error_info["message"].replace(
                            "\n", " ").strip()),
                    ),
                    1,
                ))
Esempio n. 3
0
def format_file_url(filename, lineno, col_offset):
    s = "thonny-editor://" + rst_utils.escape(filename).replace(" ", "%20")
    if lineno is not None:
        s += "#" + str(lineno)
        if col_offset is not None:
            s += ":" + str(col_offset)

    return s
Esempio n. 4
0
    def _get_warnings(self, main_file_path):
        # TODO: current dir may be different
        main_file_dir = os.path.dirname(main_file_path)
        if not os.path.isdir(main_file_dir):
            return []

        library_modules = known_stdlib_modules | self._get_3rd_party_modules()

        for item in os.listdir(main_file_dir):
            full_path = os.path.join(main_file_dir, item)
            if item.endswith(".py") and item[:-3] in library_modules:

                if is_same_path(full_path, main_file_path):
                    prelude = "Your program file is named '%s'." % item
                    rename_hint = " (*Run → Rename…* )"
                else:
                    prelude = (
                        "Your working directory `%s <%s>`__ contains a file named '%s'.\n\n"
                        % (
                            rst_utils.escape(main_file_dir),
                            rst_utils.escape(main_file_dir),
                            item,
                        ))
                    rename_hint = ""

                yield {
                    "filename":
                    full_path,
                    "lineno":
                    0,
                    "symbol":
                    "file-shadows-library-module",
                    "msg":
                    "Possibly bad file name",
                    "explanation_rst":
                    prelude + "\n\n" +
                    "When you try to import library module ``%s``, your file will be imported instead.\n\n"
                    % item[:-3] +
                    "Rename your '%s'%s to make the library module visible again."
                    % (item, rename_hint),
                    "group":
                    "warnings",
                    "relevance":
                    5,
                }
Esempio n. 5
0
    def _explain_exception(self, error_info):
        rst = (
            self._get_rst_prelude() +
            rst_utils.create_title(error_info["type_name"] + ": " +
                                   rst_utils.escape(error_info["message"])) +
            "\n")

        if (error_info.get("lineno") is not None and error_info.get("filename")
                and os.path.exists(error_info["filename"])):
            rst += "`%s, line %d <%s>`__\n\n" % (
                os.path.basename(error_info["filename"]),
                error_info["lineno"],
                self._format_file_url(error_info),
            )

        helpers = [
            helper_class(error_info) for helper_class in (
                _error_helper_classes.get(error_info["type_name"], []) +
                _error_helper_classes["*"])
        ]

        best_intro = helpers[0]
        for helper in helpers:
            if helper.intro_confidence > best_intro.intro_confidence:
                best_intro = helper

        # intro
        if best_intro.intro_text:
            rst += (".. note::\n" + "    " +
                    best_intro.intro_text.strip().replace("\n", "\n\n    ") +
                    "\n\n")

        suggestions = [
            suggestion for helper in helpers
            for suggestion in helper.suggestions if suggestion is not None
        ]
        suggestions = sorted(suggestions,
                             key=lambda s: s.relevance,
                             reverse=True)

        if suggestions[0].relevance > 1 or best_intro.intro_confidence > 1:
            relevance_threshold = 2
        else:
            # use relevance 1 only when there is nothing better
            relevance_threshold = 1

        suggestions = [
            s for s in suggestions if s.relevance >= relevance_threshold
        ]

        for i, suggestion in enumerate(suggestions):
            rst += self._format_suggestion(
                suggestion,
                i == len(suggestions) - 1,
                # TODO: is it good if first is preopened?
                # It looks cleaner if it is not.
                False,  # i==0
            )

        self._current_snapshot["exception_suggestions"] = [
            dict(sug._asdict()) for sug in suggestions
        ]

        self.text.append_rst(rst)
        self._append_text("\n")

        self._current_snapshot["exception_type_name"] = error_info["type_name"]
        self._current_snapshot["exception_message"] = error_info["message"]
        self._current_snapshot["exception_file_path"] = error_info["filename"]
        self._current_snapshot["exception_lineno"] = error_info["lineno"]
        self._current_snapshot["exception_rst"] = rst  # for debugging purposes