Merge lp:~florent.x/pyflakes/1097061-unittest2 into lp:~divmod-dev/pyflakes/trunk

Proposed by Florent
Status: Merged
Merged at revision: 49
Proposed branch: lp:~florent.x/pyflakes/1097061-unittest2
Merge into: lp:~divmod-dev/pyflakes/trunk
Diff against target: 616 lines (+119/-165)
6 files modified
.travis.yml (+3/-2)
pyflakes/test/harness.py (+3/-3)
pyflakes/test/test_imports.py (+6/-7)
pyflakes/test/test_other.py (+5/-20)
pyflakes/test/test_script.py (+100/-131)
pyflakes/test/test_undefined_names.py (+2/-2)
To merge this branch: bzr merge lp:~florent.x/pyflakes/1097061-unittest2
Reviewer Review Type Date Requested Status
Florent (community) self-review Approve
Divmod-dev Pending
Jean-Paul Calderone Pending
Review via email: mp+142224@code.launchpad.net

Description of the change

Enhancement for continuous integration and coverage of Python version 2.5 (and 3.x in the near future)

To post a comment you must log in.
Revision history for this message
Jean-Paul Calderone (exarkun) wrote :

I'd prefer not to see Pyflakes gain a setuptools dependency (even an optional one). setuptools causes far more problems than it solves. Regardless, as a part of this branch, the addition seems out of place - Pyflakes' setup.py did not declare a dependency on Twisted previously (in other words, it's an unrelated "enhancement").

Revision history for this message
Florent (florent.x) wrote :

To be fair, the testsuite was dependent on Twisted previously, even if it was not declared in setup.py.

Here, the optional import gives a benefit for commands like:

 $ python setup.py test

This allows to run the tests simply, and it takes care of installing the 'test_requires' dependency without other action (without any assumption on the test framework: nose, py.test, twisted.trial, unittest, etc...).
This particular use case is not supported by the distutils library.

In addition, the optional dependency is not on setuptools exclusively. It works perfectly with distribute as well.
I just tried without distribute/setuptools, and I see that there's UserWarnings in the console.
I could change setup.py in order to add 'test_requires'/'test_suite' keywords only if the feature is available.

For the record, there are some users which use the advanced features of distribute/setuptools and already tried to have it supported: https://github.com/kevinw/pyflakes/pull/19

Revision history for this message
Florent (florent.x) wrote :

> Here, the optional import gives a benefit for commands like:
>
> $ python setup.py test
>

Another verb which is widely used but not supported by distutils:

  $ python setup.py develop

Revision history for this message
Jean-Paul Calderone (exarkun) wrote :

> To be fair, the testsuite was dependent on Twisted previously, even if it was not declared in setup.py.

Yes. That was part of my point. It depended on Twisted and did not declare it in setup.py. You can switch to unittest2 and still not declare it it setup.py. The change to introduce a setuptools dependency can be considered *completely* separately from the change to use unittest2.

Revision history for this message
Florent (florent.x) wrote :

Sorry, but I fail to understand the reasoning to reject the setuptools optional dependency.
It makes testing easier and more standard for the developer.
Since the 'tests_require' contains information about the tests requirements, anyone can run the tests without digging in the source code to know which libraries are required.
And when the distribute/setuptools package is not installed, it imports from distutils and it behaves the same as before.

If the request is to split the merge proposal into 2 patches ... why not.
For me, they are complementary changes to improve testing, so it makes sense to propose them together.

Revision history for this message
Jean-Paul Calderone (exarkun) wrote :

> It makes testing easier and more standard for the developer.

It doesn't do either of these.

> Since the 'tests_require' contains information about the tests requirements, anyone can run the tests without digging in the source code to know which libraries are required.

This can be addressed just as easily with an INSTALL or README file.

> And when the distribute/setuptools package is not installed, it imports from distutils and it behaves the same as before.

So there are now twice as many possible install outcomes, which makes debugging installation problems (at least) twice as hard.

> If the request is to split the merge proposal into 2 patches ... why not.

Yes, that's what I was requesting (so that I can only reject the setuptools change while not rejecting the unittest2 change).

> For me, they are complementary changes to improve testing, so it makes sense to propose them together.

Many, many, many, many changes are complementary. That doesn't mean they should be made simultaneously. Changesets should focus on one change, not many complementary changes. Basically, the smallest useful change is what you should try to make. That way issues with *unrelated* changes don't hold up useful improvements, reviews are easier, the history is easier to navigate, tickets can have simple descriptions, and problems that require changes to be reverted don't also revert working functionality.

Revision history for this message
Florent (florent.x) wrote :

The branch was replaced according to your request.

Revision history for this message
Glyph Lefkowitz (glyph) wrote :

On Jan 8, 2013, at 8:20 AM, Jean-Paul Calderone <email address hidden> wrote:

>> If the request is to split the merge proposal into 2 patches ... why not.
>
> Yes, that's what I was requesting (so that I can only reject the setuptools change while not rejecting the unittest2 change).
>
>> For me, they are complementary changes to improve testing, so it makes sense to propose them together.
>
> Many, many, many, many changes are complementary. That doesn't mean they should be made simultaneously. Changesets should focus on one change, not many complementary changes. Basically, the smallest useful change is what you should try to make. That way issues with *unrelated* changes don't hold up useful improvements, reviews are easier, the history is easier to navigate, tickets can have simple descriptions, and problems that require changes to be reverted don't also revert working functionality.

My feelings about setuptools are somewhat more ambivalent, but this point is more important. The fact that this discussion about setuptools is happening is now holding up an unrelated change. If the changes were split up, the less controversial parts (which are by far the larger part of these changes) could be discussed on their own merits and landed much more quickly.

Revision history for this message
Florent (florent.x) wrote :

This branch contains only the replacement of Twisted with unittest2 and is ready for review.

Revision history for this message
Florent (florent.x) wrote :

LGTM ;)

