Merge pull request #2243 from wiredfool/pr_2192

Drop support for Python 2.6 and 3.2
This commit is contained in:
wiredfool 2016-11-22 12:31:03 +00:00 committed by GitHub
commit b1c816169e
24 changed files with 44 additions and 93 deletions

View File

@ -11,9 +11,7 @@ python:
- "pypy3"
- 3.5
- 2.7
- 2.6
- "2.7_with_system_site_packages" # For PyQt4
- 3.2
- 3.3
- 3.4
- nightly
@ -24,14 +22,10 @@ install:
- "travis_retry pip install cffi"
- "travis_retry pip install nose"
- "travis_retry pip install check-manifest"
# Pyroma tests sometimes hang on PyPy and Python 2.6; skip for those
- if [ $TRAVIS_PYTHON_VERSION != "pypy" && $TRAVIS_PYTHON_VERSION != "2.6" ]; then travis_retry pip install pyroma; fi
# Pyroma tests sometimes hang on PyPy; skip
- if [ $TRAVIS_PYTHON_VERSION != "pypy" ]; then travis_retry pip install pyroma; fi
- if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then travis_retry pip install unittest2; fi
# Coverage 4.0 doesn't support Python 3.2
- if [ "$TRAVIS_PYTHON_VERSION" == "3.2" ]; then travis_retry pip install coverage==3.7.1; fi
- if [ "$TRAVIS_PYTHON_VERSION" != "3.2" ]; then travis_retry pip install coverage; fi
- "travis_retry pip install coverage"
# docs only on python 2.7
- if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then travis_retry pip install -r requirements.txt ; fi

View File

@ -73,7 +73,7 @@ class BmpImageFile(ImageFile.ImageFile):
read, seek = self.fp.read, self.fp.seek
if header:
seek(header)
file_info = dict()
file_info = {}
file_info['header_size'] = i32(read(4)) # read bmp header size @offset 14 (this is part of the header size)
file_info['direction'] = -1
# --------------------- If requested, read header at a specific position

View File

