Drop support for Python 2.6

* Drop unittest2 requirement
* Use set literals
* Use dict/set comprehension
* Use str.format() automatic numbering
This commit is contained in:
Jon Dufresne 2016-11-07 04:33:46 -08:00 committed by wiredfool
parent 70c2df21ca
commit dbe9f85c7d
23 changed files with 41 additions and 73 deletions

View File

@ -11,7 +11,6 @@ python:
- "pypy3"
- 3.5
- 2.7
- 2.6
- "2.7_with_system_site_packages" # For PyQt4
- 3.2
- 3.3
@ -24,10 +23,8 @@ 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
- if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then travis_retry pip install unittest2; fi
# Pyroma tests sometimes hang on PyPy; skip
- if [ $TRAVIS_PYTHON_VERSION != "pypy" ]; then travis_retry pip install pyroma; 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

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.2, 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

@ -147,7 +147,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,7 +770,6 @@ 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",

View File

@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
envlist = py26, py27, py32, py33, py34, py35
envlist = py27, py32, 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

@ -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.2.5', '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'