Skip to content

Commit db26deb

Browse files
authored
Merge pull request #1292 from abebus/speedups/module_imports_on_top_of_file
reduce "module_imports_on_top_of_file" execution time by ~20%
2 parents c50ba15 + edab883 commit db26deb

File tree

1 file changed

+32
-25
lines changed

1 file changed

+32
-25
lines changed

pycodestyle.py

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,22 @@ def imports_on_separate_lines(logical_line):
11601160
yield found, "E401 multiple imports on one line"
11611161

11621162

1163+
_STRING_PREFIXES = frozenset(('u', 'U', 'b', 'B', 'r', 'R'))
1164+
1165+
1166+
def _is_string_literal(line):
1167+
if line:
1168+
first_char = line[0]
1169+
if first_char in _STRING_PREFIXES:
1170+
first_char = line[1]
1171+
return first_char == '"' or first_char == "'"
1172+
return False
1173+
1174+
1175+
_ALLOWED_KEYWORDS_IN_IMPORTS = (
1176+
'try', 'except', 'else', 'finally', 'with', 'if', 'elif')
1177+
1178+
11631179
@register_check
11641180
def module_imports_on_top_of_file(
11651181
logical_line, indent_level, checker_state, noqa):
@@ -1178,41 +1194,32 @@ def module_imports_on_top_of_file(
11781194
11791195
Okay: if x:\n import os
11801196
""" # noqa
1181-
def is_string_literal(line):
1182-
if line[0] in 'uUbB':
1183-
line = line[1:]
1184-
if line and line[0] in 'rR':
1185-
line = line[1:]
1186-
return line and (line[0] == '"' or line[0] == "'")
1187-
1188-
allowed_keywords = (
1189-
'try', 'except', 'else', 'finally', 'with', 'if', 'elif')
11901197

11911198
if indent_level: # Allow imports in conditional statement/function
11921199
return
11931200
if not logical_line: # Allow empty lines or comments
11941201
return
11951202
if noqa:
11961203
return
1197-
line = logical_line
1198-
if line.startswith('import ') or line.startswith('from '):
1204+
if logical_line.startswith(('import ', 'from ')):
11991205
if checker_state.get('seen_non_imports', False):
12001206
yield 0, "E402 module level import not at top of file"
1201-
elif re.match(DUNDER_REGEX, line):
1202-
return
1203-
elif any(line.startswith(kw) for kw in allowed_keywords):
1204-
# Allow certain keywords intermixed with imports in order to
1205-
# support conditional or filtered importing
1206-
return
1207-
elif is_string_literal(line):
1208-
# The first literal is a docstring, allow it. Otherwise, report
1209-
# error.
1210-
if checker_state.get('seen_docstring', False):
1211-
checker_state['seen_non_imports'] = True
1207+
elif not checker_state.get('seen_non_imports', False):
1208+
if DUNDER_REGEX.match(logical_line):
1209+
return
1210+
elif logical_line.startswith(_ALLOWED_KEYWORDS_IN_IMPORTS):
1211+
# Allow certain keywords intermixed with imports in order to
1212+
# support conditional or filtered importing
1213+
return
1214+
elif _is_string_literal(logical_line):
1215+
# The first literal is a docstring, allow it. Otherwise,
1216+
# report error.
1217+
if checker_state.get('seen_docstring', False):
1218+
checker_state['seen_non_imports'] = True
1219+
else:
1220+
checker_state['seen_docstring'] = True
12121221
else:
1213-
checker_state['seen_docstring'] = True
1214-
else:
1215-
checker_state['seen_non_imports'] = True
1222+
checker_state['seen_non_imports'] = True
12161223

12171224

12181225
@register_check

0 commit comments

Comments
 (0)