mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-28 02:46:18 +03:00
Merge pull request #2243 from wiredfool/pr_2192
Drop support for Python 2.6 and 3.2
This commit is contained in:
commit
b1c816169e
12
.travis.yml
12
.travis.yml
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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'):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---------
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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__':
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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')),
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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
2
py3.h
|
@ -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
|
||||
|
|
19
setup.py
19
setup.py
|
@ -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",
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -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 =
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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.)
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue
Block a user