Skip to content

Commit 4ccdc55

Browse files
committed
Merge pull request #525 from mtmiller/issue341
Detect single letter variable names enumerated in PEP-0008
2 parents 60859d6 + fdf3e6a commit 4ccdc55

3 files changed

Lines changed: 62 additions & 1 deletion

File tree

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Changes:
1616
* Added check E275 for whitespace on `from ... import ...` lines; #489 / #491
1717
* Added W503 to the list of codes ignored by default ignore list; #498
1818
* Removed use of project level `.pep8` configuration file; #364
19+
* Added check E741 for using variables named 'l', 'O', or 'I'; #341
1920

2021
Bugs:
2122

docs/intro.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,12 @@ This is the current list of error and warning codes:
359359
+------------+----------------------------------------------------------------------+
360360
| E731 | do not assign a lambda expression, use a def |
361361
+------------+----------------------------------------------------------------------+
362+
| E741 | do not use variables named 'l', 'O', or 'I' |
363+
+------------+----------------------------------------------------------------------+
364+
| E742 | do not define classes named 'l', 'O', or 'I' |
365+
+------------+----------------------------------------------------------------------+
366+
| E743 | do not define functions named 'l', 'O', or 'I' |
367+
+------------+----------------------------------------------------------------------+
362368
+------------+----------------------------------------------------------------------+
363369
| **E9** | *Runtime* |
364370
+------------+----------------------------------------------------------------------+

pycodestyle.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,60 @@ def comparison_type(logical_line, noqa):
11551155
yield match.start(), "E721 do not compare types, use 'isinstance()'"
11561156

11571157

1158+
def ambiguous_identifier(logical_line, tokens):
1159+
r"""Never use the characters 'l', 'O', or 'I' as variable names.
1160+
1161+
In some fonts, these characters are indistinguishable from the numerals
1162+
one and zero. When tempted to use 'l', use 'L' instead.
1163+
1164+
Okay: L = 0
1165+
Okay: o = 123
1166+
Okay: i = 42
1167+
E741: l = 0
1168+
E741: O = 123
1169+
E741: I = 42
1170+
1171+
Variables can be bound in several other contexts, including class and
1172+
function definitions, 'global' and 'nonlocal' statements, exception
1173+
handlers, and 'with' statements.
1174+
1175+
Okay: except AttributeError as o:
1176+
Okay: with lock as L:
1177+
E741: except AttributeError as O:
1178+
E741: with lock as l:
1179+
E741: global I
1180+
E741: nonlocal l
1181+
E742: class I(object):
1182+
E743: def l(x):
1183+
"""
1184+
idents_to_avoid = ('l', 'O', 'I')
1185+
prev_type, prev_text, prev_start, prev_end, __ = tokens[0]
1186+
for token_type, text, start, end, line in tokens[1:]:
1187+
ident = pos = None
1188+
# identifiers on the lhs of an assignment operator
1189+
if token_type == tokenize.OP and '=' in text:
1190+
if prev_text in idents_to_avoid:
1191+
ident = prev_text
1192+
pos = prev_start
1193+
# identifiers bound to a value with 'as', 'global', or 'nonlocal'
1194+
if prev_text in ('as', 'global', 'nonlocal'):
1195+
if text in idents_to_avoid:
1196+
ident = text
1197+
pos = start
1198+
if prev_text == 'class':
1199+
if text in idents_to_avoid:
1200+
yield start, "E742 ambiguous class definition '%s'" % text
1201+
if prev_text == 'def':
1202+
if text in idents_to_avoid:
1203+
yield start, "E743 ambiguous function definition '%s'" % text
1204+
if ident:
1205+
yield pos, "E741 ambiguous variable name '%s'" % ident
1206+
prev_type = token_type
1207+
prev_text = text
1208+
prev_start = start
1209+
prev_end = end
1210+
1211+
11581212
def python_3000_has_key(logical_line, noqa):
11591213
r"""The {}.has_key() method is removed in Python 3: use the 'in' operator.
11601214
@@ -1224,7 +1278,7 @@ def readlines(filename):
12241278
with open(filename, 'rb') as f:
12251279
(coding, lines) = tokenize.detect_encoding(f.readline)
12261280
f = TextIOWrapper(f, coding, line_buffering=True)
1227-
return [l.decode(coding) for l in lines] + f.readlines()
1281+
return [line.decode(coding) for line in lines] + f.readlines()
12281282
except (LookupError, SyntaxError, UnicodeError):
12291283
# Fall back if file encoding is improperly declared
12301284
with open(filename, encoding='latin-1') as f:

0 commit comments

Comments
 (0)