From 24cd3d2cfa88eaaf2bccff2649d221c4c593c1b5 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 25 Jun 2014 15:01:47 -0700 Subject: [PATCH 1/8] Make nose run tests in parallel --- .travis.yml | 2 +- test-installed.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d4880847c..800fac43a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python notifications: irc: "chat.freenode.net#pil" -env: MAX_CONCURRENCY=4 +env: MAX_CONCURRENCY=4 NOSE_PROCESSES=4 NOSE_PROCESS_TIMEOUT=30 python: - "pypy" diff --git a/test-installed.py b/test-installed.py index 0248590a5..0fed377b8 100755 --- a/test-installed.py +++ b/test-installed.py @@ -20,5 +20,13 @@ if len(sys.argv) == 1: if ('--no-path-adjustment' not in sys.argv) and ('-P' not in sys.argv): sys.argv.insert(1, '--no-path-adjustment') +if 'NOSE_PROCESSES' not in os.environ: + for arg in sys.argv: + if '--processes' in arg: + break + else: # for + sys.argv.insert(1, '--processes=-1') # -1 == number of cores + sys.argv.insert(1, '--process-timeout=30') + if __name__ == '__main__': nose.main() From c824a15fe8d45535ce5ace70ea0d53bcd4305e40 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 25 Jun 2014 17:08:24 -0700 Subject: [PATCH 2/8] Thread and race condition safe tempfiles for testing --- Tests/helper.py | 72 +++++++++++++----------------------------- Tests/test_font_pcf.py | 3 +- 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 416586c78..9a18f0202 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -3,39 +3,30 @@ Helper functions. """ from __future__ import print_function import sys +import tempfile +import os +import glob if sys.version_info[:2] <= (2, 6): import unittest2 as unittest else: import unittest - -# This should be imported into every test_XXX.py file to report -# any remaining temp files at the end of the run. def tearDownModule(): - import glob - import os - import tempfile - temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests') - tempfiles = glob.glob(os.path.join(temp_root, "temp_*")) - if tempfiles: - print("===", "remaining temporary files") - for file in tempfiles: - print(file) - print("-"*68) - + #remove me later + pass class PillowTestCase(unittest.TestCase): - currentResult = None # holds last result object passed to run method - _tempfiles = [] + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + self.currentResult = None # holds last result object passed to run method def run(self, result=None): - self.addCleanup(self.delete_tempfiles) self.currentResult = result # remember result for use later unittest.TestCase.run(self, result) # call superclass run method - def delete_tempfiles(self): + def delete_tempfile(self, path): try: ok = self.currentResult.wasSuccessful() except AttributeError: # for nosetests @@ -44,19 +35,14 @@ class PillowTestCase(unittest.TestCase): if ok: # only clean out tempfiles if test passed - import os - import os.path - import tempfile - for file in self._tempfiles: - try: - os.remove(file) - except OSError: - pass # report? - temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests') try: - os.rmdir(temp_root) + print("Removing File: %s" % path) + os.remove(path) except OSError: - pass + pass # report? + else: + print("=== orphaned temp file") + print(path) def assert_almost_equal(self, a, b, msg=None, eps=1e-6): self.assertLess( @@ -139,27 +125,13 @@ class PillowTestCase(unittest.TestCase): self.assertTrue(found) return result - def tempfile(self, template, *extra): - import os - import os.path - import sys - import tempfile - files = [] - root = os.path.join(tempfile.gettempdir(), 'pillow-tests') - try: - os.mkdir(root) - except OSError: - pass - for temp in (template,) + extra: - assert temp[:5] in ("temp.", "temp_") - name = os.path.basename(sys.argv[0]) - name = temp[:4] + os.path.splitext(name)[0][4:] - name = name + "_%d" % len(self._tempfiles) + temp[4:] - name = os.path.join(root, name) - files.append(name) - self._tempfiles.extend(files) - return files[0] - + def tempfile(self, template): + assert template[:5] in ("temp.", "temp_") + (fd, path) = tempfile.mkstemp(template[4:], template[:4]) + os.close(fd) + + self.addCleanup(self.delete_tempfile, path) + return path # helpers diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index 24abcf73d..8c4c04cd4 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -22,7 +22,8 @@ class TestFontPcf(PillowTestCase): self.assertIsInstance(font, FontFile.FontFile) self.assertEqual(len([_f for _f in font.glyph if _f]), 192) - tempname = self.tempfile("temp.pil", "temp.pbm") + tempname = self.tempfile("temp.pil") + self.addCleanup(self.delete_tempfile, tempname[:-4]+'.pbm') font.save(tempname) return tempname From acab4e8fdcfdae19862ddc1f8e30fdde894964a3 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 25 Jun 2014 22:47:21 -0700 Subject: [PATCH 3/8] Cleaned up prints --- Tests/helper.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 9a18f0202..1c9851e25 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -36,13 +36,11 @@ class PillowTestCase(unittest.TestCase): if ok: # only clean out tempfiles if test passed try: - print("Removing File: %s" % path) os.remove(path) except OSError: pass # report? else: - print("=== orphaned temp file") - print(path) + print("=== orphaned temp file: %s" %path) def assert_almost_equal(self, a, b, msg=None, eps=1e-6): self.assertLess( From 0ac0e973f0dda9fecf74af05363fa3ebd4311413 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 27 Jun 2014 12:07:34 -0700 Subject: [PATCH 4/8] Ignore debugging blocks --- .coveragerc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.coveragerc b/.coveragerc index bd93c4749..87e3e968f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -9,3 +9,6 @@ exclude_lines = # Don't complain if non-runnable code isn't run: if 0: if __name__ == .__main__.: + # Don't complain about debug code + if Image.DEBUG: + if DEBUG: \ No newline at end of file From 3834d01044c360d58fb4a1939006089b9f724b26 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 27 Jun 2014 12:07:53 -0700 Subject: [PATCH 5/8] Help for testing --- Makefile | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Makefile b/Makefile index 4f6a00711..0637e901f 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ + + pre: virtualenv . bin/pip install -r requirements.txt @@ -9,3 +11,32 @@ pre: check-manifest pyroma . viewdoc + +clean: + python setup.py clean + rm PIL/*.so || true + find . -name __pycache__ | xargs rm -r + +install: + python setup.py install + python selftest.py --installed + +test: install + python test-installed.py + +inplace: clean + python setup.py build_ext --inplace + +coverage: +# requires nose-cov + coverage erase + coverage run --parallel-mode --include=PIL/* selftest.py + nosetests --with-cov --cov='PIL/' --cov-report=html Tests/test_*.py +# doesn't combine properly before report, +# writing report instead of displaying invalid report + rm -r htmlcov || true + coverage combine + coverage report + +test-dep: + pip install coveralls nose nose-cov pep8 pyflakes From 2faf36ab5b9104c1088d973c9f882e64a826ba09 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 30 Jun 2014 15:30:05 -0700 Subject: [PATCH 6/8] Not enabling multithreaded tests on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 800fac43a..d4880847c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python notifications: irc: "chat.freenode.net#pil" -env: MAX_CONCURRENCY=4 NOSE_PROCESSES=4 NOSE_PROCESS_TIMEOUT=30 +env: MAX_CONCURRENCY=4 python: - "pypy" From 9dd559cb50e20a23a5d046c600572d5e850176e5 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 30 Jun 2014 15:35:24 -0700 Subject: [PATCH 7/8] Enable multithread testing for travis --- .travis.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index d4880847c..3a8d8653f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python notifications: irc: "chat.freenode.net#pil" -env: MAX_CONCURRENCY=4 +env: MAX_CONCURRENCY=4 NOSE_PROCESSES=4 NOSE_PROCESS_TIMEOUT=30 python: - "pypy" @@ -14,9 +14,9 @@ python: - 3.4 install: - - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake" + - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" - "pip install cffi" - - "pip install coveralls nose pyroma" + - "pip install coveralls nose nose-cov" - if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install unittest2; fi # webp @@ -35,10 +35,13 @@ script: - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time nosetests Tests/test_*.py; fi # Cover the others - - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* selftest.py; fi - - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* -m nose Tests/test_*.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then coverage run --parallel-mode --include=PIL/* selftest.py; fi + # write html report, then ignore. Coverage needs to be combined first + - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then nosetests --with-cov --cov='PIL/' --cov-report=html Tests/test_*.py; fi after_success: + - ls -l .coverage* + - coverage combine - coverage report - coveralls - pip install pep8 pyflakes From 2ca9ffba5d0981e5fbbe53dba297a0abf0013272 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 1 Jul 2014 09:09:00 -0700 Subject: [PATCH 8/8] renabling pyroma --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3a8d8653f..57c2cb94b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ python: install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" - "pip install cffi" - - "pip install coveralls nose nose-cov" + - "pip install coveralls nose pyroma nose-cov" - if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install unittest2; fi # webp