def check_lines(self, lines, i): """check lines have less than a maximum number of characters """ max_chars = self.config.max_line_length ignore_long_line = self.config.ignore_long_lines for line in lines.splitlines(True): if not line.endswith('\n'): self.add_message('missing-final-newline', line=i) else: stripped_line = line.rstrip() if not stripped_line and _EMPTY_LINE in self.config.no_space_check: # allow empty lines pass elif line[len(stripped_line):] not in ('\n', '\r\n'): self.add_message('trailing-whitespace', line=i) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and mobj.group(1).split('=', 1)[0].strip() == 'disable': line = line.split('#')[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message('line-too-long', line=i, args=(len(line), max_chars)) i += 1
def check_line(line, i): if not line.endswith('\n'): self.add_message('missing-final-newline', line=i) else: # exclude \f (formfeed) from the rstrip stripped_line = line.rstrip('\t\n\r\v ') if not stripped_line and _EMPTY_LINE in self.config.no_space_check: # allow empty lines pass elif line[len(stripped_line):] not in ('\n', '\r\n'): self.add_message('trailing-whitespace', line=i) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and '=' in line: front_of_equal, back_of_equal = mobj.group(1).split('=', 1) if front_of_equal.strip() == 'disable': if 'line-too-long' in [ _msg_id.strip() for _msg_id in back_of_equal.split(',') ]: return None line = line.rsplit('#', 1)[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message('line-too-long', line=i, args=(len(line), max_chars)) return i + 1
def check_line(line, i): if not line.endswith('\n'): self.add_message('missing-final-newline', line=i) else: # exclude \f (formfeed) from the rstrip stripped_line = line.rstrip('\t\n\r\v ') if not stripped_line and _EMPTY_LINE in self.config.no_space_check: # allow empty lines pass elif line[len(stripped_line):] not in ('\n', '\r\n'): self.add_message('trailing-whitespace', line=i, col_offset=len(stripped_line)) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and '=' in line: front_of_equal, _, back_of_equal = mobj.group(1).partition('=') if front_of_equal.strip() == 'disable': if 'line-too-long' in {_msg_id.strip() for _msg_id in back_of_equal.split(',')}: return None line = line.rsplit('#', 1)[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message('line-too-long', line=i, args=(len(line), max_chars)) return i + 1
def check_line(line, i): if not line.endswith("\n"): self.add_message("missing-final-newline", line=i) else: # exclude \f (formfeed) from the rstrip stripped_line = line.rstrip("\t\n\r\v ") if not stripped_line and _EMPTY_LINE in self.config.no_space_check: # allow empty lines pass elif line[len(stripped_line):] not in ("\n", "\r\n"): self.add_message("trailing-whitespace", line=i, col_offset=len(stripped_line)) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and "=" in line: front_of_equal, _, back_of_equal = mobj.group(1).partition("=") if front_of_equal.strip() == "disable": if "line-too-long" in { _msg_id.strip() for _msg_id in back_of_equal.split(",") }: return None line = line.rsplit("#", 1)[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message("line-too-long", line=i, args=(len(line), max_chars)) return i + 1
def _check_note(self, notes, lineno, line, module_last_lineno): """ Add the message 'fixme' in case a note is found in the line. :param notes: regular expression object matching any notes (XXX, TODO, FIXME) behind a '#' :type notes: re.pattern object :param lineno: line number :type lineno: int :param line: line to be checked :type line: str :param module_last_lineno: last line number of the module as parsed by astroid (may be different from real last line number in case commented lines exist at the end of the module) :type module_last_lineno: int """ # First, simply check if the notes are in the line at all. This is an # optimisation to prevent using the regular expression on every line, # but rather only on lines which may actually contain one of the notes. # This prevents a pathological problem with lines that are hundreds # of thousands of characters long. for note in map(str.lower, self.config.notes): if note in line.lower(): break else: return match = notes.search(line) if not match: return # In case the module ends with commented lines, the astroid parser # don't take into account those lines, then: # - the line number of those lines is greater than the # module last line number (module.tolineno) # - astroid module object can't inform pylint # of disabled messages in those extra lines. if lineno > module_last_lineno: disable_option_match = OPTION_RGX.search(line) if disable_option_match: try: _, value = disable_option_match.group(1).split('=', 1) values = [ _val.strip().upper() for _val in value.split(',') ] if set(values) & set(self.config.notes): return except ValueError: self.add_message( 'bad-inline-option', args=disable_option_match.group(1).strip(), line=line) return self.add_message('fixme', args=line[match.start(1):].rstrip(), line=lineno, col_offset=match.start(1))
def process_tokens(self, tokens): """process tokens from the current module to search for module/block level options """ for (tok_type, content, start, _, _) in tokens: if tok_type != tokenize.COMMENT: continue match = OPTION_RGX.search(content) if match is None: continue if match.group(1).strip() == "disable-all" or \ match.group(1).strip() == 'skip-file': if match.group(1).strip() == "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: opt, value = match.group(1).split('=', 1) except ValueError: self.add_message('bad-inline-option', args=match.group(1).strip(), line=start[0]) continue opt = opt.strip() if opt in self._options_methods or opt in self._bw_options_methods: try: meth = self._options_methods[opt] except KeyError: meth = self._bw_options_methods[opt] # found a "(dis|en)able-msg" pragma deprecated suppresssion self.add_message('deprecated-pragma', line=start[0], args=(opt, opt.replace('-msg', ''))) for msgid in splitstrip(value): try: if (opt, 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 meth(msgid, 'module', start[0]) except UnknownMessage: self.add_message('bad-option-value', args=msgid, line=start[0]) else: self.add_message('unrecognized-inline-option', args=opt, line=start[0])
def _check_note(self, notes, lineno, line, module_last_lineno): """ Add the message 'fixme' in case a note is found in the line. :param notes: regular expression object matching any notes (XXX, TODO, FIXME) behind a '#' :type notes: re.pattern object :param lineno: line number :type lineno: int :param line: line to be checked :type line: str :param module_last_lineno: last line number of the module as parsed by astroid (may be different from real last line number in case commented lines exist at the end of the module) :type module_last_lineno: int """ # First, simply check if the notes are in the line at all. This is an # optimisation to prevent using the regular expression on every line, # but rather only on lines which may actually contain one of the notes. # This prevents a pathological problem with lines that are hundreds # of thousands of characters long. for note in map(str.lower, self.config.notes): if note in line.lower(): break else: return match = notes.search(line) if not match: return # In case the module ends with commented lines, the astroid parser # don't take into account those lines, then: # - the line number of those lines is greater than the # module last line number (module.tolineno) # - astroid module object can't inform pylint # of disabled messages in those extra lines. if lineno > module_last_lineno: disable_option_match = OPTION_RGX.search(line) if disable_option_match: try: _, value = disable_option_match.group(1).split('=', 1) values = [_val.strip().upper() for _val in value.split(',')] if set(values) & set(self.config.notes): return except ValueError: self.add_message('bad-inline-option', args=disable_option_match.group(1).strip(), line=line) return self.add_message('fixme', args=line[match.start(1):].rstrip(), line=lineno, col_offset=match.start(1))
def process_tokens(self, tokens): """process tokens from the current module to search for module/block level options """ comment = tokenize.COMMENT newline = tokenize.NEWLINE for (tok_type, _, start, _, line) in tokens: if tok_type not in (comment, newline): continue match = OPTION_RGX.search(line) if match is None: continue if match.group(1).strip() == "disable-all" or match.group( 1).strip() == 'skip-file': if match.group(1).strip() == "disable-all": self.add_message('I0014', line=start[0]) self.add_message('I0013', line=start[0]) self._ignore_file = True return try: opt, value = match.group(1).split('=', 1) except ValueError: self.add_message('I0010', args=match.group(1).strip(), line=start[0]) continue opt = opt.strip() if opt in self._options_methods or opt in self._bw_options_methods: try: meth = self._options_methods[opt] except KeyError: meth = self._bw_options_methods[opt] warn( '%s is deprecated, replace it with %s (%s, line %s)' % (opt, opt.split('-')[0], self.current_file, line), DeprecationWarning) for msgid in splitstrip(value): try: if (opt, msgid) == ('disable', 'all'): self.add_message('I0014', line=start[0]) self.add_message('I0013', line=start[0]) self._ignore_file = True return meth(msgid, 'module', start[0]) except UnknownMessage: self.add_message('E0012', args=msgid, line=start[0]) else: self.add_message('E0011', args=opt, line=start[0])
def _check_note(self, notes, lineno, line, module_last_lineno): """ Add the message 'fixme' in case a note is found in the line. :param notes: regular expression object matching any notes (XXX, TODO, FIXME) behind a '#' :type notes: re.pattern object :param lineno: line number :type lineno: int :param line: line to be checked :type line: str :param module_last_lineno: last line number of the module as parsed by astroid (may be different from real last line number in case commented lines exist at the end of the module) :type module_last_lineno: int """ match = notes.search(line) if not match: return # In case the module ends with commented lines, the astroid parser # don't take into account those lines, then: # - the line number of those lines is greater than the # module last line number (module.tolineno) # - astroid module object can't inform pylint # of disabled messages in those extra lines. if lineno > module_last_lineno: disable_option_match = OPTION_RGX.search(line) if disable_option_match: try: _, value = disable_option_match.group(1).split("=", 1) values = [ _val.strip().upper() for _val in value.split(",") ] if set(values) & set(self.config.notes): return except ValueError: self.add_message( "bad-inline-option", args=disable_option_match.group(1).strip(), line=line, ) return self.add_message( "fixme", args=line[match.start(1):].rstrip(), line=lineno, col_offset=match.start(1), )
def _check_note(self, notes, lineno, line, module_last_lineno): """ Add the message 'fixme' in case a note is found in the line. :param notes: regular expression object matching any notes (XXX, TODO, FIXME) behind a '#' :type notes: re.pattern object :param lineno: line number :type lineno: int :param line: line to be checked :type line: str :param module_last_lineno: last line number of the module as parsed by astroid (may be different from real last line number in case commented lines exist at the end of the module) :type module_last_lineno: int """ match = notes.search(line) if not match: return # In case the module ends with commented lines, the astroid parser # don't take into account those lines, then: # - the line number of those lines is greater than the # module last line number (module.tolineno) # - astroid module object can't inform pylint # of disabled messages in those extra lines. if lineno > module_last_lineno: disable_option_match = OPTION_RGX.search(line) if disable_option_match: try: _, value = disable_option_match.group(1).split("=", 1) values = [_val.strip().upper() for _val in value.split(",")] if set(values) & set(self.config.notes): return except ValueError: self.add_message( "bad-inline-option", args=disable_option_match.group(1).strip(), line=line, ) return self.add_message( "fixme", args=line[match.start(1) :].rstrip(), line=lineno, col_offset=match.start(1), )
def process_tokens(self, tokens): """process tokens from the current module to search for module/block level options """ comment = tokenize.COMMENT newline = tokenize.NEWLINE for (tok_type, _, start, _, line) in tokens: if tok_type not in (comment, newline): continue match = OPTION_RGX.search(line) if match is None: continue if match.group(1).strip() == "disable-all" or match.group(1).strip() == 'skip-file': if match.group(1).strip() == "disable-all": self.add_message('I0014', line=start[0]) self.add_message('I0013', line=start[0]) self._ignore_file = True return try: opt, value = match.group(1).split('=', 1) except ValueError: self.add_message('I0010', args=match.group(1).strip(), line=start[0]) continue opt = opt.strip() if opt in self._options_methods or opt in self._bw_options_methods: try: meth = self._options_methods[opt] except KeyError: meth = self._bw_options_methods[opt] warn('%s is deprecated, replace it with %s (%s, line %s)' % ( opt, opt.split('-')[0], self.current_file, line), DeprecationWarning) for msgid in splitstrip(value): try: if (opt, msgid) == ('disable', 'all'): self.add_message('I0014', line=start[0]) self.add_message('I0013', line=start[0]) self._ignore_file = True return meth(msgid, 'module', start[0]) except UnknownMessage: self.add_message('E0012', args=msgid, line=start[0]) else: self.add_message('E0011', args=opt, line=start[0])
def check_line(line, i, prev_line=None): if not line.endswith('\n'): self.add_message('missing-final-newline', line=i) else: # exclude \f (formfeed) from the rstrip stripped_line = line.rstrip('\t\n\r\v ') if not stripped_line and _EMPTY_LINE in self.config.no_space_check: # allow empty lines pass elif line[len(stripped_line):] not in ('\n', '\r\n'): self.add_message('trailing-whitespace', line=i) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and mobj.group(1).split('=', 1)[0].strip() == 'disable': line = line.split('#')[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message('line-too-long', line=i, args=(len(line), max_chars)) return i + 1
def check_lines(self, lines, i): """check lines have less than a maximum number of characters """ max_chars = self.config.max_line_length ignore_long_line = self.config.ignore_long_lines for line in lines.splitlines(True): if not line.endswith('\n'): self.add_message('C0304', line=i) else: stripped_line = line.rstrip() if line[len(stripped_line):] not in ('\n', '\r\n'): self.add_message('C0303', line=i) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and mobj.group(1).split('=', 1)[0].strip() == 'disable': line = line.split('#')[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message('C0301', line=i, args=(len(line), max_chars)) i += 1
def check_lines(self, lines, i): """check lines have less than a maximum number of characters """ max_chars = self.config.max_line_length ignore_long_line = self.config.ignore_long_lines for line in lines.splitlines(True): if not line.endswith("\n"): self.add_message("missing-final-newline", line=i) else: stripped_line = line.rstrip() if line[len(stripped_line) :] not in ("\n", "\r\n"): self.add_message("trailing-whitespace", line=i) # Don't count excess whitespace in the line length. line = stripped_line mobj = OPTION_RGX.search(line) if mobj and mobj.group(1).split("=", 1)[0].strip() == "disable": line = line.split("#")[0].rstrip() if len(line) > max_chars and not ignore_long_line.search(line): self.add_message("line-too-long", line=i, args=(len(line), max_chars)) i += 1
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_RGX.search(comment_text) if disable_option_match: try: _, value = disable_option_match.group(1).split("=", 1) values = [ _val.strip().upper() for _val in value.split(",") ] 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.string, ) 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], )