mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-10 00:20:57 +03:00
Merge branch 'master' into imagecms-deprecations
This commit is contained in:
commit
7477036230
12
CHANGES.rst
12
CHANGES.rst
|
@ -5,6 +5,18 @@ Changelog (Pillow)
|
||||||
6.0.0 (unreleased)
|
6.0.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Deprecate support for PyQt4 and PySide #3655
|
||||||
|
[hugovk, radarhere]
|
||||||
|
|
||||||
|
- Add TIFF compression codecs: LZMA, Zstd, WebP #3555
|
||||||
|
[cgohlke]
|
||||||
|
|
||||||
|
- Fixed pickling of iTXt class with protocol > 1 #3537
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- _util.isPath returns True for pathlib.Path objects #3616
|
||||||
|
[wbadart]
|
||||||
|
|
||||||
- Remove unnecessary unittest.main() boilerplate from test files #3631
|
- Remove unnecessary unittest.main() boilerplate from test files #3631
|
||||||
[jdufresne]
|
[jdufresne]
|
||||||
|
|
||||||
|
|
BIN
Tests/images/itxt_chunks.png
Normal file
BIN
Tests/images/itxt_chunks.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
|
@ -1,7 +1,16 @@
|
||||||
from .helper import PillowTestCase, hopper
|
from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
from PIL import ImageQt
|
import warnings
|
||||||
|
|
||||||
|
deprecated = False
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.filterwarnings("error", category=DeprecationWarning)
|
||||||
|
try:
|
||||||
|
from PIL import ImageQt
|
||||||
|
except DeprecationWarning:
|
||||||
|
deprecated = True
|
||||||
|
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||||
|
from PIL import ImageQt
|
||||||
|
|
||||||
if ImageQt.qt_is_installed:
|
if ImageQt.qt_is_installed:
|
||||||
from PIL.ImageQt import qRgba
|
from PIL.ImageQt import qRgba
|
||||||
|
@ -78,3 +87,6 @@ class TestImageQt(PillowQtTestCase, PillowTestCase):
|
||||||
def test_image(self):
|
def test_image(self):
|
||||||
for mode in ('1', 'RGB', 'RGBA', 'L', 'P'):
|
for mode in ('1', 'RGB', 'RGBA', 'L', 'P'):
|
||||||
ImageQt.ImageQt(hopper(mode))
|
ImageQt.ImageQt(hopper(mode))
|
||||||
|
|
||||||
|
def test_deprecated(self):
|
||||||
|
self.assertEqual(ImageQt.qt_version in ["4", "side"], deprecated)
|
||||||
|
|
|
@ -67,9 +67,13 @@ class TestPickle(PillowTestCase):
|
||||||
"Tests/images/non_zero_bb.png",
|
"Tests/images/non_zero_bb.png",
|
||||||
"Tests/images/non_zero_bb_scale2.png",
|
"Tests/images/non_zero_bb_scale2.png",
|
||||||
"Tests/images/p_trns_single.png",
|
"Tests/images/p_trns_single.png",
|
||||||
"Tests/images/pil123p.png"
|
"Tests/images/pil123p.png",
|
||||||
|
"Tests/images/itxt_chunks.png"
|
||||||
]:
|
]:
|
||||||
self.helper_pickle_string(pickle, test_file=test_file)
|
for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
|
||||||
|
self.helper_pickle_string(pickle,
|
||||||
|
protocol=protocol,
|
||||||
|
test_file=test_file)
|
||||||
|
|
||||||
def test_pickle_l_mode(self):
|
def test_pickle_l_mode(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from .helper import PillowTestCase
|
from .helper import unittest, PillowTestCase
|
||||||
|
|
||||||
from PIL import _util
|
from PIL import _util
|
||||||
|
|
||||||
|
@ -35,6 +35,18 @@ class TestUtil(PillowTestCase):
|
||||||
# Assert
|
# Assert
|
||||||
self.assertTrue(it_is)
|
self.assertTrue(it_is)
|
||||||
|
|
||||||
|
@unittest.skipIf(not _util.py36, 'os.path support for Paths added in 3.6')
|
||||||
|
def test_path_obj_is_path(self):
|
||||||
|
# Arrange
|
||||||
|
from pathlib import Path
|
||||||
|
test_path = Path('filename.ext')
|
||||||
|
|
||||||
|
# Act
|
||||||
|
it_is = _util.isPath(test_path)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertTrue(it_is)
|
||||||
|
|
||||||
def test_is_not_path(self):
|
def test_is_not_path(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
filename = self.tempfile("temp.ext")
|
filename = self.tempfile("temp.ext")
|
||||||
|
|
|
@ -12,6 +12,42 @@ Deprecated features
|
||||||
Below are features which are considered deprecated. Where appropriate,
|
Below are features which are considered deprecated. Where appropriate,
|
||||||
a ``DeprecationWarning`` is issued.
|
a ``DeprecationWarning`` is issued.
|
||||||
|
|
||||||
|
PyQt4 and PySide
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 6.0.0
|
||||||
|
|
||||||
|
Qt 4 reached end-of-life on 2015-12-19. Its Python bindings are also EOL: PyQt4 since
|
||||||
|
2018-08-31 and PySide since 2015-10-14.
|
||||||
|
|
||||||
|
Support for PyQt4 and PySide has been deprecated from ``ImageQt`` and will be removed in
|
||||||
|
a future version. Please upgrade to PyQt5 or PySide2.
|
||||||
|
|
||||||
|
PIL.*ImagePlugin.__version__ attributes
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 6.0.0
|
||||||
|
|
||||||
|
The version constants of individual plugins have been deprecated and will be removed in
|
||||||
|
a future version. Use ``PIL.__version__`` instead.
|
||||||
|
|
||||||
|
=============================== ================================= ==================================
|
||||||
|
Deprecated Deprecated Deprecated
|
||||||
|
=============================== ================================= ==================================
|
||||||
|
``BmpImagePlugin.__version__`` ``Jpeg2KImagePlugin.__version__`` ``PngImagePlugin.__version__``
|
||||||
|
``CurImagePlugin.__version__`` ``JpegImagePlugin.__version__`` ``PpmImagePlugin.__version__``
|
||||||
|
``DcxImagePlugin.__version__`` ``McIdasImagePlugin.__version__`` ``PsdImagePlugin.__version__``
|
||||||
|
``EpsImagePlugin.__version__`` ``MicImagePlugin.__version__`` ``SgiImagePlugin.__version__``
|
||||||
|
``FliImagePlugin.__version__`` ``MpegImagePlugin.__version__`` ``SunImagePlugin.__version__``
|
||||||
|
``FpxImagePlugin.__version__`` ``MpoImagePlugin.__version__`` ``TgaImagePlugin.__version__``
|
||||||
|
``GdImageFile.__version__`` ``MspImagePlugin.__version__`` ``TiffImagePlugin.__version__``
|
||||||
|
``GifImagePlugin.__version__`` ``PalmImagePlugin.__version__`` ``WmfImagePlugin.__version__``
|
||||||
|
``IcoImagePlugin.__version__`` ``PcdImagePlugin.__version__`` ``XbmImagePlugin.__version__``
|
||||||
|
``ImImagePlugin.__version__`` ``PcxImagePlugin.__version__`` ``XpmImagePlugin.__version__``
|
||||||
|
``ImtImagePlugin.__version__`` ``PdfImagePlugin.__version__`` ``XVThumbImagePlugin.__version__``
|
||||||
|
``IptcImagePlugin.__version__`` ``PixarImagePlugin.__version__``
|
||||||
|
=============================== ================================= ==================================
|
||||||
|
|
||||||
Setting the size of TIFF images
|
Setting the size of TIFF images
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
The :py:mod:`ImageQt` module contains support for creating PyQt4, PyQt5, PySide or
|
The :py:mod:`ImageQt` module contains support for creating PyQt4, PyQt5, PySide or
|
||||||
PySide2 QImage objects from PIL images.
|
PySide2 QImage objects from PIL images.
|
||||||
|
|
||||||
|
Qt 4 reached end-of-life on 2015-12-19. Its Python bindings are also EOL: PyQt4 since
|
||||||
|
2018-08-31 and PySide since 2015-10-14.
|
||||||
|
|
||||||
|
Support for PyQt4 and PySide is deprecated since Pillow 6.0.0 and will be removed in a
|
||||||
|
future version. Please upgrade to PyQt5 or PySide2.
|
||||||
|
|
||||||
.. versionadded:: 1.1.6
|
.. versionadded:: 1.1.6
|
||||||
|
|
||||||
.. py:class:: ImageQt.ImageQt(image)
|
.. py:class:: ImageQt.ImageQt(image)
|
||||||
|
|
|
@ -32,10 +32,20 @@ API Changes
|
||||||
Deprecations
|
Deprecations
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
PyQt4 and PySide
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Qt 4 reached end-of-life on 2015-12-19. Its Python bindings are also EOL: PyQt4 since
|
||||||
|
2018-08-31 and PySide since 2015-10-14.
|
||||||
|
|
||||||
|
Support for PyQt4 and PySide has been deprecated from ``ImageQt`` and will be removed in
|
||||||
|
a future version. Please upgrade to PyQt5 or PySide2.
|
||||||
|
|
||||||
PIL.*ImagePlugin.__version__ attributes
|
PIL.*ImagePlugin.__version__ attributes
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
These version constants have been deprecated and will be removed in a future version.
|
These version constants have been deprecated and will be removed in a future
|
||||||
|
version.
|
||||||
|
|
||||||
* ``BmpImagePlugin.__version__``
|
* ``BmpImagePlugin.__version__``
|
||||||
* ``CurImagePlugin.__version__``
|
* ``CurImagePlugin.__version__``
|
||||||
|
|
|
@ -655,8 +655,7 @@ class Image(object):
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (isinstance(other, Image) and
|
return (self.__class__ is other.__class__ and
|
||||||
self.__class__.__name__ == other.__class__.__name__ and
|
|
||||||
self.mode == other.mode and
|
self.mode == other.mode and
|
||||||
self.size == other.size and
|
self.size == other.size and
|
||||||
self.info == other.info and
|
self.info == other.info and
|
||||||
|
|
|
@ -20,6 +20,7 @@ from . import Image
|
||||||
from ._util import isPath, py3
|
from ._util import isPath, py3
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
qt_versions = [
|
qt_versions = [
|
||||||
['5', 'PyQt5'],
|
['5', 'PyQt5'],
|
||||||
|
@ -27,6 +28,12 @@ qt_versions = [
|
||||||
['4', 'PyQt4'],
|
['4', 'PyQt4'],
|
||||||
['side', 'PySide']
|
['side', 'PySide']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
WARNING_TEXT = (
|
||||||
|
"Support for EOL {} is deprecated and will be removed in a future version. "
|
||||||
|
"Please upgrade to PyQt5 or PySide2."
|
||||||
|
)
|
||||||
|
|
||||||
# If a version has already been imported, attempt it first
|
# If a version has already been imported, attempt it first
|
||||||
qt_versions.sort(key=lambda qt_version: qt_version[1] in sys.modules,
|
qt_versions.sort(key=lambda qt_version: qt_version[1] in sys.modules,
|
||||||
reverse=True)
|
reverse=True)
|
||||||
|
@ -41,9 +48,13 @@ for qt_version, qt_module in qt_versions:
|
||||||
elif qt_module == 'PyQt4':
|
elif qt_module == 'PyQt4':
|
||||||
from PyQt4.QtGui import QImage, qRgba, QPixmap
|
from PyQt4.QtGui import QImage, qRgba, QPixmap
|
||||||
from PyQt4.QtCore import QBuffer, QIODevice
|
from PyQt4.QtCore import QBuffer, QIODevice
|
||||||
|
|
||||||
|
warnings.warn(WARNING_TEXT.format(qt_module), DeprecationWarning)
|
||||||
elif qt_module == 'PySide':
|
elif qt_module == 'PySide':
|
||||||
from PySide.QtGui import QImage, qRgba, QPixmap
|
from PySide.QtGui import QImage, qRgba, QPixmap
|
||||||
from PySide.QtCore import QBuffer, QIODevice
|
from PySide.QtCore import QBuffer, QIODevice
|
||||||
|
|
||||||
|
warnings.warn(WARNING_TEXT.format(qt_module), DeprecationWarning)
|
||||||
except (ImportError, RuntimeError):
|
except (ImportError, RuntimeError):
|
||||||
continue
|
continue
|
||||||
qt_is_installed = True
|
qt_is_installed = True
|
||||||
|
@ -67,7 +78,7 @@ def fromqimage(im):
|
||||||
"""
|
"""
|
||||||
buffer = QBuffer()
|
buffer = QBuffer()
|
||||||
buffer.open(QIODevice.ReadWrite)
|
buffer.open(QIODevice.ReadWrite)
|
||||||
# preserve alha channel with png
|
# preserve alpha channel with png
|
||||||
# otherwise ppm is more friendly with Image.open
|
# otherwise ppm is more friendly with Image.open
|
||||||
if im.hasAlphaChannel():
|
if im.hasAlphaChannel():
|
||||||
im.save(buffer, 'png')
|
im.save(buffer, 'png')
|
||||||
|
|
|
@ -194,7 +194,7 @@ class iTXt(str):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __new__(cls, text, lang, tkey):
|
def __new__(cls, text, lang=None, tkey=None):
|
||||||
"""
|
"""
|
||||||
:param cls: the class to use when creating the instance
|
:param cls: the class to use when creating the instance
|
||||||
:param text: value for this key
|
:param text: value for this key
|
||||||
|
|
|
@ -135,6 +135,9 @@ COMPRESSION_INFO = {
|
||||||
32946: "tiff_deflate",
|
32946: "tiff_deflate",
|
||||||
34676: "tiff_sgilog",
|
34676: "tiff_sgilog",
|
||||||
34677: "tiff_sgilog24",
|
34677: "tiff_sgilog24",
|
||||||
|
34925: "lzma",
|
||||||
|
50000: "zstd",
|
||||||
|
50001: "webp",
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPRESSION_INFO_REV = {v: k for k, v in COMPRESSION_INFO.items()}
|
COMPRESSION_INFO_REV = {v: k for k, v in COMPRESSION_INFO.items()}
|
||||||
|
@ -423,7 +426,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
|
|
||||||
ifd = ImageFileDirectory_v2()
|
ifd = ImageFileDirectory_v2()
|
||||||
ifd[key] = 'Some Data'
|
ifd[key] = 'Some Data'
|
||||||
ifd.tagtype[key] = 2
|
ifd.tagtype[key] = TiffTags.ASCII
|
||||||
print(ifd[key])
|
print(ifd[key])
|
||||||
'Some Data'
|
'Some Data'
|
||||||
|
|
||||||
|
@ -557,7 +560,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
if info.type:
|
if info.type:
|
||||||
self.tagtype[tag] = info.type
|
self.tagtype[tag] = info.type
|
||||||
else:
|
else:
|
||||||
self.tagtype[tag] = 7
|
self.tagtype[tag] = TiffTags.UNDEFINED
|
||||||
if all(isinstance(v, IFDRational) for v in values):
|
if all(isinstance(v, IFDRational) for v in values):
|
||||||
self.tagtype[tag] = TiffTags.RATIONAL
|
self.tagtype[tag] = TiffTags.RATIONAL
|
||||||
elif all(isinstance(v, int) for v in values):
|
elif all(isinstance(v, int) for v in values):
|
||||||
|
@ -872,7 +875,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2):
|
||||||
|
|
||||||
ifd = ImageFileDirectory_v1()
|
ifd = ImageFileDirectory_v1()
|
||||||
ifd[key] = 'Some Data'
|
ifd[key] = 'Some Data'
|
||||||
ifd.tagtype[key] = 2
|
ifd.tagtype[key] = TiffTags.ASCII
|
||||||
print(ifd[key])
|
print(ifd[key])
|
||||||
('Some Data',)
|
('Some Data',)
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,20 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
py3 = sys.version_info.major >= 3
|
py3 = sys.version_info.major >= 3
|
||||||
|
py36 = sys.version_info[0:2] >= (3, 6)
|
||||||
|
|
||||||
if py3:
|
if py3:
|
||||||
def isStringType(t):
|
def isStringType(t):
|
||||||
return isinstance(t, str)
|
return isinstance(t, str)
|
||||||
|
|
||||||
def isPath(f):
|
if py36:
|
||||||
return isinstance(f, (bytes, str))
|
from pathlib import Path
|
||||||
|
|
||||||
|
def isPath(f):
|
||||||
|
return isinstance(f, (bytes, str, Path))
|
||||||
|
else:
|
||||||
|
def isPath(f):
|
||||||
|
return isinstance(f, (bytes, str))
|
||||||
else:
|
else:
|
||||||
def isStringType(t):
|
def isStringType(t):
|
||||||
return isinstance(t, basestring) # noqa: F821
|
return isinstance(t, basestring) # noqa: F821
|
||||||
|
|
Loading…
Reference in New Issue
Block a user