From 0c33a9d9102d821c3fd5e63eebd00940bb6d61ff Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Tue, 19 May 2015 20:40:33 -0400 Subject: [PATCH] Fix issue #400: Require two blank lines after toplevel def, class --- CHANGES.txt | 1 + docs/intro.rst | 2 ++ pycodestyle.py | 13 ++++++++++++- testsuite/E12not.py | 3 +++ testsuite/E22.py | 1 + testsuite/E30.py | 29 +++++++++++++++++++++++++++++ testsuite/support.py | 1 + testsuite/test_all.py | 1 + 8 files changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index aa080851..5351f2c4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -23,6 +23,7 @@ Changes: * Added check E275 for whitespace on `from ... import ...` lines; #489 / #491 * Added W503 to the list of codes ignored by default ignore list; #498 * Removed use of project level `.pep8` configuration file; #364 +* Added check E305 for two blank lines after toplevel method and toplevel class; #400 Bugs: diff --git a/docs/intro.rst b/docs/intro.rst index 982b7866..0f5132bf 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -322,6 +322,8 @@ This is the current list of error and warning codes: +------------+----------------------------------------------------------------------+ | E304 | blank lines found after function decorator | +------------+----------------------------------------------------------------------+ +| E305 | expected 2 blank lines after end of function or class | ++------------+----------------------------------------------------------------------+ +------------+----------------------------------------------------------------------+ | **E4** | *Import* | +------------+----------------------------------------------------------------------+ diff --git a/pycodestyle.py b/pycodestyle.py index b32f16ea..fbaae4da 100755 --- a/pycodestyle.py +++ b/pycodestyle.py @@ -237,7 +237,8 @@ def maximum_line_length(physical_line, max_line_length, multiline, noqa): def blank_lines(logical_line, blank_lines, indent_level, line_number, - blank_before, previous_logical, previous_indent_level): + blank_before, previous_logical, previous_logical_toplevel, + previous_indent_level): r"""Separate top-level function and class definitions with two blank lines. Method definitions inside a class are separated by a single blank line. @@ -256,6 +257,7 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number, E303: def a():\n pass\n\n\n\ndef b(n):\n pass E303: def a():\n\n\n\n pass E304: @decorator\n\ndef a():\n pass + E305: def a():\n pass\na() """ if line_number < 3 and not previous_logical: return # Don't expect blank lines before the first line @@ -271,6 +273,10 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number, yield 0, "E301 expected 1 blank line, found 0" elif blank_before != 2: yield 0, "E302 expected 2 blank lines, found %d" % blank_before + elif (logical_line and not indent_level and blank_before != 2 and + previous_logical_toplevel.startswith(('def', 'class'))): + yield 0, "E305 expected 2 blank lines after " \ + "class or function definition, found %d" % blank_before def extraneous_whitespace(logical_line): @@ -1450,6 +1456,8 @@ def init_checks_registry(): mod = inspect.getmodule(register_check) for (name, function) in inspect.getmembers(mod, inspect.isfunction): register_check(function) + + init_checks_registry() @@ -1608,6 +1616,8 @@ def check_logical(self): if self.logical_line: self.previous_indent_level = self.indent_level self.previous_logical = self.logical_line + if not self.indent_level: + self.previous_logical_toplevel = self.logical_line self.blank_lines = 0 self.tokens = [] @@ -1678,6 +1688,7 @@ def check_all(self, expected=None, line_offset=0): self.indent_char = None self.indent_level = self.previous_indent_level = 0 self.previous_logical = '' + self.previous_logical_toplevel = '' self.tokens = [] self.blank_lines = self.blank_before = 0 parens = 0 diff --git a/testsuite/E12not.py b/testsuite/E12not.py index e76ef134..18c6a646 100644 --- a/testsuite/E12not.py +++ b/testsuite/E12not.py @@ -139,6 +139,7 @@ def long_function_name( var_four): print(var_one) + if ((row < 0 or self.moduleCount <= row or col < 0 or self.moduleCount <= col)): raise Exception("%s,%s - %s" % (row, col, self.moduleCount)) @@ -400,6 +401,7 @@ def unicode2html(s): .replace('"', '"') .replace('\n', '
\n')) + # parser.add_option('--count', action='store_true', help="print total number of errors and warnings " @@ -616,6 +618,7 @@ def other_example(): for key, val in node.items() ))] + foo([ 'bug' ]) diff --git a/testsuite/E22.py b/testsuite/E22.py index 9d8efda5..ee9dc74a 100644 --- a/testsuite/E22.py +++ b/testsuite/E22.py @@ -150,6 +150,7 @@ def halves(n): def squares(n): return (i**2 for i in range(n)) + ENG_PREFIXES = { -6: "\u03bc", # Greek letter mu -3: "m", diff --git a/testsuite/E30.py b/testsuite/E30.py index d2d7bf35..1aa11379 100644 --- a/testsuite/E30.py +++ b/testsuite/E30.py @@ -88,3 +88,32 @@ def function(): It gives error E303: too many blank lines (3) """ #: + +#: E305:7:1 +def a(): + print + + # comment + + # another comment +a() +#: E305:8:1 +def a(): + print + + # comment + + # another comment + +try: + a() +except: + pass +#: E305:5:1 +def a(): + print + +# Two spaces before comments, too. +if a(): + a() +#: diff --git a/testsuite/support.py b/testsuite/support.py index 003f181b..cf9abc53 100644 --- a/testsuite/support.py +++ b/testsuite/support.py @@ -196,5 +196,6 @@ def run_tests(style): init_tests(style) return style.check_files() + # nose should not collect these functions init_tests.__test__ = run_tests.__test__ = False diff --git a/testsuite/test_all.py b/testsuite/test_all.py index bd18943f..08f9ea91 100644 --- a/testsuite/test_all.py +++ b/testsuite/test_all.py @@ -62,5 +62,6 @@ def suite(): def _main(): return unittest.TextTestRunner(verbosity=2).run(suite()) + if __name__ == '__main__': sys.exit(not _main())