review: Approve (self-review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.travis.yml'
2--- .travis.yml 2013-01-07 17:24:54 +0000
3+++ .travis.yml 2013-01-08 22:58:19 +0000
4@@ -1,13 +1,14 @@
5 language: python
6 python:
7+ - 2.5
8 - 2.6
9 - 2.7
10 - pypy
11 install:
12 - python setup.py install
13- - pip install Twisted
14+ - pip install unittest2
15 script:
16- - trial pyflakes/test
17+ - python -m unittest2 discover
18 matrix:
19 allow_failures:
20 - python: pypy
21
22=== modified file 'pyflakes/test/harness.py'
23--- pyflakes/test/harness.py 2010-04-13 14:53:04 +0000
24+++ pyflakes/test/harness.py 2013-01-08 22:58:19 +0000
25@@ -2,12 +2,12 @@
26 import textwrap
27 import _ast
28
29-from twisted.trial import unittest
30+import unittest2
31
32 from pyflakes import checker
33
34
35-class Test(unittest.TestCase):
36+class Test(unittest2.TestCase):
37
38 def flakes(self, input, *expectedOutputs, **kw):
39 ast = compile(textwrap.dedent(input), "<test>", "exec",
40@@ -17,7 +17,7 @@
41 expectedOutputs = list(expectedOutputs)
42 outputs.sort()
43 expectedOutputs.sort()
44- self.assert_(outputs == expectedOutputs, '''\
45+ self.assertEqual(outputs, expectedOutputs, '''\
46 for input:
47 %s
48 expected outputs:
49
50=== modified file 'pyflakes/test/test_imports.py'
51--- pyflakes/test/test_imports.py 2011-10-31 15:19:35 +0000
52+++ pyflakes/test/test_imports.py 2013-01-08 22:58:19 +0000
53@@ -1,5 +1,6 @@
54
55 from sys import version_info
56+from unittest2 import skip, skipIf
57
58 from pyflakes import messages as m
59 from pyflakes.test import harness
60@@ -446,6 +447,7 @@
61 self.flakes('import fu; [fu, bar] = fu')
62 self.flakes('import fu; fu += fu')
63
64+ @skip("todo")
65 def test_tryingMultipleImports(self):
66 self.flakes('''
67 try:
68@@ -453,7 +455,6 @@
69 except ImportError:
70 import bar as fu
71 ''')
72- test_tryingMultipleImports.todo = ''
73
74 def test_nonGlobalDoesNotRedefine(self):
75 self.flakes('''
76@@ -479,6 +480,7 @@
77 fu
78 ''', m.RedefinedWhileUnused)
79
80+ @skip("todo")
81 def test_importingForImportError(self):
82 self.flakes('''
83 try:
84@@ -486,8 +488,8 @@
85 except ImportError:
86 pass
87 ''')
88- test_importingForImportError.todo = ''
89
90+ @skip("todo: requires evaluating attribute access")
91 def test_importedInClass(self):
92 '''Imports in class scope can be used through self'''
93 self.flakes('''
94@@ -496,7 +498,6 @@
95 def __init__(self):
96 self.i
97 ''')
98- test_importedInClass.todo = 'requires evaluating attribute access'
99
100 def test_futureImport(self):
101 '''__future__ is special'''
102@@ -639,10 +640,8 @@
103 """
104 Tests for checking of syntax which is valid in PYthon 2.6 and newer.
105 """
106- if version_info < (2, 6):
107- skip = "Python 2.6 required for class decorator tests."
108-
109-
110+
111+ @skipIf(version_info < (2, 6), "Python >= 2.6 only")
112 def test_usedAsClassDecorator(self):
113 """
114 Using an imported name as a class decorator results in no warnings,
115
116=== modified file 'pyflakes/test/test_other.py'
117--- pyflakes/test/test_other.py 2011-11-17 16:21:58 +0000
118+++ pyflakes/test/test_other.py 2013-01-08 22:58:19 +0000
119@@ -6,6 +6,7 @@
120 """
121
122 from sys import version_info
123+from unittest2 import skip, skipIf
124
125 from pyflakes import messages as m
126 from pyflakes.test import harness
127@@ -16,6 +17,7 @@
128 def test_duplicateArgs(self):
129 self.flakes('def fu(bar, bar): pass', m.DuplicateArgument)
130
131+ @skip("todo: this requires finding all assignments in the function body first")
132 def test_localReferencedBeforeAssignment(self):
133 self.flakes('''
134 a = 1
135@@ -23,7 +25,6 @@
136 a; a=1
137 f()
138 ''', m.UndefinedName)
139- test_localReferencedBeforeAssignment.todo = 'this requires finding all assignments in the function body first'
140
141 def test_redefinedFunction(self):
142 """
143@@ -148,6 +149,7 @@
144 ''', m.RedefinedWhileUnused)
145
146
147+ @skip("todo: Too hard to make this warn but other cases stay silent")
148 def test_doubleAssignment(self):
149 """
150 If a variable is re-assigned to without being used, no warning is
151@@ -158,8 +160,6 @@
152 x = 10
153 x = 20
154 ''', m.RedefinedWhileUnused)
155- test_doubleAssignment.todo = (
156- "Too hard to make this warn but other cases stay silent")
157
158
159 def test_doubleAssignmentConditionally(self):
160@@ -406,14 +406,6 @@
161 ''')
162
163
164-
165-class Python25Test(harness.Test):
166- """
167- Tests for checking of syntax only available in Python 2.5 and newer.
168- """
169- if version_info < (2, 5):
170- skip = "Python 2.5 required for if-else and with tests"
171-
172 def test_ifexp(self):
173 """
174 Test C{foo if bar else baz} statements.
175@@ -627,15 +619,7 @@
176 pass
177 ''', m.UndefinedName)
178
179-
180-
181-class Python27Test(harness.Test):
182- """
183- Tests for checking of syntax only available in Python 2.7 and newer.
184- """
185- if version_info < (2, 7):
186- skip = "Python 2.7 required for dict/set comprehension tests"
187-
188+ @skipIf(version_info < (2, 7), "Python >= 2.7 only")
189 def test_dictComprehension(self):
190 """
191 Dict comprehensions are properly handled.
192@@ -644,6 +628,7 @@
193 a = {1: x for x in range(10)}
194 ''')
195
196+ @skipIf(version_info < (2, 7), "Python >= 2.7 only")
197 def test_setComprehensionAndLiteral(self):
198 """
199 Set comprehensions are properly handled.
200
201=== modified file 'pyflakes/test/test_script.py'
202--- pyflakes/test/test_script.py 2012-10-23 11:52:32 +0000
203+++ pyflakes/test/test_script.py 2013-01-08 22:58:19 +0000
204@@ -4,15 +4,12 @@
205
206 import os
207 import sys
208+import shutil
209+import subprocess
210+import tempfile
211 from StringIO import StringIO
212
213-from twisted.internet import protocol
214-from twisted.internet.utils import (
215- _callProtocolWithDeferred,
216- getProcessOutputAndValue,
217- )
218-from twisted.python.filepath import FilePath
219-from twisted.trial.unittest import TestCase
220+from unittest2 import TestCase
221
222 from pyflakes.messages import UnusedImport
223 from pyflakes.reporter import Reporter
224@@ -20,7 +17,7 @@
225 checkPath,
226 checkRecursive,
227 iterSourceCode,
228- )
229+)
230
231
232 def withStderrTo(stderr, f, *args, **kwargs):
233@@ -34,7 +31,6 @@
234 sys.stderr = outer
235
236
237-
238 class LoggingReporter(object):
239 """
240 Implementation of Reporter that just appends any errors to a list.
241@@ -67,13 +63,25 @@
242 Tests for L{iterSourceCode}.
243 """
244
245+ def setUp(self):
246+ self.tempdir = tempfile.mkdtemp()
247+
248+ def tearDown(self):
249+ shutil.rmtree(self.tempdir)
250+
251+ def makeEmptyFile(self, *parts):
252+ assert parts
253+ fpath = os.path.join(self.tempdir, *parts)
254+ fd = open(fpath, 'a')
255+ fd.close()
256+ return fpath
257+
258+
259 def test_emptyDirectory(self):
260 """
261 There are no Python files in an empty directory.
262 """
263- tempdir = FilePath(self.mktemp())
264- tempdir.createDirectory()
265- self.assertEqual(list(iterSourceCode([tempdir.path])), [])
266+ self.assertEqual(list(iterSourceCode([self.tempdir])), [])
267
268
269 def test_singleFile(self):
270@@ -81,22 +89,16 @@
271 If the directory contains one Python file, C{iterSourceCode} will find
272 it.
273 """
274- tempdir = FilePath(self.mktemp())
275- tempdir.createDirectory()
276- tempdir.child('foo.py').touch()
277- self.assertEqual(
278- list(iterSourceCode([tempdir.path])),
279- [tempdir.child('foo.py').path])
280+ childpath = self.makeEmptyFile('foo.py')
281+ self.assertEqual(list(iterSourceCode([self.tempdir])), [childpath])
282
283
284 def test_onlyPythonSource(self):
285 """
286 Files that are not Python source files are not included.
287 """
288- tempdir = FilePath(self.mktemp())
289- tempdir.createDirectory()
290- tempdir.child('foo.pyc').touch()
291- self.assertEqual(list(iterSourceCode([tempdir.path])), [])
292+ self.makeEmptyFile('foo.pyc')
293+ self.assertEqual(list(iterSourceCode([self.tempdir])), [])
294
295
296 def test_recurses(self):
297@@ -104,18 +106,14 @@
298 If the Python files are hidden deep down in child directories, we will
299 find them.
300 """
301- tempdir = FilePath(self.mktemp())
302- tempdir.createDirectory()
303- tempdir.child('foo').createDirectory()
304- tempdir.child('foo').child('a.py').touch()
305- tempdir.child('bar').createDirectory()
306- tempdir.child('bar').child('b.py').touch()
307- tempdir.child('c.py').touch()
308+ os.mkdir(os.path.join(self.tempdir, 'foo'))
309+ apath = self.makeEmptyFile('foo', 'a.py')
310+ os.mkdir(os.path.join(self.tempdir, 'bar'))
311+ bpath = self.makeEmptyFile('bar', 'b.py')
312+ cpath = self.makeEmptyFile('c.py')
313 self.assertEqual(
314- sorted(iterSourceCode([tempdir.path])),
315- sorted([tempdir.child('foo').child('a.py').path,
316- tempdir.child('bar').child('b.py').path,
317- tempdir.child('c.py').path]))
318+ sorted(iterSourceCode([self.tempdir])),
319+ sorted([apath, bpath, cpath]))
320
321
322 def test_multipleDirectories(self):
323@@ -123,18 +121,15 @@
324 L{iterSourceCode} can be given multiple directories. It will recurse
325 into each of them.
326 """
327- tempdir = FilePath(self.mktemp())
328- tempdir.createDirectory()
329- foo = tempdir.child('foo')
330- foo.createDirectory()
331- foo.child('a.py').touch()
332- bar = tempdir.child('bar')
333- bar.createDirectory()
334- bar.child('b.py').touch()
335+ foopath = os.path.join(self.tempdir, 'foo')
336+ barpath = os.path.join(self.tempdir, 'bar')
337+ os.mkdir(foopath)
338+ apath = self.makeEmptyFile('foo', 'a.py')
339+ os.mkdir(barpath)
340+ bpath = self.makeEmptyFile('bar', 'b.py')
341 self.assertEqual(
342- sorted(iterSourceCode([foo.path, bar.path])),
343- sorted([foo.child('a.py').path,
344- bar.child('b.py').path]))
345+ sorted(iterSourceCode([foopath, barpath])),
346+ sorted([apath, bpath]))
347
348
349 def test_explicitFiles(self):
350@@ -142,10 +137,9 @@
351 If one of the paths given to L{iterSourceCode} is not a directory but
352 a file, it will include that in its output.
353 """
354- tempfile = FilePath(self.mktemp())
355- tempfile.touch()
356- self.assertEqual(list(iterSourceCode([tempfile.path])),
357- [tempfile.path])
358+ epath = self.makeEmptyFile('e.py')
359+ self.assertEqual(list(iterSourceCode([epath])),
360+ [epath])
361
362
363
364@@ -239,9 +233,11 @@
365 """
366 Make a temporary file containing C{content} and return a path to it.
367 """
368- path = FilePath(self.mktemp())
369- path.setContent(content)
370- return path.path
371+ _, fpath = tempfile.mkstemp()
372+ fd = open(fpath, 'wb')
373+ fd.write(content)
374+ fd.close()
375+ return fpath
376
377
378 def assertHasErrors(self, path, errorList):
379@@ -314,8 +310,12 @@
380 # isn't, something this test was unprepared for has happened.
381 def evaluate(source):
382 exec source
383- exc = self.assertRaises(SyntaxError, evaluate, source)
384- self.assertTrue(exc.text.count('\n') > 1)
385+ try:
386+ evaluate(source)
387+ except SyntaxError, e:
388+ self.assertTrue(e.text.count('\n') > 1)
389+ else:
390+ self.fail()
391
392 sourcePath = self.makeTempFile(source)
393 self.assertHasErrors(
394@@ -384,14 +384,13 @@
395 If the source file is not readable, this is reported on standard
396 error.
397 """
398- sourcePath = FilePath(self.mktemp())
399- sourcePath.setContent('')
400- sourcePath.chmod(0)
401- count, errors = self.getErrors(sourcePath.path)
402+ sourcePath = self.makeTempFile('')
403+ os.chmod(sourcePath, 0)
404+ count, errors = self.getErrors(sourcePath)
405 self.assertEquals(count, 1)
406 self.assertEquals(
407 errors,
408- [('unexpectedError', sourcePath.path, "Permission denied")])
409+ [('unexpectedError', sourcePath, "Permission denied")])
410
411
412 def test_pyflakesWarning(self):
413@@ -425,59 +424,25 @@
414 L{checkRecursive} descends into each directory, finding Python files
415 and reporting problems.
416 """
417- tempdir = FilePath(self.mktemp())
418- tempdir.createDirectory()
419- tempdir.child('foo').createDirectory()
420- file1 = tempdir.child('foo').child('bar.py')
421- file1.setContent("import baz\n")
422- file2 = tempdir.child('baz.py')
423- file2.setContent("import contraband")
424+ tempdir = tempfile.mkdtemp()
425+ os.mkdir(os.path.join(tempdir, 'foo'))
426+ file1 = os.path.join(tempdir, 'foo', 'bar.py')
427+ fd = open(file1, 'wb')
428+ fd.write("import baz\n")
429+ fd.close()
430+ file2 = os.path.join(tempdir, 'baz.py')
431+ fd = open(file2, 'wb')
432+ fd.write("import contraband")
433+ fd.close()
434 log = []
435 reporter = LoggingReporter(log)
436- warnings = checkRecursive([tempdir.path], reporter)
437+ warnings = checkRecursive([tempdir], reporter)
438 self.assertEqual(warnings, 2)
439 self.assertEqual(
440 sorted(log),
441- sorted([('flake', str(UnusedImport(file1.path, 1, 'baz'))),
442+ sorted([('flake', str(UnusedImport(file1, 1, 'baz'))),
443 ('flake',
444- str(UnusedImport(file2.path, 1, 'contraband')))]))
445-
446-
447-
448-class _EverythingGetterWithStdin(protocol.ProcessProtocol):
449- """
450- C{ProcessProtocol} that writes to stdin and gathers exit code, stdout and
451- stderr.
452- """
453-
454- # Although Twisted provides a helper that spawns a subprocess, gathers its
455- # exit code, standard output and standard error
456- # (i.e. getProcessOutputAndValue), it does *not* provide one that data to
457- # be written to stdin first.
458-
459- def __init__(self, deferred, stdin):
460- self.deferred = deferred
461- self.outBuf = StringIO()
462- self.errBuf = StringIO()
463- self.outReceived = self.outBuf.write
464- self.errReceived = self.errBuf.write
465- self.stdin = stdin
466-
467-
468- def connectionMade(self):
469- self.transport.write(self.stdin)
470- self.transport.closeStdin()
471-
472-
473- def processEnded(self, reason):
474- out = self.outBuf.getvalue()
475- err = self.errBuf.getvalue()
476- e = reason.value
477- code = e.exitCode
478- if e.signal:
479- code = -e.signal
480- self.deferred.callback((out, err, code))
481-
482+ str(UnusedImport(file2, 1, 'contraband')))]))
483
484
485 class IntegrationTests(TestCase):
486@@ -485,13 +450,20 @@
487 Tests of the pyflakes script that actually spawn the script.
488 """
489
490+ def setUp(self):
491+ self.tempdir = tempfile.mkdtemp()
492+ self.tempfilepath = os.path.join(self.tempdir, 'temp')
493+
494+ def tearDown(self):
495+ shutil.rmtree(self.tempdir)
496+
497 def getPyflakesBinary(self):
498 """
499 Return the path to the pyflakes binary.
500 """
501 import pyflakes
502- package_dir = FilePath(pyflakes.__file__).parent()
503- return package_dir.sibling('bin').child('pyflakes').path
504+ package_dir = os.path.dirname(pyflakes.__file__)
505+ return os.path.join(package_dir, '..', 'bin', 'pyflakes')
506
507
508 def runPyflakes(self, paths, stdin=None):
509@@ -505,15 +477,18 @@
510 """
511 env = dict(os.environ)
512 env['PYTHONPATH'] = os.pathsep.join(sys.path)
513- command = [self.getPyflakesBinary()]
514+ command = [sys.executable, self.getPyflakesBinary()]
515 command.extend(paths)
516 if stdin:
517- d = _callProtocolWithDeferred(
518- lambda d: _EverythingGetterWithStdin(d, stdin),
519- sys.executable, command, env=env, path=None)
520+ p = subprocess.Popen(command, env=env, stdin=subprocess.PIPE,
521+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
522+ (stdout, stderr) = p.communicate(stdin)
523 else:
524- d = getProcessOutputAndValue(sys.executable, command, env=env)
525- return d
526+ p = subprocess.Popen(command, env=env,
527+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
528+ (stdout, stderr) = p.communicate()
529+ rv = p.wait()
530+ return (stdout, stderr, rv)
531
532
533 def test_goodFile(self):
534@@ -521,10 +496,10 @@
535 When a Python source file is all good, the return code is zero and no
536 messages are printed to either stdout or stderr.
537 """
538- tempfile = FilePath(self.mktemp())
539- tempfile.touch()
540- d = self.runPyflakes([tempfile.path])
541- return d.addCallback(self.assertEqual, ('', '', 0))
542+ fd = open(self.tempfilepath, 'a')
543+ fd.close()
544+ d = self.runPyflakes([self.tempfilepath])
545+ self.assertEqual(d, ('', '', 0))
546
547
548 def test_fileWithFlakes(self):
549@@ -532,12 +507,11 @@
550 When a Python source file has warnings, the return code is non-zero
551 and the warnings are printed to stdout.
552 """
553- tempfile = FilePath(self.mktemp())
554- tempfile.setContent("import contraband\n")
555- d = self.runPyflakes([tempfile.path])
556- return d.addCallback(
557- self.assertEqual,
558- ("%s\n" % UnusedImport(tempfile.path, 1, 'contraband'), '', 1))
559+ fd = open(self.tempfilepath, 'wb')
560+ fd.write("import contraband\n")
561+ fd.close()
562+ d = self.runPyflakes([self.tempfilepath])
563+ self.assertEqual(d, ("%s\n" % UnusedImport(self.tempfilepath, 1, 'contraband'), '', 1))
564
565
566 def test_errors(self):
567@@ -546,11 +520,8 @@
568 exist, say), then the return code is non-zero and the errors are
569 printed to stderr.
570 """
571- tempfile = FilePath(self.mktemp())
572- d = self.runPyflakes([tempfile.path])
573- return d.addCallback(
574- self.assertEqual,
575- ('', '%s: No such file or directory\n' % (tempfile.path,), 1))
576+ d = self.runPyflakes([self.tempfilepath])
577+ self.assertEqual(d, ('', '%s: No such file or directory\n' % (self.tempfilepath,), 1))
578
579
580 def test_readFromStdin(self):
581@@ -558,6 +529,4 @@
582 If no arguments are passed to C{pyflakes} then it reads from stdin.
583 """
584 d = self.runPyflakes([], stdin='import contraband')
585- return d.addCallback(
586- self.assertEqual,
587- ("%s\n" % UnusedImport('<stdin>', 1, 'contraband'), '', 1))
588+ self.assertEqual(d, ("%s\n" % UnusedImport('<stdin>', 1, 'contraband'), '', 1))
589
590=== modified file 'pyflakes/test/test_undefined_names.py'
591--- pyflakes/test/test_undefined_names.py 2011-12-04 20:27:45 +0000
592+++ pyflakes/test/test_undefined_names.py 2013-01-08 22:58:19 +0000
593@@ -1,7 +1,7 @@
594
595 from _ast import PyCF_ONLY_AST
596
597-from twisted.trial.unittest import TestCase
598+from unittest2 import skip, TestCase
599
600 from pyflakes import messages as m, checker
601 from pyflakes.test import harness
602@@ -87,13 +87,13 @@
603 bar; baz
604 ''')
605
606+ @skip("todo")
607 def test_definedByGlobal(self):
608 '''"global" can make an otherwise undefined name in another function defined'''
609 self.flakes('''
610 def a(): global fu; fu = 1
611 def b(): fu
612 ''')
613- test_definedByGlobal.todo = ''
614
615 def test_globalInGlobalScope(self):
616 """

Subscribers

People subscribed via source and target branches

to all changes: