示例#1
0
    def __init__(self, error_info):
        super().__init__(error_info)

        if "Address already in use" in self.error_info["message"]:
            self.intro_text = "Your programs tries to listen on a port which is already taken."
            self.suggestions = [
                Suggestion(
                    "kill-by-port-type-error",
                    "Want to close the other process?",
                    self.get_kill_process_instructions(),
                    5,
                ),
                Suggestion(
                    "use-another-type-error",
                    "Can you use another port?",
                    "If you don't want to mess with the other process, then check whether"
                    + " you can configure your program to use another port.",
                    3,
                ),
            ]

        else:
            self.intro_text = "No specific information is available for this error."
示例#2
0
    def _sug_bad_type(self):
        if self._is_call_function():
            action = "call this function on"
        else:
            action = "ask this attribute from"

        return Suggestion(
            "wrong-type-attribute",
            "Did you expect another type?",
            "If you didn't mean %s %s, " % (action, _get_phrase_for_object(self.type_name))
            + "then step through your program to see "
            + "why this type appears here.",
            3,
        )
    def _sug_missing_quotes(self):
        if self._is_attribute_value() or self._is_call_function(
        ) or self._is_subscript_value():
            relevance = 0
        else:
            relevance = 5

        return Suggestion(
            "missing-quotes",
            "Did you actually mean string (text)?",
            'If you didn\'t mean a variable but literal text "%s", then surround it with quotes.'
            % self.name,
            relevance,
        )
    def __init__(self, error_info):
        super().__init__(error_info)

        self.intro_text = (
            "Python was asked to do an operation with an object which " +
            "doesn't support it.")

        self.suggestions = [
            Suggestion(
                "step-to-find-type-error",
                "Did you expect another type?",
                "Step through your program to see why this type appears here.",
                3,
            ),
            Suggestion(
                "look-documentation-type-error",
                "Maybe you forgot some details about this operation?",
                "Look up the documentation or perform a web search with the error message.",
                2,
            ),
        ]

        # overwrite / add for special cases
        # something + str or str + something
        for r, string_first in [
            (r"unsupported operand type\(s\) for \+: '(.+?)' and 'str'",
             False),
            (r"^Can't convert '(.+?)' object to str implicitly$",
             True),  # Python 3.5
            (r"^must be str, not (.+)$", True),  # Python 3.6
            (r'^can only concatenate str (not "(.+?)") to str$',
             True),  # Python 3.7
        ]:
            m = re.match(r, error_info["message"], re.I)  # @UndefinedVariable
            if m is not None:
                self._bad_string_concatenation(m.group(1), string_first)
                return
    def _sug_local_from_global(self):
        relevance = 0
        body = None

        if (
            self.last_frame.code_name == "<module>"
            and self.last_frame_module_ast is not None
        ):
            function_names = set()
            for node in ast.walk(self.last_frame_module_ast):
                if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
                    if self.name in map(lambda x: x.arg, node.args.args):
                        function_names.add(node.name)
                    # TODO: varargs, kw, ...
                    declared_global = False
                    for localnode in ast.walk(node):
                        # print(node.name, localnode)
                        if (
                            isinstance(localnode, ast.Name)
                            and localnode.id == self.name
                            and isinstance(localnode.ctx, ast.Store)
                        ):
                            function_names.add(node.name)
                        elif (
                            isinstance(localnode, ast.Global)
                            and self.name in localnode.names
                        ):
                            declared_global = True

                    if node.name in function_names and declared_global:
                        function_names.remove(node.name)

            if function_names:
                relevance = 9
                body = (
                    (
                        "Name `%s` defined in `%s` is not accessible in the global/module level."
                        % (self.name, " and ".join(function_names))
                    )
                    + "\n\nIf you need that data at the global level, then consider changing the function so that it `return`-s the value."
                )

        return Suggestion(
            "local-from-global",
            "Are you trying to acces a local variable outside of the function?",
            body,
            relevance,
        )
    def _sug_bad_spelling(self):

        # Yes, it would be more proper to consult builtins from the backend,
        # but it's easier this way...
        all_names = {
            name
            for name in dir(builtins) if not name.startswith("_")
        }
        all_names |= {"pass", "break", "continue", "return", "yield"}

        if self.last_frame.globals is not None:
            all_names |= set(self.last_frame.globals.keys())
        if self.last_frame.locals is not None:
            all_names |= set(self.last_frame.locals.keys())

        similar_names = {self.name}
        if all_names:
            relevance = 0
            for name in all_names:
                sim = name_similarity(name, self.name)
                if sim > 4:
                    similar_names.add(name)
                relevance = max(sim, relevance)
        else:
            relevance = 3

        if len(similar_names) > 1:
            body = "I found similar names. Are all of them spelled correctly?\n\n"
            for name in sorted(similar_names, key=lambda x: x.lower()):
                # TODO: add location info
                body += "* `%s`\n\n" % name
        else:
            body = (
                "Compare the name with corresponding definition / assignment / documentation."
                + " Don't forget that case of the letters matters!")

        return Suggestion("bad-spelling-name",
                          "Did you misspell it (somewhere)?", body, relevance)
    def _sug_wrong_attribute_instead_of_len(self):

        if self.type_name == "str":
            goal = "length"
        elif self.type_name == "bytes":
            goal = "number of bytes"
        elif self.type_name == "list":
            goal = "number of elements"
        elif self.type_name == "tuple":
            goal = "number of elements"
        elif self.type_name == "set":
            goal = "number of elements"
        elif self.type_name == "dict":
            goal = "number of entries"
        else:
            return None

        return Suggestion(
            "wrong-attribute-instead-of-len",
            "Did you mean to ask the %s?" % goal,
            "This can be done with function `len`, eg:\n\n`len(%s)`"
            % _get_sample_for_type(self.type_name),
            (9 if self.att_name.lower() in ("len", "length", "size") else 0),
        )
    def _sug_missing_or_misplaced_colon(self):
        import tokenize

        i = 0
        title = "Did you forget the colon?"
        relevance = 0
        body = ""
        while i < len(self.tokens) and self.tokens[i].type != token.ENDMARKER:
            t = self.tokens[i]
            if t.string in [
                "if",
                "elif",
                "else",
                "while",
                "for",
                "with",
                "try",
                "except",
                "finally",
                "class",
                "def",
            ]:
                keyword_pos = i
                while (
                    self.tokens[i].type
                    not in [
                        token.NEWLINE,
                        token.ENDMARKER,
                        token.COLON,  # colon may be OP
                        token.RBRACE,
                    ]
                    and self.tokens[i].string != ":"
                ):

                    old_i = i
                    if self.tokens[i].string in "([{":
                        i = self._skip_braced_part(i)
                        assert i > old_i
                        if i == len(self.tokens):
                            return None
                    else:
                        i += 1

                if self.tokens[i].string != ":":
                    relevance = 9
                    body = "`%s` header must end with a colon." % t.string
                    break

                # Colon was present, but maybe it should have been right
                # after the keyword.
                if (
                    t.string in ["else", "try", "finally"]
                    and self.tokens[keyword_pos + 1].string != ":"
                ):
                    title = "Incorrect use of `%s`" % t.string
                    body = "Nothing is allowed between `%s` and colon." % t.string
                    relevance = 9
                    if (
                        self.tokens[keyword_pos + 1].type not in (token.NEWLINE, tokenize.COMMENT)
                        and t.string == "else"
                    ):
                        body = "If you want to specify a conditon, then use `elif` or nested `if`."
                    break

            i += 1

        return Suggestion("missing-or-misplaced-colon", title, body, relevance)
    def _sug_missing_import(self):
        likely_importable_functions = {
            "math": {"ceil", "floor", "sqrt", "sin", "cos", "degrees"},
            "random": {"randint"},
            "turtle": {
                "left",
                "right",
                "forward",
                "fd",
                "goto",
                "setpos",
                "Turtle",
                "penup",
                "up",
                "pendown",
                "down",
                "color",
                "pencolor",
                "fillcolor",
                "begin_fill",
                "end_fill",
                "pensize",
                "width",
            },
            "re": {"search", "match", "findall"},
            "datetime": {"date", "time", "datetime", "today"},
            "statistics": {
                "mean",
                "median",
                "median_low",
                "median_high",
                "mode",
                "pstdev",
                "pvariance",
                "stdev",
                "variance",
            },
            "os": {"listdir"},
            "time": {"time", "sleep"},
        }

        body = None

        if self._is_call_function():
            relevance = 5
            for mod in likely_importable_functions:
                if self.name in likely_importable_functions[mod]:
                    relevance += 3
                    body = (
                        "If you meant `%s` from module `%s`, then add\n\n`from %s import %s`\n\nto the beginning of your script."
                        % (self.name, mod, mod, self.name)
                    )
                    break

        elif self._is_attribute_value():
            relevance = 5
            body = (
                "If you meant module `%s`, then add `import %s` to the beginning of your script"
                % (self.name, self.name)
            )

            if self.name in likely_importable_functions:
                relevance += 3

        elif self._is_subscript_value() and self.name != "argv":
            relevance = 0
        elif self.name == "pi":
            body = "If you meant the constant π, then add `from math import pi` to the beginning of your script."
            relevance = 8
        elif self.name == "argv":
            body = "If you meant the list with program arguments, then add `from sys import argv` to the beginning of your script."
            relevance = 8
        else:
            relevance = 3

        if body is None:
            body = "Some functions/variables need to be imported before they can be used."

        return Suggestion("missing-import", "Did you forget to import it?", body, relevance)
示例#10
0
    def _sug_unbalanced_parens(self):
        problem = self._find_first_braces_problem()
        if not problem:
            return None

        return Suggestion("missing-or-misplaced-colon", "Unbalanced brackets", problem[1], 8)