mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 09:14:27 +03:00
Merge branch 'master' into rm-2.7
This commit is contained in:
commit
5006401d0b
|
@ -68,11 +68,14 @@ class TestFeatures(PillowTestCase):
|
|||
lines = out.splitlines()
|
||||
self.assertEqual(lines[0], "-" * 68)
|
||||
self.assertTrue(lines[1].startswith("Pillow "))
|
||||
self.assertEqual(lines[2], "-" * 68)
|
||||
self.assertTrue(lines[3].startswith("Python modules loaded from "))
|
||||
self.assertTrue(lines[4].startswith("Binary modules loaded from "))
|
||||
self.assertEqual(lines[5], "-" * 68)
|
||||
self.assertTrue(lines[6].startswith("Python "))
|
||||
self.assertTrue(lines[2].startswith("Python "))
|
||||
lines = lines[3:]
|
||||
while lines[0].startswith(" "):
|
||||
lines = lines[1:]
|
||||
self.assertEqual(lines[0], "-" * 68)
|
||||
self.assertTrue(lines[1].startswith("Python modules loaded from "))
|
||||
self.assertTrue(lines[2].startswith("Binary modules loaded from "))
|
||||
self.assertEqual(lines[3], "-" * 68)
|
||||
jpeg = (
|
||||
"\n"
|
||||
+ "-" * 68
|
||||
|
|
|
@ -2,6 +2,7 @@ import logging
|
|||
import os
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
from PIL import Image, TiffImagePlugin
|
||||
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION
|
||||
|
||||
|
@ -584,6 +585,9 @@ class TestFileTiff(PillowTestCase):
|
|||
im.load()
|
||||
self.assertFalse(fp.closed)
|
||||
|
||||
# Ignore this UserWarning which triggers for four tags:
|
||||
# "Possibly corrupt EXIF data. Expecting to read 50404352 bytes but..."
|
||||
@pytest.mark.filterwarnings("ignore:Possibly corrupt EXIF data")
|
||||
def test_string_dimension(self):
|
||||
# Assert that an error is raised if one of the dimensions is a string
|
||||
with self.assertRaises(ValueError):
|
||||
|
|
|
@ -16,11 +16,14 @@ class TestMain(TestCase):
|
|||
lines = out.splitlines()
|
||||
self.assertEqual(lines[0], "-" * 68)
|
||||
self.assertTrue(lines[1].startswith("Pillow "))
|
||||
self.assertEqual(lines[2], "-" * 68)
|
||||
self.assertTrue(lines[3].startswith("Python modules loaded from "))
|
||||
self.assertTrue(lines[4].startswith("Binary modules loaded from "))
|
||||
self.assertEqual(lines[5], "-" * 68)
|
||||
self.assertTrue(lines[6].startswith("Python "))
|
||||
self.assertTrue(lines[2].startswith("Python "))
|
||||
lines = lines[3:]
|
||||
while lines[0].startswith(" "):
|
||||
lines = lines[1:]
|
||||
self.assertEqual(lines[0], "-" * 68)
|
||||
self.assertTrue(lines[1].startswith("Python modules loaded from "))
|
||||
self.assertTrue(lines[2].startswith("Binary modules loaded from "))
|
||||
self.assertEqual(lines[3], "-" * 68)
|
||||
jpeg = (
|
||||
os.linesep
|
||||
+ "-" * 68
|
||||
|
|
|
@ -12,29 +12,6 @@ Deprecated features
|
|||
Below are features which are considered deprecated. Where appropriate,
|
||||
a ``DeprecationWarning`` is issued.
|
||||
|
||||
Image.__del__
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 6.1.0
|
||||
|
||||
Implicitly closing the image's underlying file in ``Image.__del__`` has been deprecated.
|
||||
Use a context manager or call ``Image.close()`` instead to close the file in a
|
||||
deterministic way.
|
||||
|
||||
Deprecated:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
im = Image.open("hopper.png")
|
||||
im.save("out.jpg")
|
||||
|
||||
Use instead:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with Image.open("hopper.png") as im:
|
||||
im.save("out.jpg")
|
||||
|
||||
Python 2.7
|
||||
~~~~~~~~~~
|
||||
|
||||
|
@ -96,6 +73,29 @@ Removed features
|
|||
Deprecated features are only removed in major releases after an appropriate
|
||||
period of deprecation has passed.
|
||||
|
||||
Image.__del__
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
*Removed in version 7.0.0.*
|
||||
|
||||
Implicitly closing the image's underlying file in ``Image.__del__`` has been removed.
|
||||
Use a context manager or call ``Image.close()`` instead to close the file in a
|
||||
deterministic way.
|
||||
|
||||
Previous method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
im = Image.open("hopper.png")
|
||||
im.save("out.jpg")
|
||||
|
||||
Use instead:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with Image.open("hopper.png") as im:
|
||||
im.save("out.jpg")
|
||||
|
||||
PILLOW_VERSION constant
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
71
docs/releasenotes/7.0.0.rst
Normal file
71
docs/releasenotes/7.0.0.rst
Normal file
|
@ -0,0 +1,71 @@
|
|||
7.0.0
|
||||
-----
|
||||
|
||||
Backwards Incompatible Changes
|
||||
==============================
|
||||
|
||||
PILLOW_VERSION constant
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``PILLOW_VERSION`` has been removed. Use ``__version__`` instead.
|
||||
|
||||
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 removed from ``ImageQt``. Please upgrade to PyQt5
|
||||
or PySide2.
|
||||
|
||||
Setting the size of TIFF images
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Setting the size of a TIFF image directly (eg. ``im.size = (256, 256)``) throws
|
||||
an error. Use ``Image.resize`` instead.
|
||||
|
||||
|
||||
API Changes
|
||||
===========
|
||||
|
||||
Deprecations
|
||||
^^^^^^^^^^^^
|
||||
|
||||
TODO
|
||||
~~~~
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
API Additions
|
||||
=============
|
||||
|
||||
TODO
|
||||
^^^^
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
Other Changes
|
||||
=============
|
||||
|
||||
Image.__del__
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Implicitly closing the image's underlying file in ``Image.__del__`` has been removed.
|
||||
Use a context manager or call ``Image.close()`` instead to close the file in a
|
||||
deterministic way.
|
||||
|
||||
Previous method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
im = Image.open("hopper.png")
|
||||
im.save("out.jpg")
|
||||
|
||||
Use instead:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with Image.open("hopper.png") as im:
|
||||
im.save("out.jpg")
|
|
@ -6,6 +6,7 @@ Release Notes
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
7.0.0
|
||||
6.2.1
|
||||
6.2.0
|
||||
6.1.0
|
||||
|
|
28
selftest.py
28
selftest.py
|
@ -1,7 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# minimal sanity check
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PIL import Image, features
|
||||
|
@ -161,32 +160,7 @@ if __name__ == "__main__":
|
|||
|
||||
exit_status = 0
|
||||
|
||||
print("-" * 68)
|
||||
print("Pillow", Image.__version__, "TEST SUMMARY ")
|
||||
print("-" * 68)
|
||||
print("Python modules loaded from", os.path.dirname(Image.__file__))
|
||||
print("Binary modules loaded from", os.path.dirname(Image.core.__file__))
|
||||
print("-" * 68)
|
||||
for name, feature in [
|
||||
("pil", "PIL CORE"),
|
||||
("tkinter", "TKINTER"),
|
||||
("freetype2", "FREETYPE2"),
|
||||
("littlecms2", "LITTLECMS2"),
|
||||
("webp", "WEBP"),
|
||||
("transp_webp", "WEBP Transparency"),
|
||||
("webp_mux", "WEBPMUX"),
|
||||
("webp_anim", "WEBP Animation"),
|
||||
("jpg", "JPEG"),
|
||||
("jpg_2000", "OPENJPEG (JPEG2000)"),
|
||||
("zlib", "ZLIB (PNG/ZIP)"),
|
||||
("libtiff", "LIBTIFF"),
|
||||
("raqm", "RAQM (Bidirectional Text)"),
|
||||
]:
|
||||
if features.check(name):
|
||||
print("---", feature, "support ok")
|
||||
else:
|
||||
print("***", feature, "support not installed")
|
||||
print("-" * 68)
|
||||
features.pilinfo(sys.stdout, False)
|
||||
|
||||
# use doctest to make sure the test program behaves as documented!
|
||||
import doctest
|
||||
|
|
|
@ -56,12 +56,6 @@ class DecompressionBombError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class _imaging_not_installed:
|
||||
# module placeholder
|
||||
def __getattr__(self, id):
|
||||
raise ImportError("The _imaging C module is not installed")
|
||||
|
||||
|
||||
# Limit to around a quarter gigabyte for a 24 bit (3 bpp) image
|
||||
MAX_IMAGE_PIXELS = int(1024 * 1024 * 1024 // 4 // 3)
|
||||
|
||||
|
@ -82,7 +76,7 @@ try:
|
|||
)
|
||||
|
||||
except ImportError as v:
|
||||
core = _imaging_not_installed()
|
||||
core = deferred_error(ImportError("The _imaging C module is not installed."))
|
||||
# Explanations for ways that we know we might have an import error
|
||||
if str(v).startswith("Module use of python"):
|
||||
# The _imaging C module is present, but not compiled for
|
||||
|
|
|
@ -54,6 +54,7 @@ features = {
|
|||
"transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY"),
|
||||
"raqm": ("PIL._imagingft", "HAVE_RAQM"),
|
||||
"libjpeg_turbo": ("PIL._imaging", "HAVE_LIBJPEGTURBO"),
|
||||
"libimagequant": ("PIL._imaging", "HAVE_LIBIMAGEQUANT"),
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,7 +93,7 @@ def get_supported():
|
|||
return ret
|
||||
|
||||
|
||||
def pilinfo(out=None):
|
||||
def pilinfo(out=None, supported_formats=True):
|
||||
if out is None:
|
||||
out = sys.stdout
|
||||
|
||||
|
@ -100,6 +101,10 @@ def pilinfo(out=None):
|
|||
|
||||
print("-" * 68, file=out)
|
||||
print("Pillow {}".format(PIL.__version__), file=out)
|
||||
py_version = sys.version.splitlines()
|
||||
print("Python {}".format(py_version[0].strip()), file=out)
|
||||
for py_version in py_version[1:]:
|
||||
print(" {}".format(py_version.strip()), file=out)
|
||||
print("-" * 68, file=out)
|
||||
print(
|
||||
"Python modules loaded from {}".format(os.path.dirname(Image.__file__)),
|
||||
|
@ -111,12 +116,6 @@ def pilinfo(out=None):
|
|||
)
|
||||
print("-" * 68, file=out)
|
||||
|
||||
v = sys.version.splitlines()
|
||||
print("Python {}".format(v[0].strip()), file=out)
|
||||
for v in v[1:]:
|
||||
print(" {}".format(v.strip()), file=out)
|
||||
print("-" * 68, file=out)
|
||||
|
||||
for name, feature in [
|
||||
("pil", "PIL CORE"),
|
||||
("tkinter", "TKINTER"),
|
||||
|
@ -131,6 +130,7 @@ def pilinfo(out=None):
|
|||
("zlib", "ZLIB (PNG/ZIP)"),
|
||||
("libtiff", "LIBTIFF"),
|
||||
("raqm", "RAQM (Bidirectional Text)"),
|
||||
("libimagequant", "LIBIMAGEQUANT (Quantization method)"),
|
||||
]:
|
||||
if check(name):
|
||||
print("---", feature, "support ok", file=out)
|
||||
|
@ -138,30 +138,33 @@ def pilinfo(out=None):
|
|||
print("***", feature, "support not installed", file=out)
|
||||
print("-" * 68, file=out)
|
||||
|
||||
extensions = collections.defaultdict(list)
|
||||
for ext, i in Image.EXTENSION.items():
|
||||
extensions[i].append(ext)
|
||||
if supported_formats:
|
||||
extensions = collections.defaultdict(list)
|
||||
for ext, i in Image.EXTENSION.items():
|
||||
extensions[i].append(ext)
|
||||
|
||||
for i in sorted(Image.ID):
|
||||
line = "{}".format(i)
|
||||
if i in Image.MIME:
|
||||
line = "{} {}".format(line, Image.MIME[i])
|
||||
print(line, file=out)
|
||||
for i in sorted(Image.ID):
|
||||
line = "{}".format(i)
|
||||
if i in Image.MIME:
|
||||
line = "{} {}".format(line, Image.MIME[i])
|
||||
print(line, file=out)
|
||||
|
||||
if i in extensions:
|
||||
print("Extensions: {}".format(", ".join(sorted(extensions[i]))), file=out)
|
||||
if i in extensions:
|
||||
print(
|
||||
"Extensions: {}".format(", ".join(sorted(extensions[i]))), file=out
|
||||
)
|
||||
|
||||
features = []
|
||||
if i in Image.OPEN:
|
||||
features.append("open")
|
||||
if i in Image.SAVE:
|
||||
features.append("save")
|
||||
if i in Image.SAVE_ALL:
|
||||
features.append("save_all")
|
||||
if i in Image.DECODERS:
|
||||
features.append("decode")
|
||||
if i in Image.ENCODERS:
|
||||
features.append("encode")
|
||||
features = []
|
||||
if i in Image.OPEN:
|
||||
features.append("open")
|
||||
if i in Image.SAVE:
|
||||
features.append("save")
|
||||
if i in Image.SAVE_ALL:
|
||||
features.append("save_all")
|
||||
if i in Image.DECODERS:
|
||||
features.append("decode")
|
||||
if i in Image.ENCODERS:
|
||||
features.append("encode")
|
||||
|
||||
print("Features: {}".format(", ".join(features)), file=out)
|
||||
print("-" * 68, file=out)
|
||||
print("Features: {}".format(", ".join(features)), file=out)
|
||||
print("-" * 68, file=out)
|
||||
|
|
|
@ -3892,6 +3892,12 @@ setup_module(PyObject* m) {
|
|||
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_False);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBIMAGEQUANT
|
||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_True);
|
||||
#else
|
||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_False);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
/* zip encoding strategies */
|
||||
PyModule_AddIntConstant(m, "DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY);
|
||||
|
|
|
@ -845,8 +845,6 @@ font_render(FontObject* self, PyObject* args)
|
|||
|
||||
bitmap = bitmap_glyph->bitmap;
|
||||
left = bitmap_glyph->left;
|
||||
|
||||
FT_Done_Glyph(glyph);
|
||||
} else {
|
||||
bitmap = glyph_slot->bitmap;
|
||||
left = glyph_slot->bitmap_left;
|
||||
|
@ -908,6 +906,9 @@ font_render(FontObject* self, PyObject* args)
|
|||
}
|
||||
x += glyph_info[i].x_advance;
|
||||
y -= glyph_info[i].y_advance;
|
||||
if (stroker != NULL) {
|
||||
FT_Done_Glyph(glyph);
|
||||
}
|
||||
}
|
||||
|
||||
FT_Stroker_Done(stroker);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import os
|
||||
|
||||
SF_MIRROR = "https://iweb.dl.sourceforge.net"
|
||||
PILLOW_DEPENDS_DIR = "C:\\pillow-depends\\"
|
||||
|
||||
pythons = {
|
||||
# for AppVeyor
|
||||
|
|
Loading…
Reference in New Issue
Block a user