Skip to content

Commit c7448b4

Browse files
authored
Merge pull request #676 from jdufresne/invalid-escape
Add W605 warning for invalid escape sequences in string literals
2 parents 769ea41 + 13d2bd2 commit c7448b4

File tree

5 files changed

+80
-4
lines changed

5 files changed

+80
-4
lines changed

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
UNRELEASED
5+
----------
6+
7+
New checks:
8+
9+
* Add W605 warning for invalid escape sequences in string literals
10+
411
2.3.1 (2017-01-31)
512
------------------
613

docs/intro.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,8 @@ This is the current list of error and warning codes:
413413
+------------+----------------------------------------------------------------------+
414414
| W604 | backticks are deprecated, use 'repr()' |
415415
+------------+----------------------------------------------------------------------+
416+
| W605 | invalid escape sequence '\x' |
417+
+------------+----------------------------------------------------------------------+
416418

417419

418420
**(*)** In the default configuration, the checks **E121**, **E123**, **E126**,

pycodestyle.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,57 @@ def python_3000_backticks(logical_line):
13881388
yield pos, "W604 backticks are deprecated, use 'repr()'"
13891389

13901390

1391+
@register_check
1392+
def python_3000_invalid_escape_sequence(logical_line, tokens):
1393+
r"""Invalid escape sequences are deprecated in Python 3.6.
1394+
1395+
Okay: regex = r'\.png$'
1396+
W605: regex = '\.png$'
1397+
"""
1398+
# https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
1399+
valid = [
1400+
'\n',
1401+
'\\',
1402+
'\'',
1403+
'"',
1404+
'a',
1405+
'b',
1406+
'f',
1407+
'n',
1408+
'r',
1409+
't',
1410+
'v',
1411+
'0', '1', '2', '3', '4', '5', '6', '7',
1412+
'x',
1413+
1414+
# Escape sequences only recognized in string literals
1415+
'N',
1416+
'u',
1417+
'U',
1418+
]
1419+
1420+
for token_type, text, start, end, line in tokens:
1421+
if token_type == tokenize.STRING:
1422+
quote = text[-3:] if text[-3:] in ('"""', "'''") else text[-1]
1423+
# Extract string modifiers (e.g. u or r)
1424+
quote_pos = text.index(quote)
1425+
prefix = text[:quote_pos].lower()
1426+
start = quote_pos + len(quote)
1427+
string = text[start:-len(quote)]
1428+
1429+
if 'r' not in prefix:
1430+
pos = string.find('\\')
1431+
while pos >= 0:
1432+
pos += 1
1433+
if string[pos] not in valid:
1434+
yield (
1435+
pos,
1436+
"W605 invalid escape sequence '\\%s'" %
1437+
string[pos],
1438+
)
1439+
pos = string.find('\\', pos + 1)
1440+
1441+
13911442
##############################################################################
13921443
# Helper functions
13931444
##############################################################################

testsuite/E12not.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,10 @@ def qualify_by_address(self, cr, uid, ids, context=None,
358358
""" This gets called by the web server """
359359

360360

361-
_ipv4_re = re.compile('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
362-
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
363-
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
364-
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')
361+
_ipv4_re = re.compile(r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
362+
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
363+
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
364+
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')
365365

366366

367367
fct("""

testsuite/W60.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,19 @@
1313
x = 0
1414
#: W604
1515
val = `1 + 2`
16+
#: W605
17+
regex = '\.png$'
18+
#: W605
19+
regex = '''
20+
\.png$
21+
'''
22+
#: Okay
23+
regex = r'\.png$'
24+
regex = '\\.png$'
25+
regex = r'''
26+
\.png$
27+
'''
28+
regex = r'''
29+
\\.png$
30+
'''
31+
s = '\\'

0 commit comments

Comments
 (0)