Skip to content

Commit 3088ffb

Browse files
committed
Fix PyPy
1 parent 02f55ed commit 3088ffb

File tree

5 files changed

+114
-24
lines changed

5 files changed

+114
-24
lines changed

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ python:
88
- 3.5
99
- nightly
1010
- pypy
11+
- pypy3
1112
install:
1213
- pip install flake8==2.1.0 pep8==1.5.6
1314
- python setup.py install
@@ -16,7 +17,4 @@ install:
1617
script:
1718
- python setup.py test -q
1819
- if [ "$TRAVIS_PYTHON_VERSION" != "nightly" ]; then flake8 pyflakes setup.py; fi
19-
matrix:
20-
allow_failures:
21-
- python: pypy
2220
sudo: false

pyflakes/api.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,18 @@ def check(codeString, filename, reporter=None):
4141

4242
(lineno, offset, text) = value.lineno, value.offset, value.text
4343

44+
if checker.PYPY:
45+
if text is None:
46+
lines = codeString.splitlines()
47+
if len(lines) >= lineno:
48+
text = lines[lineno - 1]
49+
if sys.version_info >= (3, ) and isinstance(text, bytes):
50+
try:
51+
text = text.decode('ascii')
52+
except UnicodeDecodeError:
53+
text = None
54+
offset -= 1
55+
4456
# If there's an encoding problem with the file, the text is None.
4557
if text is None:
4658
# Avoid using msg, since for the only known case, it contains a

pyflakes/checker.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
PY2 = sys.version_info < (3, 0)
1212
PY32 = sys.version_info < (3, 3) # Python 2.5 to 3.2
1313
PY33 = sys.version_info < (3, 4) # Python 2.5 to 3.3
14+
try:
15+
sys.pypy_version_info
16+
PYPY = True
17+
except AttributeError:
18+
PYPY = False
19+
1420
builtin_vars = dir(__import__('__builtin__' if PY2 else 'builtins'))
1521

1622
try:
@@ -594,8 +600,13 @@ def getDocstring(self, node):
594600
node = node.value
595601
if not isinstance(node, ast.Str):
596602
return (None, None)
597-
# Computed incorrectly if the docstring has backslash
598-
doctest_lineno = node.lineno - node.s.count('\n') - 1
603+
604+
if PYPY:
605+
doctest_lineno = node.lineno - 1
606+
else:
607+
# Computed incorrectly if the docstring has backslash
608+
doctest_lineno = node.lineno - node.s.count('\n') - 1
609+
599610
return (node.s, doctest_lineno)
600611

601612
def handleNode(self, node, parent):
@@ -642,6 +653,8 @@ def handleDoctests(self, node):
642653
tree = compile(example.source, "<doctest>", "exec", ast.PyCF_ONLY_AST)
643654
except SyntaxError:
644655
e = sys.exc_info()[1]
656+
if PYPY:
657+
e.offset += 1
645658
position = (node_lineno + example.lineno + e.lineno,
646659
example.indent + 4 + (e.offset or 0))
647660
self.report(messages.DoctestSyntaxError, node, position)

pyflakes/test/test_api.py

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@
2323
from io import StringIO
2424
unichr = chr
2525

26+
try:
27+
sys.pypy_version_info
28+
PYPY = True
29+
except AttributeError:
30+
PYPY = False
31+
32+
ERROR_HAS_COL_NUM = ERROR_HAS_LAST_LINE = sys.version_info >= (3, 2) or PYPY
33+
2634

2735
def withStderrTo(stderr, f, *args, **kwargs):
2836
"""
@@ -312,46 +320,65 @@ def evaluate(source):
312320
evaluate(source)
313321
except SyntaxError:
314322
e = sys.exc_info()[1]
315-
self.assertTrue(e.text.count('\n') > 1)
323+
if not PYPY:
324+
self.assertTrue(e.text.count('\n') > 1)
316325
else:
317326
self.fail()
318327

319328
sourcePath = self.makeTempFile(source)
329+
330+
if PYPY:
331+
message = 'EOF while scanning triple-quoted string literal'
332+
else:
333+
message = 'invalid syntax'
334+
320335
self.assertHasErrors(
321336
sourcePath,
322337
["""\
323-
%s:8:11: invalid syntax
338+
%s:8:11: %s
324339
'''quux'''
325340
^
326-
""" % (sourcePath,)])
341+
""" % (sourcePath, message)])
327342

