def test_disable_checker_with_number_in_name() -> None: comment = "#pylint: disable = j3-custom-checker" match = OPTION_PO.search(comment) assert match for pragma_repr in parse_pragma(match.group(2)): assert pragma_repr.action == "disable" assert pragma_repr.messages == ["j3-custom-checker"]
def test_simple_pragma_no_messages() -> None: comment = "#pylint: skip-file" match = OPTION_PO.search(comment) assert match for pragma_repr in parse_pragma(match.group(2)): assert pragma_repr.action == "skip-file" assert not pragma_repr.messages
def test_simple_pragma_multiple_messages() -> None: comment = "#pylint: disable = missing-docstring, invalid-name" match = OPTION_PO.search(comment) assert match for pragma_repr in parse_pragma(match.group(2)): assert pragma_repr.action == "disable" assert pragma_repr.messages == ["missing-docstring", "invalid-name"]
def test_parse_message_with_dash() -> None: comment = "#pylint: disable = raw_input-builtin" match = OPTION_PO.search(comment) assert match res = list(parse_pragma(match.group(2))) assert res[0].action == "disable" assert res[0].messages == ["raw_input-builtin"]
def test_multiple_pragma_multiple_messages(): comment = "#pylint: disable = missing-docstring, invalid-name, enable = R0202, no-self-use" match = OPTION_PO.search(comment) res = list(parse_pragma(match.group(2))) assert res[0].action == "disable" assert res[0].messages == ["missing-docstring", "invalid-name"] assert res[1].action == "enable" assert res[1].messages == ["R0202", "no-self-use"]
def check_lines(self, lines: str, lineno: int) -> None: """Check given lines for potential messages. Check lines have : - a final newline - no trailing whitespace - less than a maximum number of characters """ # we're first going to do a rough check whether any lines in this set # go over the line limit. If none of them do, then we don't need to # parse out the pylint options later on and can just assume that these # lines are clean # we'll also handle the line ending check here to avoid double-iteration # unless the line lengths are suspect max_chars = self.linter.namespace.max_line_length split_lines = self.specific_splitlines(lines) for offset, line in enumerate(split_lines): self.check_line_ending(line, lineno + offset) # hold onto the initial lineno for later potential_line_length_warning = False for offset, line in enumerate(split_lines): # this check is purposefully simple and doesn't rstrip # since this is running on every line you're checking it's # advantageous to avoid doing a lot of work if len(line) > max_chars: potential_line_length_warning = True break # if there were no lines passing the max_chars config, we don't bother # running the full line check (as we've met an even more strict condition) if not potential_line_length_warning: return # Line length check may be deactivated through `pylint: disable` comment mobj = OPTION_PO.search(lines) checker_off = False if mobj: if not self.is_line_length_check_activated(mobj): checker_off = True # The 'pylint: disable whatever' should not be taken into account for line length count lines = self.remove_pylint_option_from_lines(mobj) # here we re-run specific_splitlines since we have filtered out pylint options above for offset, line in enumerate(self.specific_splitlines(lines)): self.check_line_length(line, lineno + offset, checker_off)
def process_tokens(self, tokens): """inspect the source to find fixme problems""" if not self.config.notes: return comments = ( token_info for token_info in tokens if token_info.type == tokenize.COMMENT ) for comment in comments: comment_text = comment.string[1:].lstrip() # trim '#' and whitespaces # handle pylint disable clauses disable_option_match = OPTION_PO.search(comment_text) if disable_option_match: try: values = [] try: for pragma_repr in ( p_rep for p_rep in parse_pragma(disable_option_match.group(2)) if p_rep.action == "disable" ): values.extend(pragma_repr.messages) except PragmaParserError: # Printing useful information dealing with this error is done in the lint package pass values = [_val.upper() for _val in values] if set(values) & set(self.config.notes): continue except ValueError: self.add_message( "bad-inline-option", args=disable_option_match.group(1).strip(), line=comment.start[0], ) continue # emit warnings if necessary match = self._fixme_pattern.search("#" + comment_text.lower()) if match: note = match.group(1) self.add_message( "fixme", col_offset=comment.string.lower().index(note.lower()), args=comment_text, line=comment.start[0], )
def check_lines(self, lines: str, lineno: int) -> None: """ Check lines have : - a final newline - no trailing whitespace - less than a maximum number of characters """ # By default, check the line length check_l_length = True # Line length check may be deactivated through `pylint: disable` comment mobj = OPTION_PO.search(lines) if mobj: check_l_length = self.is_line_length_check_activated(mobj) # The 'pylint: disable whatever' should not be taken into account for line length count lines = self.remove_pylint_option_from_lines(mobj) for line in self.specific_splitlines(lines): if check_l_length: self.check_line_length(line, lineno) self.check_line_ending(line, lineno) lineno += 1
def _verify_pre_check(filepath): """Check student code for certain issues.""" # Make sure the program doesn't crash for students. # Could use some improvement for better logging and error reporting. try: # Check for inline "pylint:" comment, which may indicate a student # trying to disable a check. with tokenize.open(os.path.expanduser(filepath)) as f: for tok_type, content, _, _, _ in tokenize.generate_tokens( f.readline): if tok_type != tokenize.COMMENT: continue match = OPTION_PO.search(content) if match is not None: print('[ERROR] String "pylint:" found in comment. ' + "No check run on file `{}.`\n".format(filepath)) return False except IndentationError as e: print("[ERROR] python_ta could not check your code due to an " + "indentation error at line {}.".format(e.lineno)) return False except tokenize.TokenError as e: print("[ERROR] python_ta could not check your code due to a " + "syntax error in your file.") return False except UnicodeDecodeError: print("[ERROR] python_ta could not check your code due to an " + "invalid character. Please check the following lines " "in your file and all characters that are marked with a �.") with open(os.path.expanduser(filepath), encoding="utf-8", errors="replace") as f: for i, line in enumerate(f): if "�" in line: print(f" Line {i}: {line}", end="") return False return True
def test_missing_message() -> None: comment = "#pylint: disable = " match = OPTION_PO.search(comment) assert match with pytest.raises(InvalidPragmaError): list(parse_pragma(match.group(2)))
def test_unknown_keyword_with_messages(): comment = "#pylint: unknown-keyword = missing-docstring" match = OPTION_PO.search(comment) with pytest.raises(UnRecognizedOptionError): list(parse_pragma(match.group(2)))
def test_unsupported_assignment() -> None: comment = "#pylint: disable-all = missing-docstring" match = OPTION_PO.search(comment) assert match with pytest.raises(UnRecognizedOptionError): list(parse_pragma(match.group(2)))
def test_missing_keyword(): comment = "#pylint: = missing-docstring" match = OPTION_PO.search(comment) with pytest.raises(InvalidPragmaError): for pragma_repr in parse_pragma(match.group(2)): pass
def test_simple_pragma(): comment = "#pylint: disable = missing-docstring" match = OPTION_PO.search(comment) for pragma_repr in parse_pragma(match.group(2)): assert pragma_repr.action == "disable" assert pragma_repr.messages == ["missing-docstring"]
def test_unsupported_assignment(): comment = "#pylint: disable-all = missing-docstring" match = OPTION_PO.search(comment) with pytest.raises(UnRecognizedOptionError): for pragma_repr in parse_pragma(match.group(2)): pass
def test_missing_keyword() -> None: comment = "#pylint: = missing-docstring" match = OPTION_PO.search(comment) assert match with pytest.raises(InvalidPragmaError): list(parse_pragma(match.group(2)))
def test_unknown_keyword_without_messages(): comment = "#pylint: unknown-keyword" match = OPTION_PO.search(comment) with pytest.raises(UnRecognizedOptionError): for pragma_repr in parse_pragma(match.group(2)): pass
def test_unknown_keyword_without_messages() -> None: comment = "#pylint: unknown-keyword" match = OPTION_PO.search(comment) assert match with pytest.raises(UnRecognizedOptionError): list(parse_pragma(match.group(2)))
def test_missing_message(): comment = "#pylint: disable = " match = OPTION_PO.search(comment) with pytest.raises(InvalidPragmaError): for pragma_repr in parse_pragma(match.group(2)): pass
def process_tokens(self, tokens): """process tokens from the current module to search for module/block level options """ control_pragmas = {"disable", "enable"} prev_line = None saw_newline = True seen_newline = True for (tok_type, content, start, _, _) in tokens: if prev_line and prev_line != start[0]: saw_newline = seen_newline seen_newline = False prev_line = start[0] if tok_type in (tokenize.NL, tokenize.NEWLINE): seen_newline = True if tok_type != tokenize.COMMENT: continue match = OPTION_PO.search(content) if match is None: continue try: for pragma_repr in parse_pragma(match.group(2)): if pragma_repr.action in ("disable-all", "skip-file"): if pragma_repr.action == "disable-all": self.add_message( "deprecated-pragma", line=start[0], args=("disable-all", "skip-file"), ) self.add_message("file-ignored", line=start[0]) self._ignore_file = True return try: meth = self._options_methods[pragma_repr.action] except KeyError: meth = self._bw_options_methods[pragma_repr.action] # found a "(dis|en)able-msg" pragma deprecated suppression self.add_message( "deprecated-pragma", line=start[0], args=( pragma_repr.action, pragma_repr.action.replace("-msg", ""), ), ) for msgid in pragma_repr.messages: # Add the line where a control pragma was encountered. if pragma_repr.action in control_pragmas: self._pragma_lineno[msgid] = start[0] if (pragma_repr.action, msgid) == ("disable", "all"): self.add_message( "deprecated-pragma", line=start[0], args=("disable=all", "skip-file"), ) self.add_message("file-ignored", line=start[0]) self._ignore_file = True return # If we did not see a newline between the previous line and now, # we saw a backslash so treat the two lines as one. l_start = start[0] if not saw_newline: l_start -= 1 try: meth(msgid, "module", l_start) except exceptions.UnknownMessageError: self.add_message("bad-option-value", args=msgid, line=start[0]) except UnRecognizedOptionError as err: self.add_message("unrecognized-inline-option", args=err.token, line=start[0]) continue except InvalidPragmaError as err: self.add_message("bad-inline-option", args=err.token, line=start[0]) continue
def test_missing_assignment(): comment = "#pylint: disable missing-docstring" match = OPTION_PO.search(comment) with pytest.raises(InvalidPragmaError): list(parse_pragma(match.group(2)))