Skip to content

Fix Issue 400: Require two blank lines after toplevel def, class #536

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should actually be up in the unreleased next version changes section.


Bugs:

Expand Down
2 changes: 2 additions & 0 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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* |
+------------+----------------------------------------------------------------------+
Expand Down
13 changes: 12 additions & 1 deletion pycodestyle.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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()


Expand Down Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is a bit poor. We're also now adding a new attribute to a Checker that a plugin can request. Given that we're exposing this to plugins, can we consider a better name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've thought about it, I'm not sure what alternative variable name to use. Open to suggestions!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I'm weird, but I think previous_toplevel_logical_line is better. (Frankly I never liked previous_logical as a name.)

self.blank_lines = 0
self.tokens = []

Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions testsuite/E12not.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -400,6 +401,7 @@ def unicode2html(s):
.replace('"', '&#34;')
.replace('\n', '<br>\n'))


#
parser.add_option('--count', action='store_true',
help="print total number of errors and warnings "
Expand Down Expand Up @@ -616,6 +618,7 @@ def other_example():
for key, val in node.items()
))]


foo([
'bug'
])
Expand Down
1 change: 1 addition & 0 deletions testsuite/E22.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
29 changes: 29 additions & 0 deletions testsuite/E30.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
#:
1 change: 1 addition & 0 deletions testsuite/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions testsuite/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,6 @@ def suite():
def _main():
return unittest.TextTestRunner(verbosity=2).run(suite())


if __name__ == '__main__':
sys.exit(not _main())