merge from master

This commit is contained in:
wiredfool 2014-06-05 00:13:47 +00:00
commit 09db145329
9 changed files with 183 additions and 66 deletions

59
.gitignore vendored
View File

@ -1,11 +1,56 @@
*.pyc
*.egg-info
build
dist
.tox
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
docs/_build
*~
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
# Django stuff:
*.log
*.pot
# Sphinx documentation
docs/_build/
# Vim cruft
.*.swp

View File

@ -14,21 +14,30 @@ python:
- 3.3
- "pypy"
install:
install:
- "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake"
- "pip install cffi"
- "pip install coveralls"
# webp
# webp
- pushd depends && ./install_webp.sh && popd
# openjpeg
- pushd depends && ./install_openjpeg.sh && popd
script:
- coverage erase
- python setup.py clean
- python setup.py build_ext --inplace
- python selftest.py
- python Tests/run.py
- coverage run --append --include=PIL/* selftest.py
- python Tests/run.py --coverage
after_success:
- coverage report
- coveralls
- pip install pep8 pyflakes
- pep8 PIL/*.py
- pyflakes PIL/*.py
matrix:
allow_failures:

View File

@ -1,6 +1,15 @@
Changelog (Pillow)
==================
2.5.0 (unreleased)
------------------
- Have the tempfile use a suffix with a dot
[wiredfool]
- Fix variable name used for transparency manipulations
[nijel]
2.4.0 (2014-04-01)
------------------

View File

@ -505,15 +505,18 @@ class Image:
def _dump(self, file=None, format=None):
import tempfile, os
suffix = ''
if format:
suffix = '.'+format
if not file:
f, file = tempfile.mkstemp(format or '')
f, file = tempfile.mkstemp(suffix)
os.close(f)
self.load()
if not format or format == "PPM":
self.im.save_ppm(file)
else:
if file.endswith(format):
if not file.endswith(format):
file = file + "." + format
self.save(file, format)
return file
@ -807,7 +810,7 @@ class Image:
new_im = self._new(im)
if delete_trns:
#crash fail if we leave a bytes transparency in an rgb/l mode.
del(new.info['transparency'])
del(new_im.info['transparency'])
if trns is not None:
if new_im.mode == 'P':
try:

View File

@ -5,8 +5,9 @@ Pillow
Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
.. image:: https://travis-ci.org/python-imaging/Pillow.png
.. image:: https://travis-ci.org/python-imaging/Pillow.svg?branch=master
:target: https://travis-ci.org/python-imaging/Pillow
:alt: Travis CI build status
.. image:: https://pypip.in/v/Pillow/badge.png
:target: https://pypi.python.org/pypi/Pillow/
@ -16,4 +17,7 @@ Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the Pyt
:target: https://pypi.python.org/pypi/Pillow/
:alt: Number of PyPI downloads
.. image:: https://coveralls.io/repos/python-imaging/Pillow/badge.png?branch=master
:target: https://coveralls.io/r/python-imaging/Pillow?branch=master
The documentation is hosted at http://pillow.readthedocs.org/. It contains installation instructions, tutorials, reference, compatibility details, and more.

View File

@ -2,7 +2,12 @@ from __future__ import print_function
# minimal test runner
import glob, os, os.path, sys, tempfile, re
import glob
import os
import os.path
import re
import sys
import tempfile
try:
root = os.path.dirname(__file__)
@ -34,6 +39,7 @@ files.sort()
success = failure = 0
include = [x for x in sys.argv[1:] if x[:2] != "--"]
skipped = []
failed = []
python_options = " ".join(python_options)
tester_options = " ".join(tester_options)
@ -48,8 +54,8 @@ for file in files:
# 2>&1 works on unix and on modern windowses. we might care about
# very old Python versions, but not ancient microsoft products :-)
out = os.popen("%s %s -u %s %s 2>&1" % (
sys.executable, python_options, file, tester_options
))
sys.executable, python_options, file, tester_options
))
result = out.read()
# Extract any ignore patterns
@ -63,7 +69,7 @@ for file in files:
if not p.endswith('$'):
p = p + '$'
return p
ignore_res = [re.compile(fix_re(p), re.MULTILINE) for p in ignore_pats]
except:
print('(bad ignore patterns %r)' % ignore_pats)
@ -73,11 +79,11 @@ for file in files:
result = r.sub('', result)
result = result.strip()
if result == "ok":
result = None
elif result == "skip":
print("---", "skipped") # FIXME: driver should include a reason
print("---", "skipped") # FIXME: driver should include a reason
skipped.append(test)
continue
elif not result:
@ -91,7 +97,7 @@ for file in files:
# if there's an ok at the end, it's not really ok
result = result[:-3]
print(result)
failure = failure + 1
failed.append(test)
else:
success = success + 1
@ -105,6 +111,7 @@ if tempfiles:
print(file)
print("-"*68)
def tests(n):
if n == 1:
return "1 test"
@ -112,10 +119,12 @@ def tests(n):
return "%d tests" % n
if skipped:
print("---", tests(len(skipped)), "skipped.")
print(skipped)
if failure:
print("***", tests(failure), "of", (success + failure), "failed.")
print("---", tests(len(skipped)), "skipped:")
print(", ".join(skipped))
if failed:
failure = len(failed)
print("***", tests(failure), "of", (success + failure), "failed:")
print(", ".join(failed))
sys.exit(1)
else:
print(tests(success), "passed.")

View File

@ -2,6 +2,7 @@ from tester import *
from PIL import Image
def verify(im1):
im2 = lena("I")
assert_equal(im1.size, im2.size)
@ -18,6 +19,7 @@ def verify(im1):
return
success()
def test_basic():
# PIL 1.1 has limited support for 16-bit image data. Check that
# create/copy/transform and save works as expected.
@ -30,10 +32,10 @@ def test_basic():
w, h = imIn.size
imOut = imIn.copy()
verify(imOut) # copy
verify(imOut) # copy
imOut = imIn.transform((w, h), Image.EXTENT, (0, 0, w, h))
verify(imOut) # transform
verify(imOut) # transform
filename = tempfile("temp.im")
imIn.save(filename)

View File

@ -6,15 +6,13 @@ warnings.simplefilter('default')
# temporarily turn off resource warnings that warn about unclosed
# files in the test scripts.
try:
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ResourceWarning)
except NameError:
# we expect a NameError on py2.x, since it doesn't have ResourceWarnings.
pass
# we expect a NameError on py2.x, since it doesn't have ResourceWarnings.
pass
import sys
py3 = (sys.version_info >= (3,0))
py3 = (sys.version_info >= (3, 0))
# some test helpers
@ -22,6 +20,7 @@ _target = None
_tempfiles = []
_logfile = None
def success():
import sys
success.count += 1
@ -29,8 +28,10 @@ def success():
print(sys.argv[0], success.count, failure.count, file=_logfile)
return True
def failure(msg=None, frame=None):
import sys, linecache
import sys
import linecache
failure.count += 1
if _target:
if frame is None:
@ -49,6 +50,7 @@ def failure(msg=None, frame=None):
success.count = failure.count = 0
# predicates
def assert_true(v, msg=None):
@ -57,35 +59,39 @@ def assert_true(v, msg=None):
else:
failure(msg or "got %r, expected true value" % v)
def assert_false(v, msg=None):
if v:
failure(msg or "got %r, expected false value" % v)
else:
success()
def assert_equal(a, b, msg=None):
if a == b:
success()
else:
failure(msg or "got %r, expected %r" % (a, b))
def assert_almost_equal(a, b, msg=None, eps=1e-6):
if abs(a-b) < eps:
success()
else:
failure(msg or "got %r, expected %r" % (a, b))
def assert_deep_equal(a, b, msg=None):
try:
if len(a) == len(b):
if all([x==y for x,y in zip(a,b)]):
if all([x == y for x, y in zip(a, b)]):
success()
else:
failure(msg or "got %s, expected %s" % (a,b))
failure(msg or "got %s, expected %s" % (a, b))
else:
failure(msg or "got length %s, expected %s" % (len(a), len(b)))
failure(msg or "got length %s, expected %s" % (len(a), len(b)))
except:
assert_equal(a,b,msg)
assert_equal(a, b, msg)
def assert_match(v, pattern, msg=None):
@ -95,8 +101,10 @@ def assert_match(v, pattern, msg=None):
else:
failure(msg or "got %r, doesn't match pattern %r" % (v, pattern))
def assert_exception(exc_class, func):
import sys, traceback
import sys
import traceback
try:
func()
except exc_class:
@ -108,8 +116,10 @@ def assert_exception(exc_class, func):
else:
failure("expected %r exception, got no exception" % exc_class.__name__)
def assert_no_exception(func):
import sys, traceback
import sys
import traceback
try:
func()
except:
@ -118,11 +128,14 @@ def assert_no_exception(func):
else:
success()
def assert_warning(warn_class, func):
# note: this assert calls func three times!
import warnings
def warn_error(message, category=UserWarning, **options):
raise category(message)
def warn_ignore(message, category=UserWarning, **options):
pass
warn = warnings.warn
@ -134,22 +147,25 @@ def assert_warning(warn_class, func):
warnings.warn = warn_error
assert_exception(warn_class, func)
finally:
warnings.warn = warn # restore
warnings.warn = warn # restore
return result
# helpers
from io import BytesIO
def fromstring(data):
from PIL import Image
return Image.open(BytesIO(data))
def tostring(im, format, **options):
out = BytesIO()
im.save(out, format, **options)
return out.getvalue()
def lena(mode="RGB", cache={}):
from PIL import Image
im = cache.get(mode)
@ -165,6 +181,7 @@ def lena(mode="RGB", cache={}):
cache[mode] = im
return im
def assert_image(im, mode, size, msg=None):
if mode is not None and im.mode != mode:
failure(msg or "got mode %r, expected %r" % (im.mode, mode))
@ -173,6 +190,7 @@ def assert_image(im, mode, size, msg=None):
else:
success()
def assert_image_equal(a, b, msg=None):
if a.mode != b.mode:
failure(msg or "got mode %r, expected %r" % (a.mode, b.mode))
@ -184,6 +202,7 @@ def assert_image_equal(a, b, msg=None):
else:
success()
def assert_image_similar(a, b, epsilon, msg=None):
epsilon = float(epsilon)
if a.mode != b.mode:
@ -193,19 +212,25 @@ def assert_image_similar(a, b, epsilon, msg=None):
diff = 0
try:
ord(b'0')
for abyte,bbyte in zip(a.tobytes(),b.tobytes()):
for abyte, bbyte in zip(a.tobytes(), b.tobytes()):
diff += abs(ord(abyte)-ord(bbyte))
except:
for abyte,bbyte in zip(a.tobytes(),b.tobytes()):
for abyte, bbyte in zip(a.tobytes(), b.tobytes()):
diff += abs(abyte-bbyte)
ave_diff = float(diff)/(a.size[0]*a.size[1])
if epsilon < ave_diff:
return failure(msg or "average pixel value difference %.4f > epsilon %.4f" %(ave_diff, epsilon))
return failure(
msg or "average pixel value difference %.4f > epsilon %.4f" % (
ave_diff, epsilon))
else:
return success()
def tempfile(template, *extra):
import os, os.path, sys, tempfile
import os
import os.path
import sys
import tempfile
files = []
root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
try:
@ -222,18 +247,20 @@ def tempfile(template, *extra):
_tempfiles.extend(files)
return files[0]
# test runner
def run():
global _target, _tests, run
import sys, traceback
import sys
import traceback
_target = sys.modules["__main__"]
run = None # no need to run twice
run = None # no need to run twice
tests = []
for name, value in list(vars(_target).items()):
if name[:5] == "test_" and type(value) is type(success):
tests.append((value.__code__.co_firstlineno, name, value))
tests.sort() # sort by line
tests.sort() # sort by line
for lineno, name, func in tests:
try:
_tests = []
@ -251,52 +278,56 @@ def run():
sys.argv[0], lineno, v))
failure.count += 1
def yield_test(function, *args):
# collect delayed/generated tests
_tests.append((function, args))
def skip(msg=None):
import os
print("skip")
os._exit(0) # don't run exit handlers
os._exit(0) # don't run exit handlers
def ignore(pattern):
"""Tells the driver to ignore messages matching the pattern, for the
duration of the current test."""
print('ignore: %s' % pattern)
def _setup():
global _logfile
import sys
if "--coverage" in sys.argv:
import coverage
cov = coverage.coverage(auto_data=True, include="PIL/*")
cov.start()
def report():
if run:
run()
if success.count and not failure.count:
print("ok")
# only clean out tempfiles if test passed
import os, os.path, tempfile
import os
import os.path
import tempfile
for file in _tempfiles:
try:
os.remove(file)
except OSError:
pass # report?
pass # report?
temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
try:
os.rmdir(temp_root)
except OSError:
pass
if "--coverage" in sys.argv:
import coverage
coverage.stop()
# The coverage module messes up when used from inside an
# atexit handler. Do an explicit save to make sure that
# we actually flush the coverage cache.
coverage.the_coverage.save()
import atexit, sys
import atexit
atexit.register(report)
if "--coverage" in sys.argv:
import coverage
coverage.start()
if "--log" in sys.argv:
_logfile = open("test.log", "a")

View File

@ -1,11 +1,12 @@
Pillow
Pillow
======
Pillow is the 'friendly' PIL fork by Alex Clark and Contributors. PIL is the
Python Imaging Library by Fredrik Lundh and Contributors.
.. image:: https://travis-ci.org/python-imaging/Pillow.png
.. image:: https://travis-ci.org/python-imaging/Pillow.svg?branch=master
:target: https://travis-ci.org/python-imaging/Pillow
:alt: Travis CI build status
.. image:: https://pypip.in/v/Pillow/badge.png
:target: https://pypi.python.org/pypi/Pillow/
@ -15,6 +16,10 @@ Python Imaging Library by Fredrik Lundh and Contributors.
:target: https://pypi.python.org/pypi/Pillow/
:alt: Number of PyPI downloads
.. image:: https://coveralls.io/repos/python-imaging/Pillow/badge.png?branch=master
:target: https://coveralls.io/r/python-imaging/Pillow?branch=master
:alt: Test coverage
To start using Pillow, please read the :doc:`installation
instructions <installation>`.
@ -48,7 +53,7 @@ Pillow is a volunteer effort led by Alex Clark. If you can't help with
development please consider helping us financially. Your assistance would
be very much appreciated!
.. note:: Contributors please add your name and donation preference here.
.. note:: Contributors please add your name and donation preference here.
======================================= =======================================
**Developer** **Preference**