diff --git a/PIL/ImageWin.py b/PIL/ImageWin.py index cc4dced97..d8398e92b 100644 --- a/PIL/ImageWin.py +++ b/PIL/ImageWin.py @@ -182,14 +182,6 @@ class Dib(object): """ return self.image.tobytes() - def fromstring(self, *args, **kw): - raise NotImplementedError("fromstring() has been removed. " + - "Please use frombytes() instead.") - - def tostring(self, *args, **kw): - raise NotImplementedError("tostring() has been removed. " + - "Please use tobytes() instead.") - class Window(object): """Create a Window with the given title size.""" diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index bb2816c13..8890ed9ee 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -127,7 +127,7 @@ def APP(self, marker): dpi = x_resolution[0] / x_resolution[1] except TypeError: dpi = x_resolution - if resolution_unit == 3: # cm + if resolution_unit == 3: # cm # 1 dpcm = 2.54 dpi dpi *= 2.54 self.info["dpi"] = dpi, dpi @@ -423,7 +423,8 @@ def _fixup_dict(src_dict): try: if len(value) == 1 and not isinstance(value, dict): return value[0] - except: pass + except: + pass return value return {k: _fixup(v) for k, v in src_dict.items()} @@ -554,7 +555,6 @@ RAWMODE = { "1": "L", "L": "L", "RGB": "RGB", - "RGBA": "RGB", "RGBX": "RGB", "CMYK": "CMYK;I", # assume adobe conventions "YCbCr": "YCbCr", @@ -603,14 +603,6 @@ def _save(im, fp, filename): except KeyError: raise IOError("cannot write mode %s as JPEG" % im.mode) - if im.mode == 'RGBA': - warnings.warn( - 'You are saving RGBA image as JPEG. The alpha channel will be ' - 'discarded. This conversion is deprecated and will be disabled ' - 'in Pillow 3.7. Please, convert the image to RGB explicitly.', - DeprecationWarning - ) - info = im.encoderinfo dpi = [int(round(x)) for x in info.get("dpi", (0, 0))] @@ -705,8 +697,8 @@ def _save(im, fp, filename): # "progressive" is the official name, but older documentation # says "progression" # FIXME: issue a warning if the wrong form is used (post-1.1.7) - progressive = info.get("progressive", False) or\ - info.get("progression", False) + progressive = (info.get("progressive", False) or + info.get("progression", False)) optimize = info.get("optimize", False) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index f9709e83b..ad1694d2f 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -242,6 +242,7 @@ def _limit_rational(val, max_val): n_d = IFDRational(1 / val if inv else val).limit_rational(max_val) return n_d[::-1] if inv else n_d + ## # Wrapper for TIFF IFDs. @@ -462,15 +463,6 @@ class ImageFileDirectory_v2(collections.MutableMapping): def __str__(self): return str(dict(self)) - def as_dict(self): - """Return a dictionary of the image's tags. - - .. deprecated:: 3.0.0 - """ - warnings.warn("as_dict() is deprecated. " + - "Please use dict(ifd) instead.", DeprecationWarning) - return dict(self) - def named(self): """ :returns: dict of name|key: value @@ -535,7 +527,8 @@ class ImageFileDirectory_v2(collections.MutableMapping): self.tagtype[tag] = 2 if self.tagtype[tag] == 7 and bytes is not str: - values = [value.encode("ascii", 'replace') if isinstance(value, str) else value] + values = [value.encode("ascii", 'replace') if isinstance( + value, str) else value] values = tuple(info.cvt_enum(value) for value in values) @@ -588,9 +581,13 @@ class ImageFileDirectory_v2(collections.MutableMapping): b"".join(self._pack(fmt, value) for value in values)) list(map(_register_basic, - [(3, "H", "short"), (4, "L", "long"), - (6, "b", "signed byte"), (8, "h", "signed short"), - (9, "l", "signed long"), (11, "f", "float"), (12, "d", "double")])) + [(3, "H", "short"), + (4, "L", "long"), + (6, "b", "signed byte"), + (8, "h", "signed short"), + (9, "l", "signed long"), + (11, "f", "float"), + (12, "d", "double")])) @_register_loader(1, 1) # Basic type, except for the legacy API. def load_byte(self, data, legacy_api=True): @@ -662,7 +659,8 @@ class ImageFileDirectory_v2(collections.MutableMapping): try: for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]): - tag, typ, count, data = self._unpack("HHL4s", self._ensure_read(fp, 12)) + tag, typ, count, data = self._unpack("HHL4s", + self._ensure_read(fp, 12)) if DEBUG: tagname = TiffTags.lookup(tag).name typname = TYPES.get(typ, "unknown") @@ -690,8 +688,8 @@ class ImageFileDirectory_v2(collections.MutableMapping): if len(data) != size: warnings.warn("Possibly corrupt EXIF data. " - "Expecting to read %d bytes but only got %d. " - "Skipping tag %s" % (size, len(data), tag)) + "Expecting to read %d bytes but only got %d." + " Skipping tag %s" % (size, len(data), tag)) continue if not data: @@ -750,7 +748,8 @@ class ImageFileDirectory_v2(collections.MutableMapping): if len(data) <= 4: entries.append((tag, typ, count, data.ljust(4, b"\0"), b"")) else: - entries.append((tag, typ, count, self._pack("L", offset), data)) + entries.append((tag, typ, count, self._pack("L", offset), + data)) offset += (len(data) + 1) // 2 * 2 # pad to word # update strip offset data to point beyond auxiliary data @@ -779,6 +778,7 @@ class ImageFileDirectory_v2(collections.MutableMapping): return offset + ImageFileDirectory_v2._load_dispatch = _load_dispatch ImageFileDirectory_v2._write_dispatch = _write_dispatch for idx, name in TYPES.items(): @@ -1178,7 +1178,8 @@ class TiffImageFile(ImageFile.ImageFile): self.info["dpi"] = xres * 2.54, yres * 2.54 elif resunit is None: # used to default to 1, but now 2) self.info["dpi"] = xres, yres - # For backward compatibility, we also preserve the old behavior. + # For backward compatibility, + # we also preserve the old behavior self.info["resolution"] = xres, yres else: # No absolute unit of measurement self.info["resolution"] = xres, yres @@ -1294,6 +1295,8 @@ class TiffImageFile(ImageFile.ImageFile): if self.mode == "P": palette = [o8(b // 256) for b in self.tag_v2[COLORMAP]] self.palette = ImagePalette.raw("RGB;L", b"".join(palette)) + + # # -------------------------------------------------------------------- # Write TIFF files @@ -1682,13 +1685,10 @@ class AppendingTiffWriter: def fixIFD(self): numTags = self.readShort() - # trace("fixing IFD at %X; number of tags: %u (0x%X)", self.f.tell()-2, - # numTags, numTags) for i in range(numTags): - tag, fieldType, count = struct.unpack(self.tagFormat, self.f.read(8)) - # trace(" at %X: tag %u (0x%X), type %u, count %u", self.f.tell()-8, - # tag, tag, fieldType, count) + tag, fieldType, count = struct.unpack(self.tagFormat, + self.f.read(8)) fieldSize = self.fieldSizes[fieldType] totalSize = fieldSize * count @@ -1756,6 +1756,7 @@ def _save_all(im, fp, filename): finally: im.seek(cur_idx) + # # -------------------------------------------------------------------- # Register diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 6e5758857..6858e52f5 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -476,17 +476,11 @@ class TestFileJpeg(PillowTestCase): img.save(out, "JPEG") def test_save_wrong_modes(self): - out = BytesIO() - for mode in ['LA', 'La', 'RGBa', 'P']: - img = Image.new(mode, (20, 20)) - self.assertRaises(IOError, img.save, out, "JPEG") - - def test_save_modes_with_warnings(self): # ref https://github.com/python-pillow/Pillow/issues/2005 out = BytesIO() - for mode in ['RGBA']: + for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']: img = Image.new(mode, (20, 20)) - self.assert_warning(DeprecationWarning, img.save, out, "JPEG") + self.assertRaises(IOError, img.save, out, "JPEG") def test_save_tiff_with_dpi(self): # Arrange diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index ebcc6dd35..403396f64 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -6,6 +6,7 @@ import sys from helper import unittest, PillowTestCase, hopper, py3 from PIL import Image, TiffImagePlugin +from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION, RESOLUTION_UNIT logger = logging.getLogger(__name__) @@ -77,7 +78,6 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.mode, 'RGB') def test_xyres_tiff(self): - from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION filename = "Tests/images/pil168.tif" im = Image.open(filename) @@ -94,7 +94,6 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.info['dpi'], (72., 72.)) def test_xyres_fallback_tiff(self): - from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION, RESOLUTION_UNIT filename = "Tests/images/compression.tif" im = Image.open(filename) @@ -112,7 +111,6 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.info['dpi'], (100., 100.)) def test_int_resolution(self): - from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION filename = "Tests/images/pil168.tif" im = Image.open(filename) @@ -123,7 +121,6 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.info['dpi'], (71., 71.)) def test_save_setting_missing_resolution(self): - from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION b = BytesIO() Image.open("Tests/images/10ct_32bit_128.tiff").save( b, format="tiff", resolution=123.45) @@ -274,16 +271,6 @@ class TestFileTiff(PillowTestCase): # Assert self.assertIsInstance(ret, str) - def test_as_dict_deprecation(self): - # Arrange - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - - self.assert_warning(DeprecationWarning, im.tag_v2.as_dict) - self.assert_warning(DeprecationWarning, im.tag.as_dict) - self.assertEqual(dict(im.tag_v2), im.tag_v2.as_dict()) - self.assertEqual(dict(im.tag), im.tag.as_dict()) - def test_dict(self): # Arrange filename = "Tests/images/pil136.tiff" @@ -457,8 +444,8 @@ class TestFileTiff(PillowTestCase): def test_saving_icc_profile(self): # Tests saving TIFF with icc_profile set. # At the time of writing this will only work for non-compressed tiffs - # as libtiff does not support embedded ICC profiles, ImageFile._save(..) - # however does. + # as libtiff does not support embedded ICC profiles, + # ImageFile._save(..) however does. im = Image.new('RGB', (1, 1)) im.info['icc_profile'] = 'Dummy value' @@ -495,8 +482,6 @@ class TestFileTiff(PillowTestCase): im.load() self.assertFalse(fp.closed) - - @unittest.skipUnless(sys.platform.startswith('win32'), "Windows only") class TestFileTiffW32(PillowTestCase): def test_fd_leak(self): @@ -521,5 +506,6 @@ class TestFileTiffW32(PillowTestCase): # and close should have closed the mmap os.remove(tmpfile) + if __name__ == '__main__': unittest.main() diff --git a/Tests/test_imagewin.py b/Tests/test_imagewin.py index d802b1fb2..70bf28247 100644 --- a/Tests/test_imagewin.py +++ b/Tests/test_imagewin.py @@ -107,15 +107,6 @@ class TestImageWinDib(PillowTestCase): # Confirm they're the same self.assertEqual(dib1.tobytes(), dib2.tobytes()) - def test_removed_methods(self): - # Arrange - im = hopper() - dib = ImageWin.Dib(im) - - # Act/Assert - self.assertRaises(Exception, dib.tostring) - self.assertRaises(Exception, dib.fromstring) - if __name__ == '__main__': unittest.main() diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 3f1bb7b8d..49cbc2177 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -270,24 +270,3 @@ Methods :param text: Text to be measured. :param font: An :py:class:`~PIL.ImageFont.ImageFont` instance. :param spacing: The number of pixels between lines. - -Legacy API ----------- - -The :py:class:`~PIL.ImageDraw.Draw` class contains a constructor and a number -of methods which are provided for backwards compatibility only. For this to -work properly, you should either use options on the drawing primitives, or -these methods. Do not mix the old and new calling conventions. - - -.. py:function:: PIL.ImageDraw.ImageDraw(image) - - :rtype: :py:class:`~PIL.ImageDraw.Draw` - -.. py:method:: PIL.ImageDraw.Draw.setfont(font) - - .. deprecated:: 1.1.5 - - Sets the default font to use for the text method. - - :param font: An :py:class:`~PIL.ImageFont.ImageFont` instance. diff --git a/docs/releasenotes/4.2.0.rst b/docs/releasenotes/4.2.0.rst new file mode 100644 index 000000000..e405ab58b --- /dev/null +++ b/docs/releasenotes/4.2.0.rst @@ -0,0 +1,11 @@ +4.2.0 +----- + +Removed Deprecated Items +======================== + +Several deprecated items have been removed. + +* The methods :py:meth:`PIL.ImageWin.Dib.fromstring`, :py:meth:`PIL.ImageWin.Dib.tostring` and :py:meth:`PIL.TiffImagePlugin.ImageFileDirectory_v2.as_dict` have been removed. + +* Before Pillow 4.2.0, attempting to save an RGBA image as JPEG would discard the alpha channel. From Pillow 3.4.0, a deprecation warning was shown. From Pillow 4.2.0, the deprecation warning is removed and an :py:exc:`IOError` is raised. diff --git a/docs/releasenotes/index.rst b/docs/releasenotes/index.rst index 27851ec7a..624c727a9 100644 --- a/docs/releasenotes/index.rst +++ b/docs/releasenotes/index.rst @@ -6,6 +6,7 @@ Release Notes .. toctree:: :maxdepth: 2 + 4.2.0 4.1.1 4.1.0 4.0.0