diff --git a/PIL/Image.py b/PIL/Image.py index 62ae9b5ac..28289d0d9 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -28,8 +28,11 @@ from __future__ import print_function from PIL import VERSION, PILLOW_VERSION, _plugins +import logging import warnings +logger = logging.getLogger(__name__) + class DecompressionBombWarning(RuntimeWarning): pass @@ -138,11 +141,6 @@ def isImageType(t): """ return hasattr(t, "im") -# -# Debug level - -DEBUG = 0 - # # Constants (also defined in _imagingmodule.c!) @@ -387,13 +385,10 @@ def init(): for plugin in _plugins: try: - if DEBUG: - print("Importing %s" % plugin) + logger.debug("Importing %s", plugin) __import__("PIL.%s" % plugin, globals(), locals(), []) - except ImportError: - if DEBUG: - print("Image: failed to import", end=' ') - print(plugin, ":", sys.exc_info()[1]) + except ImportError as e: + logger.debug("Image: failed to import %s: %s", plugin, e) if OPEN or SAVE: _initialized = 2 @@ -555,8 +550,7 @@ class Image(object): try: self.fp.close() except Exception as msg: - if DEBUG: - print("Error closing: %s" % msg) + logger.debug("Error closing: %s" % msg) # Instead of simply setting to None, we're setting up a # deferred error that will better explain that the core image @@ -2307,9 +2301,7 @@ def open(fp, mode="r"): _decompression_bomb_check(im.size) return im except (SyntaxError, IndexError, TypeError, struct.error): - # import traceback - # traceback.print_exc() - pass + logger.debug("", exc_info=True) if init(): @@ -2322,9 +2314,7 @@ def open(fp, mode="r"): _decompression_bomb_check(im.size) return im except (SyntaxError, IndexError, TypeError, struct.error): - # import traceback - # traceback.print_exc() - pass + logger.debug("", exc_info=True) raise IOError("cannot identify image file %r" % (filename if filename else fp)) diff --git a/PIL/ImageFile.py b/PIL/ImageFile.py index cc1d73f09..52d21e1e8 100644 --- a/PIL/ImageFile.py +++ b/PIL/ImageFile.py @@ -30,10 +30,13 @@ from PIL import Image from PIL._util import isPath import io +import logging import os import sys import traceback +logger = logging.getLogger(__name__) + MAXBLOCK = 65536 SAFEBLOCK = 1024*1024 @@ -95,21 +98,11 @@ class ImageFile(Image.Image): try: self._open() - except IndexError as v: # end of data - if Image.DEBUG > 1: - traceback.print_exc() - raise SyntaxError(v) - except TypeError as v: # end of data (ord) - if Image.DEBUG > 1: - traceback.print_exc() - raise SyntaxError(v) - except KeyError as v: # unsupported mode - if Image.DEBUG > 1: - traceback.print_exc() - raise SyntaxError(v) - except EOFError as v: # got header but not the first frame - if Image.DEBUG > 1: - traceback.print_exc() + except (IndexError, # end of data + TypeError, # end of data (ord) + KeyError, # unsupported mode + EOFError) as v: # got header but not the first frame + logger.exception("%s") raise SyntaxError(v) if not self.mode or self.size[0] <= 0: diff --git a/PIL/PcxImagePlugin.py b/PIL/PcxImagePlugin.py index 40fafa0dc..906c38a35 100644 --- a/PIL/PcxImagePlugin.py +++ b/PIL/PcxImagePlugin.py @@ -27,8 +27,11 @@ from __future__ import print_function +import logging from PIL import Image, ImageFile, ImagePalette, _binary +logger = logging.getLogger(__name__) + i8 = _binary.i8 i16 = _binary.i16le o8 = _binary.o8 @@ -59,17 +62,15 @@ class PcxImageFile(ImageFile.ImageFile): bbox = i16(s, 4), i16(s, 6), i16(s, 8)+1, i16(s, 10)+1 if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]: raise SyntaxError("bad PCX image size") - if Image.DEBUG: - print("BBox: %s %s %s %s" % bbox) + logger.debug("BBox: %s %s %s %s", *bbox) # format version = i8(s[1]) bits = i8(s[3]) planes = i8(s[65]) stride = i16(s, 66) - if Image.DEBUG: - print("PCX version %s, bits %s, planes %s, stride %s" % - (version, bits, planes, stride)) + logger.debug("PCX version %s, bits %s, planes %s, stride %s", + version, bits, planes, stride) self.info["dpi"] = i16(s, 12), i16(s, 14) @@ -107,8 +108,7 @@ class PcxImageFile(ImageFile.ImageFile): self.size = bbox[2]-bbox[0], bbox[3]-bbox[1] bbox = (0, 0) + self.size - if Image.DEBUG: - print("size: %sx%s" % self.size) + logger.debug("size: %sx%s", *self.size) self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))] @@ -144,9 +144,8 @@ def _save(im, fp, filename, check=0): # Ideally it should be passed in in the state, but the bytes value # gets overwritten. - if Image.DEBUG: - print("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % ( - im.size[0], bits, stride)) + logger.debug("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d", + im.size[0], bits, stride) # under windows, we could determine the current screen size with # "Image.core.display_mode()[1]", but I think that's overkill... diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index 214ff9385..9fcc9fe4e 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -35,10 +35,13 @@ from __future__ import print_function __version__ = "0.9" +import logging import re +import zlib from PIL import Image, ImageFile, ImagePalette, _binary -import zlib + +logger = logging.getLogger(__name__) i8 = _binary.i8 i16 = _binary.i16be @@ -129,8 +132,7 @@ class ChunkStream(object): def call(self, cid, pos, length): "Call the appropriate chunk handler" - if Image.DEBUG: - print("STREAM", cid, pos, length) + logger.debug("STREAM %s %s %s", cid, pos, length) return getattr(self, "chunk_" + cid.decode('ascii'))(pos, length) def crc(self, cid, data): @@ -293,9 +295,8 @@ class PngStream(ChunkStream): # Compression method 1 byte (0) # Compressed profile n bytes (zlib with deflate compression) i = s.find(b"\0") - if Image.DEBUG: - print("iCCP profile name", s[:i]) - print("Compression method", i8(s[i])) + logger.debug("iCCP profile name %s", s[:i]) + logger.debug("Compression method %s", i8(s[i])) comp_method = i8(s[i]) if comp_method != 0: raise SyntaxError("Unknown compression method %s in iCCP chunk" % @@ -507,8 +508,7 @@ class PngImageFile(ImageFile.ImageFile): except EOFError: break except AttributeError: - if Image.DEBUG: - print(cid, pos, length, "(unknown)") + logger.debug("%s %s %s (unknown)", cid, pos, length) s = ImageFile._safe_read(self.fp, length) self.png.crc(cid, s) diff --git a/PIL/PyAccess.py b/PIL/PyAccess.py index 4924facd5..cb4f00cad 100644 --- a/PIL/PyAccess.py +++ b/PIL/PyAccess.py @@ -22,10 +22,14 @@ from __future__ import print_function -from cffi import FFI +import logging import sys -DEBUG = 0 +from cffi import FFI + + +logger = logging.getLogger(__name__) + defs = """ struct Pixel_RGBA { @@ -50,8 +54,7 @@ class PyAccess(object): self.xsize = vals['xsize'] self.ysize = vals['ysize'] - if DEBUG: - print(vals) + logger.debug("%s", vals) self._post_init() def _post_init(self): @@ -305,11 +308,9 @@ else: def new(img, readonly=False): access_type = mode_map.get(img.mode, None) if not access_type: - if DEBUG: - print("PyAccess Not Implemented: %s" % img.mode) + logger.debug("PyAccess Not Implemented: %s", img.mode) return None - if DEBUG: - print("New PyAccess: %s" % img.mode) + logger.debug("New PyAccess: %s", img.mode) return access_type(img, readonly) # End of file diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 99c890459..9d6e56abf 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -42,6 +42,7 @@ from __future__ import print_function __version__ = "1.3.5" +DEBUG = False # Needs to be merged with the new logging approach. from PIL import Image, ImageFile from PIL import ImagePalette @@ -434,7 +435,7 @@ class ImageFileDirectory(collections.MutableMapping): tag, typ = i16(ifd), i16(ifd, 2) - if Image.DEBUG: + if DEBUG: from PIL import TiffTags tagname = TiffTags.TAGS.get(tag, "unknown") typname = TiffTags.TYPES.get(typ, "unknown") @@ -444,7 +445,7 @@ class ImageFileDirectory(collections.MutableMapping): try: dispatch = self.load_dispatch[typ] except KeyError: - if Image.DEBUG: + if DEBUG: print("- unsupported type", typ) continue # ignore unsupported type @@ -455,10 +456,10 @@ class ImageFileDirectory(collections.MutableMapping): # Get and expand tag value if size > 4: here = fp.tell() - if Image.DEBUG: + if DEBUG: print("Tag Location: %s" % here) fp.seek(i32(ifd, 8)) - if Image.DEBUG: + if DEBUG: print("Data Location: %s" % fp.tell()) data = ImageFile._safe_read(fp, size) fp.seek(here) @@ -474,7 +475,7 @@ class ImageFileDirectory(collections.MutableMapping): self.tagdata[tag] = data self.tagtype[tag] = typ - if Image.DEBUG: + if DEBUG: if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP): print("- value: " % size) @@ -517,8 +518,8 @@ class ImageFileDirectory(collections.MutableMapping): if tag in self.tagtype: typ = self.tagtype[tag] - if Image.DEBUG: - print("Tag %s, Type: %s, Value: %s" % (tag, typ, value)) + if DEBUG: + print ("Tag %s, Type: %s, Value: %s" % (tag, typ, value)) if typ == 1: # byte data @@ -571,7 +572,7 @@ class ImageFileDirectory(collections.MutableMapping): else: data = b"".join(map(o32, value)) - if Image.DEBUG: + if DEBUG: from PIL import TiffTags tagname = TiffTags.TAGS.get(tag, "unknown") typname = TiffTags.TYPES.get(typ, "unknown") @@ -608,7 +609,7 @@ class ImageFileDirectory(collections.MutableMapping): # pass 2: write directory to file for tag, typ, count, value, data in directory: - if Image.DEBUG > 1: + if DEBUG > 1: print(tag, typ, count, repr(value), repr(data)) fp.write(o16(tag) + o16(typ) + o32(count) + value) @@ -652,10 +653,10 @@ class TiffImageFile(ImageFile.ImageFile): self._n_frames = None self._is_animated = None - if Image.DEBUG: - print("*** TiffImageFile._open ***") - print("- __first:", self.__first) - print("- ifh: ", ifh) + if DEBUG: + print ("*** TiffImageFile._open ***") + print ("- __first:", self.__first) + print ("- ifh: ", ifh) # and load the first frame self._seek(0) @@ -700,7 +701,7 @@ class TiffImageFile(ImageFile.ImageFile): while len(self._frame_pos) <= frame: if not self.__next: raise EOFError("no more images in TIFF file") - if Image.DEBUG: + if DEBUG: print("Seeking to frame %s, on frame %s, __next %s, location: %s" % (frame, self.__frame, self.__next, self.fp.tell())) # reset python3 buffered io handle in case fp @@ -708,7 +709,7 @@ class TiffImageFile(ImageFile.ImageFile): self.fp.tell() self.fp.seek(self.__next) self._frame_pos.append(self.__next) - if Image.DEBUG: + if DEBUG: print("Loading tags, location: %s" % self.fp.tell()) self.tag.load(self.fp) self.__next = self.tag.next @@ -786,20 +787,20 @@ class TiffImageFile(ImageFile.ImageFile): # Rearranging for supporting byteio items, since they have a fileno # that returns an IOError if there's no underlying fp. Easier to # deal with here by reordering. - if Image.DEBUG: - print("have getvalue. just sending in a string from getvalue") + if DEBUG: + print ("have getvalue. just sending in a string from getvalue") n, err = decoder.decode(self.fp.getvalue()) elif hasattr(self.fp, "fileno"): # we've got a actual file on disk, pass in the fp. - if Image.DEBUG: - print("have fileno, calling fileno version of the decoder.") + if DEBUG: + print ("have fileno, calling fileno version of the decoder.") self.fp.seek(0) # 4 bytes, otherwise the trace might error out n, err = decoder.decode(b"fpfp") else: # we have something else. - if Image.DEBUG: - print("don't have fileno or getvalue. just reading") + if DEBUG: + print ("don't have fileno or getvalue. just reading") # UNDONE -- so much for that buffer size thing. n, err = decoder.decode(self.fp.read()) @@ -836,7 +837,7 @@ class TiffImageFile(ImageFile.ImageFile): fillorder = getscalar(FILLORDER, 1) - if Image.DEBUG: + if DEBUG: print("*** Summary ***") print("- compression:", self._compression) print("- photometric_interpretation:", photo) @@ -848,7 +849,7 @@ class TiffImageFile(ImageFile.ImageFile): ysize = getscalar(IMAGELENGTH) self.size = xsize, ysize - if Image.DEBUG: + if DEBUG: print("- size:", self.size) format = getscalar(SAMPLEFORMAT, 1) @@ -859,16 +860,16 @@ class TiffImageFile(ImageFile.ImageFile): self.tag.get(BITSPERSAMPLE, (1,)), self.tag.get(EXTRASAMPLES, ()) ) - if Image.DEBUG: + if DEBUG: print("format key:", key) try: self.mode, rawmode = OPEN_INFO[key] except KeyError: - if Image.DEBUG: + if DEBUG: print("- unsupported format") raise SyntaxError("unknown pixel mode") - if Image.DEBUG: + if DEBUG: print("- raw mode:", rawmode) print("- pil mode:", self.mode) @@ -908,7 +909,7 @@ class TiffImageFile(ImageFile.ImageFile): "tiff_sgilog", "tiff_sgilog24", "tiff_raw_16"]: - # if Image.DEBUG: + # if DEBUG: # print "Activating g4 compression for whole file" # Decoder expects entire file as one tile. @@ -949,7 +950,7 @@ class TiffImageFile(ImageFile.ImageFile): self.tag.get(BITSPERSAMPLE, (1,)), self.tag.get(EXTRASAMPLES, ()) ) - if Image.DEBUG: + if DEBUG: print("format key:", key) # this should always work, since all the # fillorder==2 modes have a corresponding @@ -978,8 +979,8 @@ class TiffImageFile(ImageFile.ImageFile): (self._compression, (0, min(y, ysize), w, min(y+h, ysize)), offsets[i], a)) - if Image.DEBUG: - print("tiles: ", self.tile) + if DEBUG: + print ("tiles: ", self.tile) y = y + h if y >= self.size[1]: x = y = 0 @@ -1007,7 +1008,7 @@ class TiffImageFile(ImageFile.ImageFile): l += 1 a = None else: - if Image.DEBUG: + if DEBUG: print("- unsupported data organization") raise SyntaxError("unknown data organization") @@ -1088,7 +1089,7 @@ def _save(im, fp, filename): # write any arbitrary tags passed in as an ImageFileDirectory info = im.encoderinfo.get("tiffinfo", {}) - if Image.DEBUG: + if DEBUG: print("Tiffinfo Keys: %s" % info.keys) keys = list(info.keys()) for key in keys: @@ -1163,9 +1164,9 @@ def _save(im, fp, filename): ifd[COMPRESSION] = COMPRESSION_INFO_REV.get(compression, 1) if libtiff: - if Image.DEBUG: - print("Saving using libtiff encoder") - print(ifd.items()) + if DEBUG: + print ("Saving using libtiff encoder") + print (ifd.items()) _fp = 0 if hasattr(fp, "fileno"): try: @@ -1221,8 +1222,8 @@ def _save(im, fp, filename): # int or similar atts[k] = v - if Image.DEBUG: - print(atts) + if DEBUG: + print (atts) # libtiff always expects the bytes in native order. # we're storing image byte order. So, if the rawmode diff --git a/Scripts/pilfile.py b/Scripts/pilfile.py index b954114ac..dab240e2f 100644 --- a/Scripts/pilfile.py +++ b/Scripts/pilfile.py @@ -21,6 +21,7 @@ from __future__ import print_function import getopt import glob +import logging import sys from PIL import Image @@ -42,6 +43,7 @@ except getopt.error as v: sys.exit(1) verbose = quiet = verify = 0 +logging_level = "WARNING" for o, a in opt: if o == "-f": @@ -58,7 +60,9 @@ for o, a in opt: elif o == "-v": verify = 1 elif o == "-D": - Image.DEBUG += 1 + logging_level = "DEBUG" + +logging.basicConfig(level=logging_level) def globfix(files): diff --git a/Scripts/player.py b/Scripts/player.py index 43877415a..ac9eb817f 100644 --- a/Scripts/player.py +++ b/Scripts/player.py @@ -15,9 +15,6 @@ from PIL import Image, ImageTk import sys -Image.DEBUG = 0 - - # -------------------------------------------------------------------- # an image animation player diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 896038b9d..8d5b383a9 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -1,11 +1,14 @@ from __future__ import print_function from helper import unittest, PillowTestCase, hopper, py3 -import os import io +import logging +import os from PIL import Image, TiffImagePlugin +logger = logging.getLogger(__name__) + class LibTiffTestCase(PillowTestCase): @@ -231,7 +234,6 @@ class TestFileLibTiff(LibTiffTestCase): """ Are we generating the same interpretation of the image as Imagemagick is? """ TiffImagePlugin.READ_LIBTIFF = True - # Image.DEBUG = True im = Image.open('Tests/images/12bit.cropped.tif') im.load() TiffImagePlugin.READ_LIBTIFF = False @@ -243,14 +245,8 @@ class TestFileLibTiff(LibTiffTestCase): im2 = Image.open('Tests/images/12in16bit.tif') - if Image.DEBUG: - print(im.getpixel((0, 0))) - print(im.getpixel((0, 1))) - print(im.getpixel((0, 2))) - - print(im2.getpixel((0, 0))) - print(im2.getpixel((0, 1))) - print(im2.getpixel((0, 2))) + logger.debug("%s", [img.getpixel((0, idx)) + for img in [im, im2] for idx in range(3)]) self.assert_image_equal(im, im2) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 1a1bbaef7..98b346016 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -1,9 +1,12 @@ from __future__ import print_function +import logging +import struct + from helper import unittest, PillowTestCase, hopper, py3 from PIL import Image, TiffImagePlugin -import struct +logger = logging.getLogger(__name__) class TestFileTiff(PillowTestCase): @@ -118,7 +121,6 @@ class TestFileTiff(PillowTestCase): """ Are we generating the same interpretation of the image as Imagemagick is? """ - # Image.DEBUG = True im = Image.open('Tests/images/12bit.cropped.tif') # to make the target -- @@ -129,14 +131,8 @@ class TestFileTiff(PillowTestCase): im2 = Image.open('Tests/images/12in16bit.tif') - if Image.DEBUG: - print(im.getpixel((0, 0))) - print(im.getpixel((0, 1))) - print(im.getpixel((0, 2))) - - print(im2.getpixel((0, 0))) - print(im2.getpixel((0, 1))) - print(im2.getpixel((0, 2))) + logger.debug("%s", [img.getpixel((0, idx)) + for img in [im, im2] for idx in range(3)]) self.assert_image_equal(im, im2) diff --git a/Tests/test_imagesequence.py b/Tests/test_imagesequence.py index 1b4bb3c02..d2aa17df7 100644 --- a/Tests/test_imagesequence.py +++ b/Tests/test_imagesequence.py @@ -23,14 +23,11 @@ class TestImageSequence(PillowTestCase): self.assertEqual(index, 1) def _test_multipage_tiff(self, dbg=False): - # debug had side effect of calling fp.tell. - Image.DEBUG = dbg im = Image.open('Tests/images/multipage.tiff') for index, frame in enumerate(ImageSequence.Iterator(im)): frame.load() self.assertEqual(index, im.tell()) frame.convert('RGB') - Image.DEBUG = False def test_tiff(self): # self._test_multipage_tiff(True)