Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

E403: add report for module-level dunder names that are misplaced. #1237

Closed
wants to merge 7 commits into from
2 changes: 2 additions & 0 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ This is the current list of error and warning codes:
+------------+----------------------------------------------------------------------+
| E402 | module level import not at top of file |
+------------+----------------------------------------------------------------------+
| E403 | module level dunder name found after non-future imports |
+------------+----------------------------------------------------------------------+
+------------+----------------------------------------------------------------------+
| **E5** | *Line length* |
+------------+----------------------------------------------------------------------+
Expand Down
22 changes: 20 additions & 2 deletions pycodestyle.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
700 statements
900 syntax error
"""

__version__ = '2.11.1'

import bisect
import configparser
import inspect
Expand All @@ -68,8 +71,6 @@
): # pragma: no cover (<py310)
tokenize._compile = lru_cache(tokenize._compile) # type: ignore

__version__ = '2.11.1'

DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504'
try:
Expand Down Expand Up @@ -378,6 +379,18 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number,
(indent_level and blank_lines == method_lines + 1)
):
yield 0, "E303 too many blank lines (%d)" % blank_lines
elif DUNDER_REGEX.match(previous_logical):
if DUNDER_REGEX.match(logical_line):
return # Allow groupings of dunder names
if not blank_lines:
yield 0, "E301 expected 1 blank line, found 0"
if blank_lines > 1:
yield 0, "E303 too many blank lines (%d)" % blank_lines
elif DUNDER_REGEX.match(logical_line):
if not blank_lines:
yield 0, "E301 expected 1 blank line, found 0"
if blank_lines > 1:
yield 0, "E303 too many blank lines (%d)" % blank_lines
elif STARTSWITH_TOP_LEVEL_REGEX.match(logical_line):
# allow a group of one-liners
if (
Expand Down Expand Up @@ -1161,7 +1174,12 @@ def is_string_literal(line):
if line.startswith('import ') or line.startswith('from '):
if checker_state.get('seen_non_imports', False):
yield 0, "E402 module level import not at top of file"
if line.split()[1] == '__future__':
return # Allow before dunders - https://bugs.python.org/issue27187
checker_state['seen_imports'] = True
elif re.match(DUNDER_REGEX, line):
if checker_state.get('seen_imports', False):
yield 0, "E403 module-level dunder name after non-future imports"
return
elif any(line.startswith(kw) for kw in allowed_keywords):
# Allow certain keywords intermixed with imports in order to
Expand Down
21 changes: 21 additions & 0 deletions testing/data/E30.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,24 @@ def f():
@hi
def g():
pass
#: E303:4:1 E303:7:1
from __future__ import annotations


__all__ = ('xyz',)


import foo
#: E301:2:1 E301:3:1
from __future__ import annotations
__all__ = ('xyz',)
import foo
#: E303:8:1
__all__ = ('together',)






import foo
5 changes: 5 additions & 0 deletions testing/data/E30not.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,8 @@ def f(
a,
):
pass
#: Okay
from __future__ import annotations

__all__ = ('not_lost',)
__author__ = 'you'
2 changes: 1 addition & 1 deletion testing/data/python38.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def f3(
#: E225:1:18
if False or (x :=1):
pass
#: Okay
#: E403:3:1
import typing as t

__all__: t.List[str] = []
Expand Down
Loading