4
from pyflakes import messages as m
5
from pyflakes.checker import (
10
from pyflakes.test.test_other import Test as TestOther
11
from pyflakes.test.test_imports import Test as TestImports
12
from pyflakes.test.test_undefined_names import Test as TestUndefinedNames
13
from pyflakes.test.harness import TestCase, skip
18
except AttributeError:
22
class _DoctestMixin(object):
26
def doctestify(self, input):
28
for line in textwrap.dedent(input).splitlines():
29
if line.strip() == '':
31
elif (line.startswith(' ') or
32
line.startswith('except:') or
33
line.startswith('except ') or
34
line.startswith('finally:') or
35
line.startswith('else:') or
36
line.startswith('elif ')):
37
line = "... %s" % line
39
line = ">>> %s" % line
41
doctestificator = textwrap.dedent('''\
42
def doctest_something():
47
return doctestificator % "\n ".join(lines)
49
def flakes(self, input, *args, **kw):
50
return super(_DoctestMixin, self).flakes(self.doctestify(input), *args, **kw)
57
def test_scope_class(self):
58
"""Check that a doctest is given a DoctestScope."""
59
checker = self.flakes("""
64
>>> d = doctest_stuff()
70
scopes = checker.deadScopes
72
scope for scope in scopes if scope.__class__ is ModuleScope]
74
scope for scope in scopes if scope.__class__ is DoctestScope]
76
scope for scope in scopes if scope.__class__ is FunctionScope]
78
self.assertEqual(len(module_scopes), 1)
79
self.assertEqual(len(doctest_scopes), 1)
81
module_scope = module_scopes[0]
82
doctest_scope = doctest_scopes[0]
84
self.assertIsInstance(doctest_scope, DoctestScope)
85
self.assertIsInstance(doctest_scope, ModuleScope)
86
self.assertNotIsInstance(doctest_scope, FunctionScope)
87
self.assertNotIsInstance(module_scope, DoctestScope)
89
self.assertIn('m', module_scope)
90
self.assertIn('doctest_stuff', module_scope)
92
self.assertIn('d', doctest_scope)
94
self.assertEqual(len(function_scopes), 1)
95
self.assertIn('f', function_scopes[0])
97
def test_nested_doctest_ignored(self):
98
"""Check that nested doctests are ignored."""
99
checker = self.flakes("""
104
>>> def function_in_doctest():
106
... >>> ignored_undefined_name
111
>>> function_in_doctest()
117
scopes = checker.deadScopes
119
scope for scope in scopes if scope.__class__ is ModuleScope]
121
scope for scope in scopes if scope.__class__ is DoctestScope]
123
scope for scope in scopes if scope.__class__ is FunctionScope]
125
self.assertEqual(len(module_scopes), 1)
126
self.assertEqual(len(doctest_scopes), 1)
128
module_scope = module_scopes[0]
129
doctest_scope = doctest_scopes[0]
131
self.assertIn('m', module_scope)
132
self.assertIn('doctest_stuff', module_scope)
133
self.assertIn('function_in_doctest', doctest_scope)
135
self.assertEqual(len(function_scopes), 2)
137
self.assertIn('f', function_scopes[0])
138
self.assertIn('df', function_scopes[1])
140
def test_global_module_scope_pollution(self):
141
"""Check that global in doctest does not pollute module scope."""
142
checker = self.flakes("""
145
>>> def function_in_doctest():
151
>>> function_in_doctest()
158
scopes = checker.deadScopes
160
scope for scope in scopes if scope.__class__ is ModuleScope]
162
scope for scope in scopes if scope.__class__ is DoctestScope]
164
scope for scope in scopes if scope.__class__ is FunctionScope]
166
self.assertEqual(len(module_scopes), 1)
167
self.assertEqual(len(doctest_scopes), 1)
169
module_scope = module_scopes[0]
170
doctest_scope = doctest_scopes[0]
172
self.assertIn('doctest_stuff', module_scope)
173
self.assertIn('function_in_doctest', doctest_scope)
175
self.assertEqual(len(function_scopes), 2)
177
self.assertIn('f', function_scopes[0])
178
self.assertIn('df', function_scopes[1])
179
self.assertIn('m', function_scopes[1])
181
self.assertNotIn('m', module_scope)
183
def test_global_undefined(self):
191
""", m.UndefinedName)
193
def test_nested_class(self):
194
"""Doctest within nested class are processed."""
201
def doctest_stuff(self):
206
""", m.UndefinedName, m.UndefinedName)
208
def test_ignore_nested_function(self):
209
"""Doctest module does not process doctest in nested functions."""
210
# 'syntax error' would cause a SyntaxError if the doctest was processed.
211
# However doctest does not find doctest in nested functions
212
# (https://bugs.python.org/issue1650090). If nested functions were
213
# processed, this use of m should cause UndefinedName, and the
214
# name inner_function should probably exist in the doctest scope.
217
def inner_function():
229
def test_inaccessible_scope_class(self):
230
"""Doctest may not access class scope."""
233
def doctest_stuff(self):
239
""", m.UndefinedName)
241
def test_importBeforeDoctest(self):
252
def test_importBeforeAndInDoctest(self):
263
''', m.RedefinedWhileUnused)
265
def test_importInDoctestAndAfter(self):
277
def test_offsetInDoctests(self):
278
exc = self.flakes('''
285
''', m.UndefinedName).messages[0]
286
self.assertEqual(exc.lineno, 5)
287
self.assertEqual(exc.col, 12)
289
def test_offsetInLambdasInDoctests(self):
290
exc = self.flakes('''
294
>>> lambda: x # line 5
297
''', m.UndefinedName).messages[0]
298
self.assertEqual(exc.lineno, 5)
299
self.assertEqual(exc.col, 20)
301
def test_offsetAfterDoctests(self):
302
exc = self.flakes('''
311
''', m.UndefinedName).messages[0]
312
self.assertEqual(exc.lineno, 8)
313
self.assertEqual(exc.col, 0)
315
def test_syntaxErrorInDoctest(self):
316
exceptions = self.flakes(
322
>>> except Exception:
325
m.DoctestSyntaxError,
326
m.DoctestSyntaxError,
327
m.DoctestSyntaxError).messages
329
self.assertEqual(exc.lineno, 4)
330
self.assertEqual(exc.col, 26)
332
# PyPy error column offset is 0,
333
# for the second and third line of the doctest
334
# i.e. at the beginning of the line
336
self.assertEqual(exc.lineno, 5)
338
self.assertEqual(exc.col, 13)
340
self.assertEqual(exc.col, 16)
342
self.assertEqual(exc.lineno, 6)
344
self.assertEqual(exc.col, 13)
346
self.assertEqual(exc.col, 18)
348
def test_indentationErrorInDoctest(self):
349
exc = self.flakes('''
355
''', m.DoctestSyntaxError).messages[0]
356
self.assertEqual(exc.lineno, 5)
358
self.assertEqual(exc.col, 13)
360
self.assertEqual(exc.col, 16)
362
def test_offsetWithMultiLineArgs(self):
363
(exc1, exc2) = self.flakes(
365
def doctest_stuff(arg1,
373
m.DoctestSyntaxError,
374
m.UndefinedName).messages
375
self.assertEqual(exc1.lineno, 6)
376
self.assertEqual(exc1.col, 19)
377
self.assertEqual(exc2.lineno, 7)
378
self.assertEqual(exc2.col, 12)
380
def test_doctestCanReferToFunction(self):
388
def test_doctestCanReferToClass(self):
400
def test_noOffsetSyntaxErrorInDoctest(self):
401
exceptions = self.flakes(
403
def buildurl(base, *args, **kwargs):
405
>>> buildurl('/blah.php', ('a', '&'), ('b', '=')
406
'/blah.php?a=%26&b=%3D'
407
>>> buildurl('/blah.php', a='&', 'b'='=')
408
'/blah.php?b=%3D&a=%26'
412
m.DoctestSyntaxError,
413
m.DoctestSyntaxError).messages
415
self.assertEqual(exc.lineno, 4)
417
self.assertEqual(exc.lineno, 6)
419
def test_singleUnderscoreInDoctest(self):
433
class TestOther(_DoctestMixin, TestOther):
434
"""Run TestOther with each test wrapped in a doctest."""
437
class TestImports(_DoctestMixin, TestImports):
438
"""Run TestImports with each test wrapped in a doctest."""
441
class TestUndefinedNames(_DoctestMixin, TestUndefinedNames):
442
"""Run TestUndefinedNames with each test wrapped in a doctest."""