@ -139,7 +139,7 @@ class IcoFile(object):
"""
Get a list of all available icon sizes and color depths.
"""
return set((h['width'], h['height']) for h in self.entry)
return {(h['width'], h['height']) for h in self.entry}
def getimage(self, size, bpp=False):
"""

View File

@ -408,7 +408,7 @@ def _fixup_dict(src_dict):
except: pass
return value
return dict((k, _fixup(v)) for k, v in src_dict.items())
return {k: _fixup(v) for k, v in src_dict.items()}
def _getexif(self):
@ -488,7 +488,7 @@ def _getmp(self):
rawmpentries = mp[0xB002]
for entrynum in range(0, quant):
unpackedentry = unpack_from(
'{0}LLLHH'.format(endianness), rawmpentries, entrynum * 16)
'{}LLLHH'.format(endianness), rawmpentries, entrynum * 16)
labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1',
'EntryNo2')
mpentry = dict(zip(labels, unpackedentry))

View File

@ -132,7 +132,7 @@ COMPRESSION_INFO = {
34677: "tiff_sgilog24",
}
COMPRESSION_INFO_REV = dict((v, k) for (k, v) in COMPRESSION_INFO.items())
COMPRESSION_INFO_REV = {v: k for k, v in COMPRESSION_INFO.items()}
OPEN_INFO = {
# (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
@ -294,11 +294,7 @@ class IFDRational(Rational):
return
elif denominator == 1:
if sys.hexversion < 0x2070000 and isinstance(value, float):
# python 2.6 is different.
self._val = Fraction.from_float(value)
else:
self._val = Fraction(value)
self._val = Fraction(value)
else:
self._val = Fraction(value, denominator)
@ -592,7 +588,7 @@ class ImageFileDirectory_v2(collections.MutableMapping):
TYPES[idx] = name
size = struct.calcsize("=" + fmt)
_load_dispatch[idx] = size, lambda self, data, legacy_api=True: (
self._unpack("{0}{1}".format(len(data) // size, fmt), data))
self._unpack("{}{}".format(len(data) // size, fmt), data))
_write_dispatch[idx] = lambda self, *values: (
b"".join(self._pack(fmt, value) for value in values))
@ -624,7 +620,7 @@ class ImageFileDirectory_v2(collections.MutableMapping):
@_register_loader(5, 8)
def load_rational(self, data, legacy_api=True):
vals = self._unpack("{0}L".format(len(data) // 4), data)
vals = self._unpack("{}L".format(len(data) // 4), data)
combine = lambda a, b: (a, b) if legacy_api else IFDRational(a, b)
return tuple(combine(num, denom)
for num, denom in zip(vals[::2], vals[1::2]))
@ -644,7 +640,7 @@ class ImageFileDirectory_v2(collections.MutableMapping):
@_register_loader(10, 8)
def load_signed_rational(self, data, legacy_api=True):
vals = self._unpack("{0}l".format(len(data) // 4), data)
vals = self._unpack("{}l".format(len(data) // 4), data)
combine = lambda a, b: (a, b) if legacy_api else IFDRational(a, b)
return tuple(combine(num, denom)
for num, denom in zip(vals[::2], vals[1::2]))
@ -1518,7 +1514,7 @@ class AppendingTiffWriter:
# JPEGQTables = 519
# JPEGDCTables = 520
# JPEGACTables = 521
Tags = set((273, 288, 324, 519, 520, 521))
Tags = {273, 288, 324, 519, 520, 521}
def __init__(self, fn, new=False):
if hasattr(fn, 'read'):

View File

@ -418,13 +418,13 @@ TYPES = {}
# some of these are not in our TAGS_V2 dict and were included from tiff.h
LIBTIFF_CORE = set([255, 256, 257, 258, 259, 262, 263, 266, 274, 277,
278, 280, 281, 340, 341, 282, 283, 284, 286, 287,
296, 297, 321, 320, 338, 32995, 322, 323, 32998,
32996, 339, 32997, 330, 531, 530, 301, 532, 333,
# as above
269 # this has been in our tests forever, and works
])
LIBTIFF_CORE = {255, 256, 257, 258, 259, 262, 263, 266, 274, 277,
278, 280, 281, 340, 341, 282, 283, 284, 286, 287,
296, 297, 321, 320, 338, 32995, 322, 323, 32998,
32996, 339, 32997, 330, 531, 530, 301, 532, 333,
# as above
269 # this has been in our tests forever, and works
}
LIBTIFF_CORE.remove(320) # Array of short, crashes
LIBTIFF_CORE.remove(301) # Array of short, crashes

View File

@ -10,10 +10,6 @@ Install::
pip install coverage nose
If you're using Python 2.6, there's one additional dependency::
pip install unittest2
Execution
---------

View File

@ -5,11 +5,7 @@ from __future__ import print_function
import sys
import tempfile
import os
if sys.version_info[:2] <= (2, 6):
import unittest2 as unittest
else:
import unittest
import unittest
class PillowTestCase(unittest.TestCase):

View File

@ -180,9 +180,9 @@ class TestFileLibTiff(LibTiffTestCase):
# Get the list of the ones that we should be able to write
core_items = dict((tag, info) for tag, info in [(s, TiffTags.lookup(s)) for s
in TiffTags.LIBTIFF_CORE]
if info.type is not None)
core_items = {tag: info for tag, info in ((s, TiffTags.lookup(s)) for s
in TiffTags.LIBTIFF_CORE)
if info.type is not None}
# Exclude ones that have special meaning
# that we're already testing them

View File

@ -8,7 +8,7 @@ from helper import unittest, PillowTestCase, hopper
from PIL import Image, TiffImagePlugin, TiffTags
from PIL.TiffImagePlugin import _limit_rational, IFDRational
tag_ids = dict((info.name, info.value) for info in TiffTags.TAGS_V2.values())
tag_ids = {info.name: info.value for info in TiffTags.TAGS_V2.values()}
class TestFileTiffMetadata(PillowTestCase):

View File

@ -1,5 +1,4 @@
from helper import unittest, PillowTestCase, hopper, py3
import sys
class TestImageGetIm(PillowTestCase):
@ -11,13 +10,7 @@ class TestImageGetIm(PillowTestCase):
if py3:
self.assertIn("PyCapsule", type_repr)
if sys.hexversion < 0x2070000:
# py2.6 x64, windows
target_types = (int, long)
else:
target_types = (int)
self.assertIsInstance(im.im.id, target_types)
self.assertIsInstance(im.im.id, int)
if __name__ == '__main__':

View File

@ -232,10 +232,10 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
def run_levels_case(self, i):
px = i.load()
for y in range(i.size[1]):
used_colors = set(px[x, y][0] for x in range(i.size[0]))
used_colors = {px[x, y][0] for x in range(i.size[0])}
self.assertEqual(256, len(used_colors),
'All colors should present in resized image. '
'Only {0} on {1} line.'.format(len(used_colors), y))
'Only {} on {} line.'.format(len(used_colors), y))
@unittest.skip("current implementation isn't precise enough")
def test_levels_rgba(self):
@ -270,7 +270,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
for y in range(i.size[1]):
for x in range(i.size[0]):
if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel:
message = 'pixel at ({0}, {1}) is differ:\n{2}\n{3}'\
message = 'pixel at ({}, {}) is differ:\n{}\n{}'\
.format(x, y, px[x, y], clean_pixel)
self.assertEqual(px[x, y][:3], clean_pixel, message)

View File

@ -69,10 +69,10 @@ class TestImagingCoreResize(PillowTestCase):
for f in [Image.LINEAR, Image.BOX, Image.BILINEAR, Image.HAMMING,
Image.BICUBIC, Image.LANCZOS]:
# samples resized with current filter
references = dict(
(name, self.resize(ch, (4, 4), f))
references = {
name: self.resize(ch, (4, 4), f)
for name, ch in samples.items()
)
}
for mode, channels_set in [
('RGB', ('blank', 'filled', 'dirty')),

View File

@ -29,7 +29,7 @@ class TestToQImage(PillowQtTestCase, PillowTestCase):
self.assertFalse(data.isNull())
# Test saving the file
tempfile = self.tempfile('temp_{0}.png'.format(mode))
tempfile = self.tempfile('temp_{}.png'.format(mode))
data.save(tempfile)

View File

@ -19,7 +19,7 @@ class TestToQPixmap(PillowQPixmapTestCase, PillowTestCase):
self.assertFalse(data.isNull())
# Test saving the file
tempfile = self.tempfile('temp_{0}.png'.format(mode))
tempfile = self.tempfile('temp_{}.png'.format(mode))
data.save(tempfile)

View File

@ -75,11 +75,7 @@ if sys.platform.startswith('win32'):
memcpy(bp, ctypes.byref(bf), ctypes.sizeof(bf))
memcpy(bp + ctypes.sizeof(bf), ctypes.byref(bi), bi.biSize)
memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
try:
return bytearray(buf)
except ValueError:
# py2.6
return buffer(buf)[:]
return bytearray(buf)
class TestImageWinPointers(PillowTestCase):
def test_pointer(self):

View File

@ -3073,11 +3073,7 @@ _getattr_id(ImagingObject* self, void* closure)
static PyObject*
_getattr_ptr(ImagingObject* self, void* closure)
{
#if PY_VERSION_HEX >= 0x02070000
return PyCapsule_New(self->image, IMAGING_MAGIC, NULL);
#else
return PyCObject_FromVoidPtrAndDesc(self->image, IMAGING_MAGIC, NULL);
#endif
}
static PyObject*

View File

@ -15,7 +15,9 @@ Notes
.. note:: Pillow < 2.0.0 supports Python versions 2.4, 2.5, 2.6, 2.7.
.. note:: Pillow >= 2.0.0 supports Python versions 2.6, 2.7, 3.2, 3.3, 3.4, 3.5
.. note:: Pillow >= 2.0.0 < 3.5.0 supports Python versions 2.6, 2.7, 3.2, 3.3, 3.4, 3.5
.. note:: Pillow >= 3.5.0 supports Python versions 2.7, 3.3, 3.4, 3.5
Basic Installation
------------------

2
py3.h
View File

@ -1,5 +1,5 @@
/*
Python3 definition file to consistently map the code to Python 2.6 or
Python3 definition file to consistently map the code to Python 2 or
Python 3.
PyInt and PyLong were merged into PyLong in Python 3, so all PyInt functions

View File

@ -74,20 +74,7 @@ def _find_include_file(self, include):
def _find_library_file(self, library):
# Fix for 3.2.x <3.2.4, 3.3.0, shared lib extension is the python shared
# lib extension, not the system shared lib extension: e.g. .cpython-33.so
# vs .so. See Python bug http://bugs.python.org/16754
if 'cpython' in self.compiler.shared_lib_extension:
_dbg('stripping cpython from shared library extension %s',
self.compiler.shared_lib_extension)
existing = self.compiler.shared_lib_extension
self.compiler.shared_lib_extension = "." + existing.split('.')[-1]
ret = self.compiler.find_library_file(self.compiler.library_dirs,
library)
self.compiler.shared_lib_extension = existing
else:
ret = self.compiler.find_library_file(self.compiler.library_dirs,
library)
ret = self.compiler.find_library_file(self.compiler.library_dirs, library)
if ret:
_dbg('Found library %s at %s', (library, ret))
else:
@ -147,7 +134,7 @@ class pil_build_ext(build_ext):
features = ['zlib', 'jpeg', 'tiff', 'freetype', 'lcms', 'webp',
'webpmux', 'jpeg2000', 'imagequant']
required = set(['jpeg', 'zlib'])
required = {'jpeg', 'zlib'}
def __init__(self):
for f in self.features:
@ -770,10 +757,8 @@ try:
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
"Topic :: Multimedia :: Graphics :: Viewers",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",

View File

@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
envlist = py26, py27, py32, py33, py34, py35
envlist = py27, py33, py34, py35
[testenv]
commands =

View File

@ -18,9 +18,6 @@ def setup_vms():
% (py, arch, VIRT_BASE, py, arch))
ret.append("%s%s%s\Scripts\pip.exe install nose" %
(VIRT_BASE, py, arch))
if py == '26':
ret.append("%s%s%s\Scripts\pip.exe install unittest2" %
(VIRT_BASE, py, arch))
return "\n".join(ret)

View File

@ -31,7 +31,7 @@ The build routines expect Python to be installed at C:\PythonXX for
Download Python 3.4, install it, and add it to the path. This is the
Python that we will use to bootstrap the build process. (The download
routines are using 3.2+ features, and installing 3.4 gives us pip and
routines are using 3 features, and installing 3.4 gives us pip and
virtualenv as well, reducing the number of packages that we need to
install.)

View File

@ -2,7 +2,7 @@ from fetch import fetch
import os
if __name__ == '__main__':
for version in ['2.6.6', '2.7.10', '3.2.5', '3.3.5', '3.4.3']:
for version in ['2.7.10', '3.3.5', '3.4.3']:
for platform in ['', '.amd64']:
for extension in ['', '.asc']:
fetch('https://www.python.org/ftp/python/%s/python-%s%s.msi%s'