328343
def test_eofSyntaxError(self):
329344
"""
330345
The error reported for source files which end prematurely causing a
331346
syntax error reflects the cause for the syntax error.
332347
"""
333348
sourcePath = self.makeTempFile("def foo(")
334-
self.assertHasErrors(
335-
sourcePath,
336-
["""\
349+
if PYPY:
350+
result = """\
351+
%s:1:7: parenthesis is never closed
352+
def foo(
353+
^
354+
""" % (sourcePath,)
355+
else:
356+
result = """\
337357
%s:1:9: unexpected EOF while parsing
338358
def foo(
339359
^
340-
""" % (sourcePath,)])
360+
""" % (sourcePath,)
361+
362+
self.assertHasErrors(
363+
sourcePath,
364+
[result])
341365

342366
def test_eofSyntaxErrorWithTab(self):
343367
"""
344368
The error reported for source files which end prematurely causing a
345369
syntax error reflects the cause for the syntax error.
346370
"""
347371
sourcePath = self.makeTempFile("if True:\n\tfoo =")
372+
column = 5 if PYPY else 7
373+
last_line = '\t ^' if PYPY else '\t ^'
374+
348375
self.assertHasErrors(
349376
sourcePath,
350377
["""\
351-
%s:2:7: invalid syntax
378+
%s:2:%s: invalid syntax
352379
\tfoo =
353-
\t ^
354-
""" % (sourcePath,)])
380+
%s
381+
""" % (sourcePath, column, last_line)])
355382

356383
def test_nonDefaultFollowsDefaultSyntaxError(self):
357384
"""
@@ -364,8 +391,8 @@ def foo(bar=baz, bax):
364391
pass
365392
"""
366393
sourcePath = self.makeTempFile(source)
367-
last_line = ' ^\n' if sys.version_info >= (3, 2) else ''
368-
column = '8:' if sys.version_info >= (3, 2) else ''
394+
last_line = ' ^\n' if ERROR_HAS_LAST_LINE else ''
395+
column = '8:' if ERROR_HAS_COL_NUM else ''
369396
self.assertHasErrors(
370397
sourcePath,
371398
["""\
@@ -383,8 +410,8 @@ def test_nonKeywordAfterKeywordSyntaxError(self):
383410
foo(bar=baz, bax)
384411
"""
385412
sourcePath = self.makeTempFile(source)
386-
last_line = ' ^\n' if sys.version_info >= (3, 2) else ''
387-
column = '13:' if sys.version_info >= (3, 2) else ''
413+
last_line = ' ^\n' if ERROR_HAS_LAST_LINE else ''
414+
column = '13:' if ERROR_HAS_COL_NUM or PYPY else ''
388415

389416
if sys.version_info >= (3, 5):
390417
message = 'positional argument follows keyword argument'
@@ -407,8 +434,15 @@ def test_invalidEscape(self):
407434
sourcePath = self.makeTempFile(r"foo = '\xyz'")
408435
if ver < (3,):
409436
decoding_error = "%s: problem decoding source\n" % (sourcePath,)
437+
elif PYPY:
438+
# pypy3 only
439+
decoding_error = """\
440+
%s:1:6: %s: ('unicodeescape', b'\\\\xyz', 0, 2, 'truncated \\\\xXX escape')
441+
foo = '\\xyz'
442+
^
443+
""" % (sourcePath, 'UnicodeDecodeError')
410444
else:
411-
last_line = ' ^\n' if ver >= (3, 2) else ''
445+
last_line = ' ^\n' if ERROR_HAS_LAST_LINE else ''
412446
# Column has been "fixed" since 3.2.4 and 3.3.1
413447
col = 1 if ver >= (3, 3, 1) or ((3, 2, 4) <= ver < (3, 3)) else 2
414448
decoding_error = """\
@@ -474,8 +508,21 @@ def test_misencodedFileUTF8(self):
474508
x = "%s"
475509
""" % SNOWMAN).encode('utf-8')
476510
sourcePath = self.makeTempFile(source)
511+
512+
if PYPY and sys.version_info < (3, ):
513+
message = ('\'ascii\' codec can\'t decode byte 0xe2 '
514+
'in position 21: ordinal not in range(128)')
515+
result = """\
516+
%s:0:0: %s
517+
x = "\xe2\x98\x83"
518+
^\n""" % (sourcePath, message)
519+
520+
else:
521+
message = 'problem decoding source'
522+
result = "%s: problem decoding source\n" % (sourcePath,)
523+
477524
self.assertHasErrors(
478-
sourcePath, ["%s: problem decoding source\n" % (sourcePath,)])
525+
sourcePath, [result])
479526

480527
def test_misencodedFileUTF16(self):
481528
"""

pyflakes/test/test_doctests.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
import textwrap
23

34
from pyflakes import messages as m
@@ -11,6 +12,12 @@
1112
from pyflakes.test.test_undefined_names import Test as TestUndefinedNames
1213
from pyflakes.test.harness import TestCase, skip
1314

15+
try:
16+
sys.pypy_version_info
17+
PYPY = True
18+
except AttributeError:
19+
PYPY = False
20+
1421

1522
class _DoctestMixin(object):
1623

@@ -273,12 +280,22 @@ def doctest_stuff():
273280
exc = exceptions[0]
274281
self.assertEqual(exc.lineno, 4)
275282
self.assertEqual(exc.col, 26)
283+
284+
# PyPy error column offset is 0,
285+
# for the second and third line of the doctest
286+
# i.e. at the beginning of the line
276287
exc = exceptions[1]
277288
self.assertEqual(exc.lineno, 5)
278-
self.assertEqual(exc.col, 16)
289+
if PYPY:
290+
self.assertEqual(exc.col, 13)
291+
else:
292+
self.assertEqual(exc.col, 16)
279293
exc = exceptions[2]
280294
self.assertEqual(exc.lineno, 6)
281-
self.assertEqual(exc.col, 18)
295+
if PYPY:
296+
self.assertEqual(exc.col, 13)
297+
else:
298+
self.assertEqual(exc.col, 18)
282299

283300
def test_indentationErrorInDoctest(self):
284301
exc = self.flakes('''
@@ -289,7 +306,10 @@ def doctest_stuff():
289306
"""
290307
''', m.DoctestSyntaxError).messages[0]
291308
self.assertEqual(exc.lineno, 5)
292-
self.assertEqual(exc.col, 16)
309+
if PYPY:
310+
self.assertEqual(exc.col, 13)
311+
else:
312+
self.assertEqual(exc.col, 16)
293313

294314
def test_offsetWithMultiLineArgs(self):
295315
(exc1, exc2) = self.flakes(

0 commit comments

Comments
 (0)