def run(self, filename, file, max_line_length: int = 79, indent_size: int = SpacingHelper.DEFAULT_TAB_WIDTH, ignore_length_regex: typed_list(str) = ()): ''' Yields results for all lines longer than the given maximum line length. :param max_line_length: Maximum number of characters for a line, the newline character being excluded. :param indent_size: Number of spaces per indentation level. :param ignore_length_regex: Lines matching each of the regular expressions in this list will be ignored. ''' spacing_helper = SpacingHelper(indent_size) ignore_regexes = [re.compile(regex) for regex in ignore_length_regex] for line_number, line in enumerate(file): line = spacing_helper.replace_tabs_with_spaces(line) if len(line) > max_line_length + 1: if any(regex.search(line) for regex in ignore_regexes): continue yield Result.from_values( origin=self, message="Line is longer than allowed." + " ({actual} > {maximum})".format(actual=len(line) - 1, maximum=max_line_length), file=filename, line=line_number + 1, column=max_line_length + 1, end_line=line_number + 1, end_column=len(line))
def test_print_spaces_tabs_in_unicode(self): printer = StringPrinter() sh = SpacingHelper(4) test_string = "\the\tllo world " print_spaces_tabs_in_unicode( printer, test_string, dict(sh.yield_tab_lengths(test_string)), "red") self.assertEqual(printer.string, "--->he->llo•world•••") # Test the case when the bullet can't be printed because of encoding # problems. def hijack_print(text, *args, **kwargs): if "•" in text: raise UnicodeEncodeError("test-codec", "", 0, 1, "") else: return StringPrinter.print(printer, text, *args, **kwargs) printer.print = hijack_print printer.clear() test_string = " he\tllo world " print_spaces_tabs_in_unicode(printer, test_string, dict(sh.yield_tab_lengths(test_string)), "red") self.assertEqual(printer.string, ".he>llo..world.")
def run(self, filename, file, max_line_length: int=80, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH): ''' Yields results for all lines longer than the given maximum line length. :param max_line_length: Maximum number of characters for a line. :param tab_width: Number of spaces to show for one tab. ''' spacing_helper = SpacingHelper(tab_width) for line_number, line in enumerate(file): line = spacing_helper.replace_tabs_with_spaces(line) if len(line) > max_line_length + 1: yield Result.from_values( origin=self, message="Line is longer than allowed." + " ({actual} > {maximum})".format( actual=len(line)-1, maximum=max_line_length), file=filename, line=line_number + 1, column=max_line_length + 1, end_line=line_number + 1, end_column=len(line))
def run(self, filename, file, max_line_length: int=79, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH, ignore_length_regex: typed_list(str)=()): ''' Yields results for all lines longer than the given maximum line length. :param max_line_length: Maximum number of characters for a line, the newline character being excluded. :param tab_width: Number of spaces to show for one tab. :param ignore_length_regex: Lines matching each of the regular expressions in this list will be ignored. ''' spacing_helper = SpacingHelper(tab_width) ignore_regexes = [re.compile(regex) for regex in ignore_length_regex] for line_number, line in enumerate(file): line = spacing_helper.replace_tabs_with_spaces(line) if len(line) > max_line_length + 1: if any(regex.search(line) for regex in ignore_regexes): continue yield Result.from_values( origin=self, message="Line is longer than allowed." + " ({actual} > {maximum})".format( actual=len(line)-1, maximum=max_line_length), file=filename, line=line_number + 1, column=max_line_length + 1, end_line=line_number + 1, end_column=len(line))
def test_print_spaces_tabs_in_unicode(self): printer = StringPrinter() sh = SpacingHelper(4) test_string = "\the\tllo world " print_spaces_tabs_in_unicode(printer, test_string, dict(sh.yield_tab_lengths(test_string)), "red") self.assertEqual(printer.string, "--->he->llo•world•••") # Test the case when the bullet can't be printed because of encoding # problems. def hijack_print(text, *args, **kwargs): if "•" in text: raise UnicodeEncodeError("test-codec", "", 0, 1, "") else: return StringPrinter.print(printer, text, *args, **kwargs) printer.print = hijack_print printer.clear() test_string = " he\tllo world " print_spaces_tabs_in_unicode(printer, test_string, dict(sh.yield_tab_lengths(test_string)), "red") self.assertEqual(printer.string, ".he>llo..world.")
def run(self, filename, file, max_line_length: int=80, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH, ignore_length_regex: str=''): ''' Yields results for all lines longer than the given maximum line length. :param max_line_length: Maximum number of characters for a line. :param tab_width: Number of spaces to show for one tab. :param ignore_length_regex: All lines matching this regular expression will be ignored. ''' spacing_helper = SpacingHelper(tab_width) ignore_regex = re.compile(ignore_length_regex) for line_number, line in enumerate(file): line = spacing_helper.replace_tabs_with_spaces(line) if len(line) > max_line_length + 1: if ignore_length_regex and ignore_regex.match(line): continue yield Result.from_values( origin=self, message="Line is longer than allowed." + " ({actual} > {maximum})".format( actual=len(line)-1, maximum=max_line_length), file=filename, line=line_number + 1, column=max_line_length + 1, end_line=line_number + 1, end_column=len(line))
def run_bear(self, filename, file, max_line_length: int, tab_width: int = SpacingHelper.DEFAULT_TAB_WIDTH): """ Yields results for all lines longer than the given maximum line length. :param max_line_length: Maximum number of characters for a line. :param tab_width: Number of spaces to show for one tab. """ results = [] bearname = self.__class__.__name__ spacing_helper = SpacingHelper.from_section(section=self.section) for line_number, line in enumerate(file): line = spacing_helper.replace_tabs_with_spaces(line) if len(line) > max_line_length + 1: results.append( Result(origin=bearname, message=_("Line is longer than allowed.") + " ({actual} > {maximum})".format( actual=len(line), maximum=max_line_length), file=filename, line_nr=line_number + 1)) return results
def run(self, filename, file, max_line_length: int, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH): """ Yields results for all lines longer than the given maximum line length. :param max_line_length: Maximum number of characters for a line. :param tab_width: Number of spaces to show for one tab. """ results = [] spacing_helper = SpacingHelper.from_section(section=self.section) for line_number, line in enumerate(file): line = spacing_helper.replace_tabs_with_spaces(line) if len(line) > max_line_length + 1: results.append( Result(origin=self, message=_("Line is longer than allowed.") + " ({actual} > {maximum})".format( actual=len(line), maximum=max_line_length), file=filename, line_nr=line_number + 1)) return results
def print_lines(console_printer, file_dict, section, sourcerange): """ Prints the lines between the current and the result line. If needed they will be shortened. :param console_printer: Object to print messages on the console. :param file_dict: A dictionary containing all files as values with filenames as key. :param sourcerange: The SourceRange object referring to the related lines to print. """ for i in range(sourcerange.start.line, sourcerange.end.line + 1): console_printer.print(format_lines(lines='', line_nr=i), color=FILE_LINES_COLOR, end='') line = file_dict[sourcerange.file][i - 1].rstrip("\n") tab_width = int(section.get('tab_width', 4)) s = SpacingHelper(tab_width) tab_dict = dict(s.yield_tab_lengths(line)) printed_chars = 0 if i == sourcerange.start.line and sourcerange.start.column: print_spaces_tabs_in_unicode( console_printer, line[:sourcerange.start.column-1], tab_dict, FILE_LINES_COLOR) printed_chars = sourcerange.start.column-1 if i == sourcerange.end.line and sourcerange.end.column: print_spaces_tabs_in_unicode( console_printer, line[printed_chars:sourcerange.end.column-1], tab_dict, HIGHLIGHTED_CODE_COLOR, printed_chars) print_spaces_tabs_in_unicode( console_printer, line[sourcerange.end.column-1:], tab_dict, FILE_LINES_COLOR, sourcerange.end.column-1) console_printer.print("") else: print_spaces_tabs_in_unicode( console_printer, line[printed_chars:], tab_dict, HIGHLIGHTED_CODE_COLOR, printed_chars) console_printer.print("")
def print_lines(console_printer, file_dict, section, sourcerange): """ Prints the lines between the current and the result line. If needed they will be shortened. :param console_printer: Object to print messages on the console. :param file_dict: A dictionary containing all files as values with filenames as key. :param sourcerange: The SourceRange object referring to the related lines to print. """ for i in range(sourcerange.start.line, sourcerange.end.line + 1): console_printer.print(format_lines(lines='', line_nr=i), color=FILE_LINES_COLOR, end='') line = file_dict[sourcerange.file][i - 1].rstrip("\n") tab_width = int(section.get('tab_width', 4)) s = SpacingHelper(tab_width) tab_dict = dict(s.yield_tab_lengths(line)) printed_chars = 0 if i == sourcerange.start.line and sourcerange.start.column: print_spaces_tabs_in_unicode( console_printer, line[:sourcerange.start.column-1], tab_dict, FILE_LINES_COLOR) printed_chars = sourcerange.start.column-1 if i == sourcerange.end.line and sourcerange.end.column: print_spaces_tabs_in_unicode( console_printer, line[printed_chars:sourcerange.end.column-1], tab_dict, HIGHLIGHTED_CODE_COLOR, printed_chars) print_spaces_tabs_in_unicode( console_printer, line[sourcerange.end.column-1:], tab_dict, FILE_LINES_COLOR, sourcerange.end.column) console_printer.print("") else: print_spaces_tabs_in_unicode( console_printer, line[printed_chars:], tab_dict, HIGHLIGHTED_CODE_COLOR, printed_chars) console_printer.print("")
def run(self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool=False, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH): """ Checks the space consistency for each line. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param tab_width: Number of spaces representing one tab. """ results = [] spacing_helper = SpacingHelper(tab_width) for line_number, line in enumerate(file): replacement = line if not allow_trailing_whitespace: replacement = replacement.rstrip(" \t\n") + "\n" if use_spaces: replacement = spacing_helper.replace_tabs_with_spaces( replacement) else: replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != line: diff = Diff() diff.change_line(line_number + 1, line, replacement) results.append(PatchResult(self, _("Line contains spacing " "inconsistencies."), {filename: diff}, filename, line_nr=line_number+1)) return results
class SpacingHelperTestCase(unittest.TestCase): def setUp(self): self.uut = SpacingHelper() def test_needed_settings(self): self.assertEqual(list(self.uut.get_optional_settings()), ["tab_width"]) self.assertEqual(list(self.uut.get_non_optional_settings()), []) def test_construction(self): section = Section("test section") self.assertRaises(TypeError, SpacingHelper, "no integer") self.assertRaises(TypeError, self.uut.from_section, 5) self.assertEqual(self.uut.tab_width, self.uut.from_section(section).tab_width) section.append(Setting("tab_width", "invalid")) # Setting won't be converted since it's not possible, SpacingHelper # will then complain with TypeError self.assertRaises(TypeError, self.uut.from_section, section) # This is assumed in some tests. If you want to change this value, be # sure to change the tests too self.assertEqual(self.uut.DEFAULT_TAB_WIDTH, 4) self.assertEqual(self.uut.tab_width, self.uut.DEFAULT_TAB_WIDTH) def test_get_indentation(self): self.assertRaises(TypeError, self.uut.get_indentation, 5) self.assertEqual(self.uut.get_indentation("no indentation"), 0) self.assertEqual(self.uut.get_indentation(" indentation"), 1) self.assertEqual(self.uut.get_indentation(" indentation"), 2) self.assertEqual(self.uut.get_indentation("\tindentation"), self.uut.DEFAULT_TAB_WIDTH) # Having a space before the tab shouldn't make any difference self.assertEqual(self.uut.get_indentation(" \tindentation"), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(" \t indentation"), self.uut.DEFAULT_TAB_WIDTH + 1) self.assertEqual(self.uut.get_indentation("\t indentation"), self.uut.DEFAULT_TAB_WIDTH + 1) # same tests but with indentation only self.assertEqual(self.uut.get_indentation("\t"), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(" \t"), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(" \t "), self.uut.DEFAULT_TAB_WIDTH + 1) self.assertEqual(self.uut.get_indentation("\t "), self.uut.DEFAULT_TAB_WIDTH + 1) self.assertEqual(self.uut.get_indentation("\t\t"), self.uut.DEFAULT_TAB_WIDTH * 2) def test_replace_tabs_with_spaces(self): self.assertRaises(TypeError, self.uut.replace_tabs_with_spaces, 5) self.assertEqual(self.uut.replace_tabs_with_spaces(""), "") self.assertEqual(self.uut.replace_tabs_with_spaces(" "), " ") self.assertEqual(self.uut.replace_tabs_with_spaces("\t"), " " * self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces("\t\t"), " " * self.uut.DEFAULT_TAB_WIDTH * 2) self.assertEqual(self.uut.replace_tabs_with_spaces(" \t"), " " * self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces(" \t"), " " * self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces("d \t "), "d" + " " * self.uut.DEFAULT_TAB_WIDTH) def test_replace_spaces_with_tabs(self): self.assertRaises(TypeError, self.uut.replace_spaces_with_tabs, 5) self.assertEqual(self.uut.replace_spaces_with_tabs(""), "") self.assertEqual(self.uut.replace_spaces_with_tabs(" "), " ") self.assertEqual(self.uut.replace_spaces_with_tabs(" "), "\t") self.assertEqual(self.uut.replace_spaces_with_tabs(" \t"), "\t") self.assertEqual(self.uut.replace_spaces_with_tabs(" dd "), " dd ") self.assertEqual(self.uut.replace_spaces_with_tabs(" dd d "), " dd d ") # One space shouldnt be replaced self.assertEqual(self.uut.replace_spaces_with_tabs(" dd "), " dd\t") self.assertEqual( self.uut.replace_spaces_with_tabs(" \t a_text another"), "\t a_text\tanother") self.assertEqual(self.uut.replace_spaces_with_tabs("d d"), "d d")
def setUp(self): self.uut = SpacingHelper()
class SpacingHelperTest(unittest.TestCase): def setUp(self): self.uut = SpacingHelper() def test_needed_settings(self): self.assertEqual(list(self.uut.get_optional_settings()), ['tab_width']) self.assertEqual(list(self.uut.get_non_optional_settings()), []) def test_construction(self): section = Section('test section') self.assertRaises(TypeError, SpacingHelper, 'no integer') self.assertRaises(TypeError, self.uut.from_section, 5) self.assertEqual(self.uut.tab_width, self.uut.from_section(section).tab_width) # This is assumed in some tests. If you want to change this value, be # sure to change the tests too self.assertEqual(self.uut.DEFAULT_TAB_WIDTH, 4) self.assertEqual(self.uut.tab_width, self.uut.DEFAULT_TAB_WIDTH) def test_get_indentation(self): self.assertRaises(TypeError, self.uut.get_indentation, 5) self.assertEqual(self.uut.get_indentation('no indentation'), 0) self.assertEqual(self.uut.get_indentation(' indentation'), 1) self.assertEqual(self.uut.get_indentation(' indentation'), 2) self.assertEqual(self.uut.get_indentation('\tindentation'), self.uut.DEFAULT_TAB_WIDTH) # Having a space before the tab shouldn't make any difference self.assertEqual(self.uut.get_indentation(' \tindentation'), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(' \t indentation'), self.uut.DEFAULT_TAB_WIDTH+1) self.assertEqual(self.uut.get_indentation('\t indentation'), self.uut.DEFAULT_TAB_WIDTH+1) # same tests but with indentation only self.assertEqual(self.uut.get_indentation('\t'), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(' \t'), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(' \t '), self.uut.DEFAULT_TAB_WIDTH+1) self.assertEqual(self.uut.get_indentation('\t '), self.uut.DEFAULT_TAB_WIDTH+1) self.assertEqual(self.uut.get_indentation('\t\t'), self.uut.DEFAULT_TAB_WIDTH*2) def test_replace_tabs_with_spaces(self): self.assertRaises(TypeError, self.uut.replace_tabs_with_spaces, 5) self.assertEqual(self.uut.replace_tabs_with_spaces(''), '') self.assertEqual(self.uut.replace_tabs_with_spaces(' '), ' ') self.assertEqual(self.uut.replace_tabs_with_spaces('\t'), ' '*self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces('\t\t'), ' '*self.uut.DEFAULT_TAB_WIDTH*2) self.assertEqual(self.uut.replace_tabs_with_spaces(' \t'), ' '*self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces(' \t'), ' '*self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces('d \t '), 'd' + ' '*self.uut.DEFAULT_TAB_WIDTH) def test_replace_spaces_with_tabs(self): self.assertRaises(TypeError, self.uut.replace_spaces_with_tabs, 5) self.assertEqual(self.uut.replace_spaces_with_tabs(''), '') self.assertEqual(self.uut.replace_spaces_with_tabs(' '), ' ') self.assertEqual(self.uut.replace_spaces_with_tabs(' '), '\t') self.assertEqual(self.uut.replace_spaces_with_tabs(' \t'), '\t') self.assertEqual(self.uut.replace_spaces_with_tabs(' dd '), ' dd ') self.assertEqual(self.uut.replace_spaces_with_tabs(' dd d '), ' dd d ') # One space shouldnt be replaced self.assertEqual(self.uut.replace_spaces_with_tabs(' dd '), ' dd\t') self.assertEqual( self.uut.replace_spaces_with_tabs(' \t a_text another'), '\t a_text\tanother') self.assertEqual(self.uut.replace_spaces_with_tabs('123\t'), '123\t') self.assertEqual(self.uut.replace_spaces_with_tabs('d d'), 'd d')
def run(self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool = False, tab_width: int = SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool = True): ''' Checks the space consistency for each line. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param tab_width: Number of spaces representing one tab. :param enforce_newline_at_EOF: Whether to enforce a newline at the End Of File. ''' spacing_helper = SpacingHelper(tab_width) result_texts = [] for line_number, line in enumerate(file, start=1): replacement = line if enforce_newline_at_EOF: # Since every line contains at the end at least one \n, only # the last line could potentially not have one. So we don't # need to check whether the current line_number is the last # one. if replacement[-1] != "\n": replacement += "\n" result_texts.append("No newline at EOF.") if not allow_trailing_whitespace: pre_replacement = line replacement = replacement.rstrip(" \t\n") + "\n" if replacement != pre_replacement: result_texts.append("Trailing whitespaces.") if use_spaces: pre_replacement = replacement replacement = spacing_helper.replace_tabs_with_spaces( replacement) if replacement != pre_replacement: result_texts.append("Tabs used instead of spaces.") else: pre_replacement = replacement replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != pre_replacement: result_texts.append("Spaces used instead of tabs.") if len(result_texts) > 0: diff = Diff(file) diff.change_line(line_number, line, replacement) inconsistencies = "".join("\n- " + string for string in result_texts) yield Result.from_values( self, "Line contains following spacing inconsistencies:" + inconsistencies, diffs={filename: diff}, file=filename, line=line_number) result_texts = []
def run(self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool = False, tab_width: int = SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool = True): ''' Check and correct spacing for all textual data. This includes usage of tabs vs. spaces, trailing whitespace and (missing) newlines before the end of the file. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param tab_width: Number of spaces representing one tab. :param enforce_newline_at_EOF: Whether to enforce a newline at the End Of File. ''' spacing_helper = SpacingHelper(tab_width) result_texts = [] additional_info_texts = [] for line_number, line in enumerate(file, start=1): replacement = line if enforce_newline_at_EOF: # Since every line contains at the end at least one \n, only # the last line could potentially not have one. So we don't # need to check whether the current line_number is the last # one. if replacement[-1] != "\n": replacement += "\n" result_texts.append("No newline at EOF.") additional_info_texts.append( "A trailing newline character ('\\n') is missing from " "your file. " "<http://stackoverflow.com/a/5813359/3212182> gives " "more information about why you might need one.") if not allow_trailing_whitespace: replacement = replacement.rstrip(" \t\n") + "\n" if replacement != line.rstrip("\n") + "\n": result_texts.append("Trailing whitespaces.") additional_info_texts.append( "Your source code contains trailing whitespaces. Those " "usually have no meaning. Please consider removing " "them.") if use_spaces: pre_replacement = replacement replacement = spacing_helper.replace_tabs_with_spaces( replacement) if replacement != pre_replacement: result_texts.append("Tabs used instead of spaces.") else: pre_replacement = replacement replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != pre_replacement: result_texts.append("Spaces used instead of tabs.") if len(result_texts) > 0: diff = Diff(file) diff.change_line(line_number, line, replacement) inconsistencies = "".join("\n- " + string for string in result_texts) yield Result.from_values( self, "Line contains following spacing inconsistencies:" + inconsistencies, diffs={filename: diff}, file=filename, line=line_number, additional_info="\n\n".join(additional_info_texts)) result_texts = [] additional_info_texts = []
class SpacingHelperTest(unittest.TestCase): def setUp(self): self.uut = SpacingHelper() def test_needed_settings(self): self.assertEqual(list(self.uut.get_optional_settings()), ["tab_width"]) self.assertEqual(list(self.uut.get_non_optional_settings()), []) def test_construction(self): section = Section("test section") self.assertRaises(TypeError, SpacingHelper, "no integer") self.assertRaises(TypeError, self.uut.from_section, 5) self.assertEqual(self.uut.tab_width, self.uut.from_section(section).tab_width) section.append(Setting("tab_width", "invalid")) # Setting won't be converted since it's not possible, SpacingHelper # will then complain with TypeError self.assertRaises(TypeError, self.uut.from_section, section) # This is assumed in some tests. If you want to change this value, be # sure to change the tests too self.assertEqual(self.uut.DEFAULT_TAB_WIDTH, 4) self.assertEqual(self.uut.tab_width, self.uut.DEFAULT_TAB_WIDTH) def test_get_indentation(self): self.assertRaises(TypeError, self.uut.get_indentation, 5) self.assertEqual(self.uut.get_indentation("no indentation"), 0) self.assertEqual(self.uut.get_indentation(" indentation"), 1) self.assertEqual(self.uut.get_indentation(" indentation"), 2) self.assertEqual(self.uut.get_indentation("\tindentation"), self.uut.DEFAULT_TAB_WIDTH) # Having a space before the tab shouldn't make any difference self.assertEqual(self.uut.get_indentation(" \tindentation"), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(" \t indentation"), self.uut.DEFAULT_TAB_WIDTH+1) self.assertEqual(self.uut.get_indentation("\t indentation"), self.uut.DEFAULT_TAB_WIDTH+1) # same tests but with indentation only self.assertEqual(self.uut.get_indentation("\t"), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(" \t"), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(" \t "), self.uut.DEFAULT_TAB_WIDTH+1) self.assertEqual(self.uut.get_indentation("\t "), self.uut.DEFAULT_TAB_WIDTH+1) self.assertEqual(self.uut.get_indentation("\t\t"), self.uut.DEFAULT_TAB_WIDTH*2) def test_replace_tabs_with_spaces(self): self.assertRaises(TypeError, self.uut.replace_tabs_with_spaces, 5) self.assertEqual(self.uut.replace_tabs_with_spaces(""), "") self.assertEqual(self.uut.replace_tabs_with_spaces(" "), " ") self.assertEqual(self.uut.replace_tabs_with_spaces("\t"), " "*self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces("\t\t"), " "*self.uut.DEFAULT_TAB_WIDTH*2) self.assertEqual(self.uut.replace_tabs_with_spaces(" \t"), " "*self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces(" \t"), " "*self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces("d \t "), "d" + " "*self.uut.DEFAULT_TAB_WIDTH) def test_replace_spaces_with_tabs(self): self.assertRaises(TypeError, self.uut.replace_spaces_with_tabs, 5) self.assertEqual(self.uut.replace_spaces_with_tabs(""), "") self.assertEqual(self.uut.replace_spaces_with_tabs(" "), " ") self.assertEqual(self.uut.replace_spaces_with_tabs(" "), "\t") self.assertEqual(self.uut.replace_spaces_with_tabs(" \t"), "\t") self.assertEqual(self.uut.replace_spaces_with_tabs(" dd "), " dd ") self.assertEqual(self.uut.replace_spaces_with_tabs(" dd d "), " dd d ") # One space shouldnt be replaced self.assertEqual(self.uut.replace_spaces_with_tabs(" dd "), " dd\t") self.assertEqual( self.uut.replace_spaces_with_tabs(" \t a_text another"), "\t a_text\tanother") self.assertEqual(self.uut.replace_spaces_with_tabs("d d"), "d d")
def run(self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool = False, indent_size: int = SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool = True, ): ''' Check and correct spacing for all textual data. This includes usage of tabs vs. spaces, trailing whitespace and (missing) newlines before the end of the file. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param indent_size: Number of spaces per indentation level. :param enforce_newline_at_EOF: Whether to enforce a newline at the End Of File. ''' spacing_helper = SpacingHelper(indent_size) result_texts = [] additional_info_texts = [] for line_number, line in enumerate(file, start=1): replacement = line if enforce_newline_at_EOF: # Since every line contains at the end at least one \n, only # the last line could potentially not have one. So we don't # need to check whether the current line_number is the last # one. if replacement[-1] != '\n': replacement += '\n' result_texts.append('No newline at EOF.') additional_info_texts.append( "A trailing newline character ('\\n') is missing from " 'your file. ' '<http://stackoverflow.com/a/5813359/3212182> gives ' 'more information about why you might need one.') if not allow_trailing_whitespace: replacement = replacement.rstrip(' \t\n') + '\n' if replacement != line.rstrip('\n') + '\n': result_texts.append('Trailing whitespaces.') additional_info_texts.append( 'Your source code contains trailing whitespaces. ' 'Those usually have no meaning. Please consider ' 'removing them.') if use_spaces: pre_replacement = replacement replacement = replacement.expandtabs(indent_size) if replacement != pre_replacement: result_texts.append('Tabs used instead of spaces.') else: pre_replacement = replacement replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != pre_replacement: result_texts.append('Spaces used instead of tabs.') if len(result_texts) > 0: diff = Diff(file) diff.change_line(line_number, line, replacement) inconsistencies = ''.join('\n- ' + string for string in result_texts) yield Result.from_values( self, 'Line contains following spacing inconsistencies:' + inconsistencies, diffs={filename: diff}, file=filename, line=line_number, additional_info='\n\n'.join(additional_info_texts)) result_texts = [] additional_info_texts = []
def run(self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool=False, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool=True): ''' Check and correct spacing for all textual data. This includes usage of tabs vs. spaces, trailing whitespace and (missing) newlines before the end of the file. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param tab_width: Number of spaces representing one tab. :param enforce_newline_at_EOF: Whether to enforce a newline at the End Of File. ''' spacing_helper = SpacingHelper(tab_width) result_texts = [] additional_info_texts = [] for line_number, line in enumerate(file, start=1): replacement = line if enforce_newline_at_EOF: # Since every line contains at the end at least one \n, only # the last line could potentially not have one. So we don't # need to check whether the current line_number is the last # one. if replacement[-1] != "\n": replacement += "\n" result_texts.append("No newline at EOF.") additional_info_texts.append( "A trailing newline character ('\\n') is missing from " "your file. " "<http://stackoverflow.com/a/5813359/3212182> gives " "more information about why you might need one.") if not allow_trailing_whitespace: replacement = replacement.rstrip(" \t\n") + "\n" if replacement != line.rstrip("\n") + "\n": result_texts.append("Trailing whitespaces.") additional_info_texts.append( "Your source code contains trailing whitespaces. Those " "usually have no meaning. Please consider removing " "them.") if use_spaces: pre_replacement = replacement replacement = spacing_helper.replace_tabs_with_spaces( replacement) if replacement != pre_replacement: result_texts.append("Tabs used instead of spaces.") else: pre_replacement = replacement replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != pre_replacement: result_texts.append("Spaces used instead of tabs.") if len(result_texts) > 0: diff = Diff(file) diff.change_line(line_number, line, replacement) inconsistencies = "".join("\n- " + string for string in result_texts) yield Result.from_values( self, "Line contains following spacing inconsistencies:" + inconsistencies, diffs={filename: diff}, file=filename, line=line_number, additional_info="\n\n".join(additional_info_texts)) result_texts = [] additional_info_texts = []
class SpacingHelperTest(unittest.TestCase): def setUp(self): self.uut = SpacingHelper() def test_needed_settings(self): self.assertEqual(list(self.uut.get_optional_settings()), ['tab_width']) self.assertEqual(list(self.uut.get_non_optional_settings()), []) def test_construction(self): section = Section('test section') self.assertRaises(TypeError, SpacingHelper, 'no integer') self.assertRaises(TypeError, self.uut.from_section, 5) self.assertEqual(self.uut.tab_width, self.uut.from_section(section).tab_width) # This is assumed in some tests. If you want to change this value, be # sure to change the tests too self.assertEqual(self.uut.DEFAULT_TAB_WIDTH, 4) self.assertEqual(self.uut.tab_width, self.uut.DEFAULT_TAB_WIDTH) def test_get_indentation(self): self.assertRaises(TypeError, self.uut.get_indentation, 5) self.assertEqual(self.uut.get_indentation('no indentation'), 0) self.assertEqual(self.uut.get_indentation(' indentation'), 1) self.assertEqual(self.uut.get_indentation(' indentation'), 2) self.assertEqual(self.uut.get_indentation('\tindentation'), self.uut.DEFAULT_TAB_WIDTH) # Having a space before the tab shouldn't make any difference self.assertEqual(self.uut.get_indentation(' \tindentation'), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(' \t indentation'), self.uut.DEFAULT_TAB_WIDTH + 1) self.assertEqual(self.uut.get_indentation('\t indentation'), self.uut.DEFAULT_TAB_WIDTH + 1) # same tests but with indentation only self.assertEqual(self.uut.get_indentation('\t'), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(' \t'), self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.get_indentation(' \t '), self.uut.DEFAULT_TAB_WIDTH + 1) self.assertEqual(self.uut.get_indentation('\t '), self.uut.DEFAULT_TAB_WIDTH + 1) self.assertEqual(self.uut.get_indentation('\t\t'), self.uut.DEFAULT_TAB_WIDTH * 2) def test_replace_tabs_with_spaces(self): self.assertRaises(TypeError, self.uut.replace_tabs_with_spaces, 5) self.assertEqual(self.uut.replace_tabs_with_spaces(''), '') self.assertEqual(self.uut.replace_tabs_with_spaces(' '), ' ') self.assertEqual(self.uut.replace_tabs_with_spaces('\t'), ' ' * self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces('\t\t'), ' ' * self.uut.DEFAULT_TAB_WIDTH * 2) self.assertEqual(self.uut.replace_tabs_with_spaces(' \t'), ' ' * self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces(' \t'), ' ' * self.uut.DEFAULT_TAB_WIDTH) self.assertEqual(self.uut.replace_tabs_with_spaces('d \t '), 'd' + ' ' * self.uut.DEFAULT_TAB_WIDTH) def test_replace_spaces_with_tabs(self): self.assertRaises(TypeError, self.uut.replace_spaces_with_tabs, 5) self.assertEqual(self.uut.replace_spaces_with_tabs(''), '') self.assertEqual(self.uut.replace_spaces_with_tabs(' '), ' ') self.assertEqual(self.uut.replace_spaces_with_tabs(' '), '\t') self.assertEqual(self.uut.replace_spaces_with_tabs(' \t'), '\t') self.assertEqual(self.uut.replace_spaces_with_tabs(' dd '), ' dd ') self.assertEqual(self.uut.replace_spaces_with_tabs(' dd d '), ' dd d ') # One space shouldnt be replaced self.assertEqual(self.uut.replace_spaces_with_tabs(' dd '), ' dd\t') self.assertEqual( self.uut.replace_spaces_with_tabs(' \t a_text another'), '\t a_text\tanother') self.assertEqual(self.uut.replace_spaces_with_tabs('123\t'), '123\t') self.assertEqual(self.uut.replace_spaces_with_tabs('d d'), 'd d')
def run( self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool = False, indent_size: int = SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool = True, ): ''' Check and correct spacing for all textual data. This includes usage of tabs vs. spaces, trailing whitespace and (missing) newlines before the end of the file. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param indent_size: Number of spaces per indentation level. :param enforce_newline_at_EOF: Whether to enforce a newline at the End Of File. ''' spacing_helper = SpacingHelper(indent_size) result_texts = [] additional_info_texts = [] for line_number, line in enumerate(file, start=1): replacement = line if enforce_newline_at_EOF: # Since every line contains at the end at least one \n, only # the last line could potentially not have one. So we don't # need to check whether the current line_number is the last # one. if replacement[-1] != '\n': replacement += '\n' result_texts.append('No newline at EOF.') additional_info_texts.append( "A trailing newline character ('\\n') is missing from " 'your file. ' '<http://stackoverflow.com/a/5813359/3212182> gives ' 'more information about why you might need one.') if not allow_trailing_whitespace: replacement = replacement.rstrip(' \t\n') + '\n' if replacement != line.rstrip('\n') + '\n': result_texts.append('Trailing whitespaces.') additional_info_texts.append( 'Your source code contains trailing whitespaces. ' 'Those usually have no meaning. Please consider ' 'removing them.') if use_spaces: pre_replacement = replacement replacement = replacement.expandtabs(indent_size) if replacement != pre_replacement: result_texts.append('Tabs used instead of spaces.') else: pre_replacement = replacement replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != pre_replacement: result_texts.append('Spaces used instead of tabs.') if len(result_texts) > 0: diff = Diff(file) diff.change_line(line_number, line, replacement) inconsistencies = ''.join('\n- ' + string for string in result_texts) yield Result.from_values( self, 'Line contains following spacing inconsistencies:' + inconsistencies, diffs={filename: diff}, file=filename, line=line_number, additional_info='\n\n'.join(additional_info_texts)) result_texts = [] additional_info_texts = []
def run(self, filename, file, use_spaces: bool, allow_trailing_whitespace: bool=False, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool=True): ''' Checks the space consistency for each line. :param use_spaces: True if spaces are to be used instead of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. :param tab_width: Number of spaces representing one tab. :param enforce_newline_at_EOF: Whether to enforce a newline at the End Of File. ''' spacing_helper = SpacingHelper(tab_width) result_texts = [] for line_number, line in enumerate(file, start=1): replacement = line if enforce_newline_at_EOF: # Since every line contains at the end at least one \n, only # the last line could potentially not have one. So we don't # need to check whether the current line_number is the last # one. if replacement[-1] != "\n": replacement += "\n" result_texts.append(_("No newline at EOF.")) if not allow_trailing_whitespace: pre_replacement = line replacement = replacement.rstrip(" \t\n") + "\n" if replacement != pre_replacement: result_texts.append(_("Trailing whitespaces.")) if use_spaces: pre_replacement = replacement replacement = spacing_helper.replace_tabs_with_spaces( replacement) if replacement != pre_replacement: result_texts.append(_("Tabs used instead of spaces.")) else: pre_replacement = replacement replacement = spacing_helper.replace_spaces_with_tabs( replacement) if replacement != pre_replacement: result_texts.append(_("Spaces used instead of tabs.")) if len(result_texts) > 0: diff = Diff() diff.change_line(line_number, line, replacement) inconsistencies = "".join("\n- " + string for string in result_texts) yield Result.from_values( self, _("Line contains following spacing inconsistencies:") + inconsistencies, diffs={filename: diff}, file=filename, line=line_number) result_texts = []