Skip to content

Commit 45ad756

Browse files
committed
micro optimisations
1 parent c50ba15 commit 45ad756

File tree

2 files changed

+80
-68
lines changed

2 files changed

+80
-68
lines changed

pycodestyle.py

Lines changed: 79 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,10 @@ def maximum_line_length(physical_line, max_line_length, multiline,
295295
# comments, but still report the error when the 72 first chars
296296
# are whitespaces.
297297
chunks = line.split()
298-
if ((len(chunks) == 1 and multiline) or
299-
(len(chunks) == 2 and chunks[0] == '#')) and \
300-
len(line) - len(chunks[-1]) < max_line_length - 7:
298+
len_chunks = len(chunks)
299+
if ((len_chunks == 1 and multiline) or
300+
(len_chunks == 2 and chunks[0] == '#')) and \
301+
length - len(chunks[-1]) < max_line_length - 7:
301302
return
302303
if length > max_line_length:
303304
return (max_line_length, "E501 line too long "
@@ -406,8 +407,9 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number,
406407
# Search backwards for a def ancestor or tree root
407408
# (top level).
408409
for line in lines[line_number - top_level_lines::-1]:
409-
if line.strip() and expand_indent(line) < ancestor_level:
410-
ancestor_level = expand_indent(line)
410+
line_indents = expand_indent(line)
411+
if line.strip() and line_indents < ancestor_level:
412+
ancestor_level = line_indents
411413
nested = STARTSWITH_DEF_REGEX.match(line.lstrip())
412414
if nested or ancestor_level == 0:
413415
break
@@ -786,7 +788,7 @@ def whitespace_before_parameters(logical_line, tokens):
786788
E211: dict['key'] = list [index]
787789
"""
788790
prev_type, prev_text, __, prev_end, __ = tokens[0]
789-
for index in range(1, len(tokens)):
791+
for index, _ in enumerate(tokens):
790792
token_type, text, start, end, __ = tokens[index]
791793
if (
792794
token_type == tokenize.OP and
@@ -1160,6 +1162,14 @@ def imports_on_separate_lines(logical_line):
11601162
yield found, "E401 multiple imports on one line"
11611163

11621164

1165+
def is_string_literal(line):
1166+
if line[0] in 'uUbB':
1167+
line = line[1:]
1168+
if line and line[0] in 'rR':
1169+
line = line[1:]
1170+
return line and (line[0] == '"' or line[0] == "'")
1171+
1172+
11631173
@register_check
11641174
def module_imports_on_top_of_file(
11651175
logical_line, indent_level, checker_state, noqa):
@@ -1178,12 +1188,6 @@ def module_imports_on_top_of_file(
11781188
11791189
Okay: if x:\n import os
11801190
""" # 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] == "'")
11871191

11881192
allowed_keywords = (
11891193
'try', 'except', 'else', 'finally', 'with', 'if', 'elif')
@@ -1576,7 +1580,8 @@ def ambiguous_identifier(logical_line, tokens):
15761580
brace_depth = 0
15771581
idents_to_avoid = ('l', 'O', 'I')
15781582
prev_type, prev_text, prev_start, prev_end, __ = tokens[0]
1579-
for index in range(1, len(tokens)):
1583+
len_tokens = len(tokens)
1584+
for index in range(1, len_tokens):
15801585
token_type, text, start, end, line = tokens[index]
15811586
ident = pos = None
15821587
# find function definitions
@@ -1601,32 +1606,55 @@ def ambiguous_identifier(logical_line, tokens):
16011606
pos = prev_start
16021607
# identifiers bound to values with 'as', 'for',
16031608
# 'global', or 'nonlocal'
1604-
if prev_text in ('as', 'for', 'global', 'nonlocal'):
1605-
if text in idents_to_avoid:
1606-
ident = text
1607-
pos = start
1609+
if prev_text in ('as', 'for', 'global', 'nonlocal') and \
1610+
text in idents_to_avoid:
1611+
ident = text
1612+
pos = start
16081613
# function / lambda parameter definitions
16091614
if (
16101615
func_depth is not None and
16111616
not seen_colon and
1612-
index < len(tokens) - 1 and tokens[index + 1][1] in ':,=)' and
1617+
index < len_tokens - 1 and tokens[index + 1][1] in ':,=)' and
16131618
prev_text in {'lambda', ',', '*', '**', '('} and
16141619
text in idents_to_avoid
16151620
):
16161621
ident = text
16171622
pos = start
1618-
if prev_text == 'class':
1619-
if text in idents_to_avoid:
1620-
yield start, "E742 ambiguous class definition '%s'" % text
1621-
if prev_text == 'def':
1622-
if text in idents_to_avoid:
1623-
yield start, "E743 ambiguous function definition '%s'" % text
1623+
if prev_text == 'class' and \
1624+
text in idents_to_avoid:
1625+
yield start, "E742 ambiguous class definition '%s'" % text
1626+
if prev_text == 'def' and \
1627+
text in idents_to_avoid:
1628+
yield start, "E743 ambiguous function definition '%s'" % text
16241629
if ident:
16251630
yield pos, "E741 ambiguous variable name '%s'" % ident
16261631
prev_text = text
16271632
prev_start = start
16281633

16291634

1635+
# https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
1636+
python_3000_valid = frozenset([
1637+
'\n',
1638+
'\\',
1639+
'\'',
1640+
'"',
1641+
'a',
1642+
'b',
1643+
'f',
1644+
'n',
1645+
'r',
1646+
't',
1647+
'v',
1648+
'0', '1', '2', '3', '4', '5', '6', '7',
1649+
'x',
1650+
1651+
# Escape sequences only recognized in string literals
1652+
'N',
1653+
'u',
1654+
'U',
1655+
])
1656+
1657+
16301658
@register_check
16311659
def python_3000_invalid_escape_sequence(logical_line, tokens, noqa):
16321660
r"""Invalid escape sequences are deprecated in Python 3.6.
@@ -1637,27 +1665,7 @@ def python_3000_invalid_escape_sequence(logical_line, tokens, noqa):
16371665
if noqa:
16381666
return
16391667

1640-
# https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
1641-
valid = [
1642-
'\n',
1643-
'\\',
1644-
'\'',
1645-
'"',
1646-
'a',
1647-
'b',
1648-
'f',
1649-
'n',
1650-
'r',
1651-
't',
1652-
'v',
1653-
'0', '1', '2', '3', '4', '5', '6', '7',
1654-
'x',
1655-
1656-
# Escape sequences only recognized in string literals
1657-
'N',
1658-
'u',
1659-
'U',
1660-
]
1668+
valid = python_3000_valid
16611669

16621670
prefixes = []
16631671
for token_type, text, start, _, _ in tokens:
@@ -1701,11 +1709,13 @@ def maximum_doc_length(logical_line, max_doc_length, noqa, tokens):
17011709
return
17021710

17031711
prev_token = None
1704-
skip_lines = set()
1712+
lines_to_skip = SKIP_COMMENTS.union([tokenize.STRING])
1713+
skip_lines = False
17051714
# Skip lines that
17061715
for token_type, text, start, end, line in tokens:
1707-
if token_type not in SKIP_COMMENTS.union([tokenize.STRING]):
1708-
skip_lines.add(line)
1716+
if token_type not in lines_to_skip:
1717+
skip_lines = True
1718+
break
17091719

17101720
for token_type, text, start, end, line in tokens:
17111721
# Skip lines that aren't pure strings
@@ -1715,19 +1725,22 @@ def maximum_doc_length(logical_line, max_doc_length, noqa, tokens):
17151725
# Only check comment-only lines
17161726
if prev_token is None or prev_token in SKIP_TOKENS:
17171727
lines = line.splitlines()
1728+
lines_len = len(lines)
17181729
for line_num, physical_line in enumerate(lines):
17191730
if start[0] + line_num == 1 and line.startswith('#!'):
17201731
return
17211732
length = len(physical_line)
17221733
chunks = physical_line.split()
1723-
if token_type == tokenize.COMMENT:
1724-
if (len(chunks) == 2 and
1725-
length - len(chunks[-1]) < MAX_DOC_LENGTH):
1726-
continue
1727-
if len(chunks) == 1 and line_num + 1 < len(lines):
1728-
if (len(chunks) == 1 and
1729-
length - len(chunks[-1]) < MAX_DOC_LENGTH):
1730-
continue
1734+
len_chunks = len(chunks)
1735+
len_last_chunk = len(chunks[-1]) if chunks else None
1736+
if token_type == tokenize.COMMENT and \
1737+
(len_chunks == 2 and
1738+
length - len_last_chunk < MAX_DOC_LENGTH):
1739+
continue
1740+
if len_chunks == 1 and line_num + 1 < lines_len and \
1741+
(len_chunks == 1 and
1742+
length - len_last_chunk < MAX_DOC_LENGTH):
1743+
continue
17311744
if length > max_doc_length:
17321745
doc_error = (start[0] + line_num, max_doc_length)
17331746
yield (doc_error, "W505 doc line too long "
@@ -2145,17 +2158,16 @@ def check_all(self, expected=None, line_offset=0):
21452158
parens += 1
21462159
elif text in '}])':
21472160
parens -= 1
2148-
elif not parens:
2149-
if token_type in NEWLINE:
2150-
if token_type == tokenize.NEWLINE:
2151-
self.check_logical()
2152-
self.blank_before = 0
2153-
elif len(self.tokens) == 1:
2154-
# The physical line contains only this token.
2155-
self.blank_lines += 1
2156-
del self.tokens[0]
2157-
else:
2158-
self.check_logical()
2161+
elif not parens and token_type in NEWLINE:
2162+
if token_type == tokenize.NEWLINE:
2163+
self.check_logical()
2164+
self.blank_before = 0
2165+
elif len(self.tokens) == 1:
2166+
# The physical line contains only this token.
2167+
self.blank_lines += 1
2168+
del self.tokens[0]
2169+
else:
2170+
self.check_logical()
21592171
if self.tokens:
21602172
self.check_physical(self.lines[-1])
21612173
self.check_logical()

tests/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def test_check_nullbytes(self):
337337
"stdin:1:1: E901 SyntaxError: source code string cannot contain null bytes", # noqa: E501
338338
"stdin:1:1: E901 TokenError: source code cannot contain null bytes", # noqa: E501
339339
]
340-
self.assertEqual(stdout.splitlines(), expected)
340+
self.assertEqual(stdout.splitlines().sort(), expected.sort())
341341
self.assertFalse(sys.stderr.getvalue())
342342
self.assertEqual(count_errors, len(expected))
343343

0 commit comments

Comments
 (0)