Improve exception traceback readability

This commit is contained in:
Hugo van Kemenade 2022-12-21 23:51:35 +02:00
parent 77f6f54ac4
commit 2ae55ccbda
79 changed files with 861 additions and 487 deletions

View File

@ -35,7 +35,8 @@ repos:
rev: 6.0.0 rev: 6.0.0
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies: [flake8-2020, flake8-implicit-str-concat] additional_dependencies:
[flake8-2020, flake8-errmsg, flake8-implicit-str-concat]
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0 rev: v1.9.0

View File

@ -211,13 +211,16 @@ class DdsImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
if not _accept(self.fp.read(4)): if not _accept(self.fp.read(4)):
raise SyntaxError("not a DDS file") msg = "not a DDS file"
raise SyntaxError(msg)
(header_size,) = struct.unpack("<I", self.fp.read(4)) (header_size,) = struct.unpack("<I", self.fp.read(4))
if header_size != 124: if header_size != 124:
raise OSError(f"Unsupported header size {repr(header_size)}") msg = f"Unsupported header size {repr(header_size)}"
raise OSError(msg)
header_bytes = self.fp.read(header_size - 4) header_bytes = self.fp.read(header_size - 4)
if len(header_bytes) != 120: if len(header_bytes) != 120:
raise OSError(f"Incomplete header: {len(header_bytes)} bytes") msg = f"Incomplete header: {len(header_bytes)} bytes"
raise OSError(msg)
header = BytesIO(header_bytes) header = BytesIO(header_bytes)
flags, height, width = struct.unpack("<3I", header.read(12)) flags, height, width = struct.unpack("<3I", header.read(12))
@ -237,7 +240,8 @@ class DdsImageFile(ImageFile.ImageFile):
elif fourcc == b"DXT5": elif fourcc == b"DXT5":
self.decoder = "DXT5" self.decoder = "DXT5"
else: else:
raise NotImplementedError(f"Unimplemented pixel format {fourcc}") msg = f"Unimplemented pixel format {fourcc}"
raise NotImplementedError(msg)
self.tile = [(self.decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))] self.tile = [(self.decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
@ -252,7 +256,8 @@ class DXT1Decoder(ImageFile.PyDecoder):
try: try:
self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize)) self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize))
except struct.error as e: except struct.error as e:
raise OSError("Truncated DDS file") from e msg = "Truncated DDS file"
raise OSError(msg) from e
return -1, 0 return -1, 0
@ -263,7 +268,8 @@ class DXT5Decoder(ImageFile.PyDecoder):
try: try:
self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize)) self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize))
except struct.error as e: except struct.error as e:
raise OSError("Truncated DDS file") from e msg = "Truncated DDS file"
raise OSError(msg) from e
return -1, 0 return -1, 0

View File

@ -78,7 +78,8 @@ true color.
elif bits == 24: elif bits == 24:
self.mode = "RGB" self.mode = "RGB"
else: else:
raise SyntaxError("unknown number of bits") msg = "unknown number of bits"
raise SyntaxError(msg)
# data descriptor # data descriptor
self.tile = [("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))] self.tile = [("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))]

View File

@ -362,15 +362,15 @@ class pil_build_ext(build_ext):
self.feature.required.discard(x) self.feature.required.discard(x)
_dbg("Disabling %s", x) _dbg("Disabling %s", x)
if getattr(self, f"enable_{x}"): if getattr(self, f"enable_{x}"):
raise ValueError( msg = f"Conflicting options: --enable-{x} and --disable-{x}"
f"Conflicting options: --enable-{x} and --disable-{x}" raise ValueError(msg)
)
if x == "freetype": if x == "freetype":
_dbg("--disable-freetype implies --disable-raqm") _dbg("--disable-freetype implies --disable-raqm")
if getattr(self, "enable_raqm"): if getattr(self, "enable_raqm"):
raise ValueError( msg = (
"Conflicting options: --enable-raqm and --disable-freetype" "Conflicting options: --enable-raqm and --disable-freetype"
) )
raise ValueError(msg)
setattr(self, "disable_raqm", True) setattr(self, "disable_raqm", True)
if getattr(self, f"enable_{x}"): if getattr(self, f"enable_{x}"):
_dbg("Requiring %s", x) _dbg("Requiring %s", x)
@ -381,13 +381,11 @@ class pil_build_ext(build_ext):
for x in ("raqm", "fribidi"): for x in ("raqm", "fribidi"):
if getattr(self, f"vendor_{x}"): if getattr(self, f"vendor_{x}"):
if getattr(self, "disable_raqm"): if getattr(self, "disable_raqm"):
raise ValueError( msg = f"Conflicting options: --vendor-{x} and --disable-raqm"
f"Conflicting options: --vendor-{x} and --disable-raqm" raise ValueError(msg)
)
if x == "fribidi" and not getattr(self, "vendor_raqm"): if x == "fribidi" and not getattr(self, "vendor_raqm"):
raise ValueError( msg = f"Conflicting options: --vendor-{x} and not --vendor-raqm"
f"Conflicting options: --vendor-{x} and not --vendor-raqm" raise ValueError(msg)
)
_dbg("Using vendored version of %s", x) _dbg("Using vendored version of %s", x)
self.feature.vendor.add(x) self.feature.vendor.add(x)

View File

@ -86,7 +86,8 @@ class BdfFontFile(FontFile.FontFile):
s = fp.readline() s = fp.readline()
if s[:13] != b"STARTFONT 2.1": if s[:13] != b"STARTFONT 2.1":
raise SyntaxError("not a valid BDF file") msg = "not a valid BDF file"
raise SyntaxError(msg)
props = {} props = {}
comments = [] comments = []

View File

@ -65,7 +65,8 @@ def __getattr__(name):
if name in enum.__members__: if name in enum.__members__:
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
return enum[name] return enum[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'") msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)
def unpack_565(i): def unpack_565(i):
@ -278,7 +279,8 @@ class BlpImageFile(ImageFile.ImageFile):
if self.magic in (b"BLP1", b"BLP2"): if self.magic in (b"BLP1", b"BLP2"):
decoder = self.magic.decode() decoder = self.magic.decode()
else: else:
raise BLPFormatError(f"Bad BLP magic {repr(self.magic)}") msg = f"Bad BLP magic {repr(self.magic)}"
raise BLPFormatError(msg)
self.mode = "RGBA" if self._blp_alpha_depth else "RGB" self.mode = "RGBA" if self._blp_alpha_depth else "RGB"
self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))] self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
@ -292,7 +294,8 @@ class _BLPBaseDecoder(ImageFile.PyDecoder):
self._read_blp_header() self._read_blp_header()
self._load() self._load()
except struct.error as e: except struct.error as e:
raise OSError("Truncated BLP file") from e msg = "Truncated BLP file"
raise OSError(msg) from e
return -1, 0 return -1, 0
def _read_blp_header(self): def _read_blp_header(self):
@ -354,13 +357,11 @@ class BLP1Decoder(_BLPBaseDecoder):
data = self._read_bgra(palette) data = self._read_bgra(palette)
self.set_as_raw(bytes(data)) self.set_as_raw(bytes(data))
else: else:
raise BLPFormatError( msg = f"Unsupported BLP encoding {repr(self._blp_encoding)}"
f"Unsupported BLP encoding {repr(self._blp_encoding)}" raise BLPFormatError(msg)
)
else: else:
raise BLPFormatError( msg = f"Unsupported BLP compression {repr(self._blp_encoding)}"
f"Unsupported BLP compression {repr(self._blp_encoding)}" raise BLPFormatError(msg)
)
def _decode_jpeg_stream(self): def _decode_jpeg_stream(self):
from .JpegImagePlugin import JpegImageFile from .JpegImagePlugin import JpegImageFile
@ -415,16 +416,15 @@ class BLP2Decoder(_BLPBaseDecoder):
for d in decode_dxt5(self._safe_read(linesize)): for d in decode_dxt5(self._safe_read(linesize)):
data += d data += d
else: else:
raise BLPFormatError( msg = f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}"
f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}" raise BLPFormatError(msg)
)
else: else:
raise BLPFormatError(f"Unknown BLP encoding {repr(self._blp_encoding)}") msg = f"Unknown BLP encoding {repr(self._blp_encoding)}"
raise BLPFormatError(msg)
else: else:
raise BLPFormatError( msg = f"Unknown BLP compression {repr(self._blp_compression)}"
f"Unknown BLP compression {repr(self._blp_compression)}" raise BLPFormatError(msg)
)
self.set_as_raw(bytes(data)) self.set_as_raw(bytes(data))
@ -460,7 +460,8 @@ class BLPEncoder(ImageFile.PyEncoder):
def _save(im, fp, filename, save_all=False): def _save(im, fp, filename, save_all=False):
if im.mode != "P": if im.mode != "P":
raise ValueError("Unsupported BLP image mode") msg = "Unsupported BLP image mode"
raise ValueError(msg)
magic = b"BLP1" if im.encoderinfo.get("blp_version") == "BLP1" else b"BLP2" magic = b"BLP1" if im.encoderinfo.get("blp_version") == "BLP1" else b"BLP2"
fp.write(magic) fp.write(magic)

View File

@ -146,7 +146,8 @@ class BmpImageFile(ImageFile.ImageFile):
file_info["a_mask"], file_info["a_mask"],
) )
else: else:
raise OSError(f"Unsupported BMP header type ({file_info['header_size']})") msg = f"Unsupported BMP header type ({file_info['header_size']})"
raise OSError(msg)
# ------------------ Special case : header is reported 40, which # ------------------ Special case : header is reported 40, which
# ---------------------- is shorter than real size for bpp >= 16 # ---------------------- is shorter than real size for bpp >= 16
@ -164,7 +165,8 @@ class BmpImageFile(ImageFile.ImageFile):
# ---------------------- Check bit depth for unusual unsupported values # ---------------------- Check bit depth for unusual unsupported values
self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None)) self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
if self.mode is None: if self.mode is None:
raise OSError(f"Unsupported BMP pixel depth ({file_info['bits']})") msg = f"Unsupported BMP pixel depth ({file_info['bits']})"
raise OSError(msg)
# ---------------- Process BMP with Bitfields compression (not palette) # ---------------- Process BMP with Bitfields compression (not palette)
decoder_name = "raw" decoder_name = "raw"
@ -205,23 +207,27 @@ class BmpImageFile(ImageFile.ImageFile):
): ):
raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])] raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
else: else:
raise OSError("Unsupported BMP bitfields layout") msg = "Unsupported BMP bitfields layout"
raise OSError(msg)
else: else:
raise OSError("Unsupported BMP bitfields layout") msg = "Unsupported BMP bitfields layout"
raise OSError(msg)
elif file_info["compression"] == self.RAW: elif file_info["compression"] == self.RAW:
if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset
raw_mode, self.mode = "BGRA", "RGBA" raw_mode, self.mode = "BGRA", "RGBA"
elif file_info["compression"] in (self.RLE8, self.RLE4): elif file_info["compression"] in (self.RLE8, self.RLE4):
decoder_name = "bmp_rle" decoder_name = "bmp_rle"
else: else:
raise OSError(f"Unsupported BMP compression ({file_info['compression']})") msg = f"Unsupported BMP compression ({file_info['compression']})"
raise OSError(msg)
# --------------- Once the header is processed, process the palette/LUT # --------------- Once the header is processed, process the palette/LUT
if self.mode == "P": # Paletted for 1, 4 and 8 bit images if self.mode == "P": # Paletted for 1, 4 and 8 bit images
# ---------------------------------------------------- 1-bit images # ---------------------------------------------------- 1-bit images
if not (0 < file_info["colors"] <= 65536): if not (0 < file_info["colors"] <= 65536):
raise OSError(f"Unsupported BMP Palette size ({file_info['colors']})") msg = f"Unsupported BMP Palette size ({file_info['colors']})"
raise OSError(msg)
else: else:
padding = file_info["palette_padding"] padding = file_info["palette_padding"]
palette = read(padding * file_info["colors"]) palette = read(padding * file_info["colors"])
@ -271,7 +277,8 @@ class BmpImageFile(ImageFile.ImageFile):
head_data = self.fp.read(14) head_data = self.fp.read(14)
# choke if the file does not have the required magic bytes # choke if the file does not have the required magic bytes
if not _accept(head_data): if not _accept(head_data):
raise SyntaxError("Not a BMP file") msg = "Not a BMP file"
raise SyntaxError(msg)
# read the start position of the BMP image data (u32) # read the start position of the BMP image data (u32)
offset = i32(head_data, 10) offset = i32(head_data, 10)
# load bitmap information (offset=raster info) # load bitmap information (offset=raster info)
@ -383,7 +390,8 @@ def _save(im, fp, filename, bitmap_header=True):
try: try:
rawmode, bits, colors = SAVE[im.mode] rawmode, bits, colors = SAVE[im.mode]
except KeyError as e: except KeyError as e:
raise OSError(f"cannot write mode {im.mode} as BMP") from e msg = f"cannot write mode {im.mode} as BMP"
raise OSError(msg) from e
info = im.encoderinfo info = im.encoderinfo
@ -411,7 +419,8 @@ def _save(im, fp, filename, bitmap_header=True):
offset = 14 + header + colors * 4 offset = 14 + header + colors * 4
file_size = offset + image file_size = offset + image
if file_size > 2**32 - 1: if file_size > 2**32 - 1:
raise ValueError("File size is too large for the BMP format") msg = "File size is too large for the BMP format"
raise ValueError(msg)
fp.write( fp.write(
b"BM" # file type (magic) b"BM" # file type (magic)
+ o32(file_size) # file size + o32(file_size) # file size

View File

@ -42,7 +42,8 @@ class BufrStubImageFile(ImageFile.StubImageFile):
offset = self.fp.tell() offset = self.fp.tell()
if not _accept(self.fp.read(4)): if not _accept(self.fp.read(4)):
raise SyntaxError("Not a BUFR file") msg = "Not a BUFR file"
raise SyntaxError(msg)
self.fp.seek(offset) self.fp.seek(offset)
@ -60,7 +61,8 @@ class BufrStubImageFile(ImageFile.StubImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if _handler is None or not hasattr(_handler, "save"): if _handler is None or not hasattr(_handler, "save"):
raise OSError("BUFR save handler not installed") msg = "BUFR save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename) _handler.save(im, fp, filename)

View File

@ -43,7 +43,8 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
# check magic # check magic
s = self.fp.read(6) s = self.fp.read(6)
if not _accept(s): if not _accept(s):
raise SyntaxError("not a CUR file") msg = "not a CUR file"
raise SyntaxError(msg)
# pick the largest cursor in the file # pick the largest cursor in the file
m = b"" m = b""
@ -54,7 +55,8 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
elif s[0] > m[0] and s[1] > m[1]: elif s[0] > m[0] and s[1] > m[1]:
m = s m = s
if not m: if not m:
raise TypeError("No cursors were found") msg = "No cursors were found"
raise TypeError(msg)
# load as bitmap # load as bitmap
self._bitmap(i32(m, 12) + offset) self._bitmap(i32(m, 12) + offset)

View File

@ -47,7 +47,8 @@ class DcxImageFile(PcxImageFile):
# Header # Header
s = self.fp.read(4) s = self.fp.read(4)
if not _accept(s): if not _accept(s):
raise SyntaxError("not a DCX file") msg = "not a DCX file"
raise SyntaxError(msg)
# Component directory # Component directory
self._offset = [] self._offset = []

View File

@ -114,13 +114,16 @@ class DdsImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
if not _accept(self.fp.read(4)): if not _accept(self.fp.read(4)):
raise SyntaxError("not a DDS file") msg = "not a DDS file"
raise SyntaxError(msg)
(header_size,) = struct.unpack("<I", self.fp.read(4)) (header_size,) = struct.unpack("<I", self.fp.read(4))
if header_size != 124: if header_size != 124:
raise OSError(f"Unsupported header size {repr(header_size)}") msg = f"Unsupported header size {repr(header_size)}"
raise OSError(msg)
header_bytes = self.fp.read(header_size - 4) header_bytes = self.fp.read(header_size - 4)
if len(header_bytes) != 120: if len(header_bytes) != 120:
raise OSError(f"Incomplete header: {len(header_bytes)} bytes") msg = f"Incomplete header: {len(header_bytes)} bytes"
raise OSError(msg)
header = BytesIO(header_bytes) header = BytesIO(header_bytes)
flags, height, width = struct.unpack("<3I", header.read(12)) flags, height, width = struct.unpack("<3I", header.read(12))
@ -216,11 +219,11 @@ class DdsImageFile(ImageFile.ImageFile):
self.info["gamma"] = 1 / 2.2 self.info["gamma"] = 1 / 2.2
return return
else: else:
raise NotImplementedError( msg = f"Unimplemented DXGI format {dxgi_format}"
f"Unimplemented DXGI format {dxgi_format}" raise NotImplementedError(msg)
)
else: else:
raise NotImplementedError(f"Unimplemented pixel format {repr(fourcc)}") msg = f"Unimplemented pixel format {repr(fourcc)}"
raise NotImplementedError(msg)
self.tile = [ self.tile = [
("bcn", (0, 0) + self.size, data_start, (n, self.pixel_format)) ("bcn", (0, 0) + self.size, data_start, (n, self.pixel_format))
@ -232,7 +235,8 @@ class DdsImageFile(ImageFile.ImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if im.mode not in ("RGB", "RGBA", "L", "LA"): if im.mode not in ("RGB", "RGBA", "L", "LA"):
raise OSError(f"cannot write mode {im.mode} as DDS") msg = f"cannot write mode {im.mode} as DDS"
raise OSError(msg)
rawmode = im.mode rawmode = im.mode
masks = [0xFF0000, 0xFF00, 0xFF] masks = [0xFF0000, 0xFF00, 0xFF]

View File

@ -133,7 +133,8 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False):
if gs_windows_binary is not None: if gs_windows_binary is not None:
if not gs_windows_binary: if not gs_windows_binary:
raise OSError("Unable to locate Ghostscript on paths") msg = "Unable to locate Ghostscript on paths"
raise OSError(msg)
command[0] = gs_windows_binary command[0] = gs_windows_binary
# push data through Ghostscript # push data through Ghostscript
@ -229,12 +230,14 @@ class EpsImageFile(ImageFile.ImageFile):
while s_raw: while s_raw:
if s: if s:
if len(s) > 255: if len(s) > 255:
raise SyntaxError("not an EPS file") msg = "not an EPS file"
raise SyntaxError(msg)
try: try:
m = split.match(s) m = split.match(s)
except re.error as e: except re.error as e:
raise SyntaxError("not an EPS file") from e msg = "not an EPS file"
raise SyntaxError(msg) from e
if m: if m:
k, v = m.group(1, 2) k, v = m.group(1, 2)
@ -268,7 +271,8 @@ class EpsImageFile(ImageFile.ImageFile):
# tools mistakenly put in the Comments section # tools mistakenly put in the Comments section
pass pass
else: else:
raise OSError("bad EPS header") msg = "bad EPS header"
raise OSError(msg)
s_raw = fp.readline() s_raw = fp.readline()
s = s_raw.strip("\r\n") s = s_raw.strip("\r\n")
@ -282,7 +286,8 @@ class EpsImageFile(ImageFile.ImageFile):
while s[:1] == "%": while s[:1] == "%":
if len(s) > 255: if len(s) > 255:
raise SyntaxError("not an EPS file") msg = "not an EPS file"
raise SyntaxError(msg)
if s[:11] == "%ImageData:": if s[:11] == "%ImageData:":
# Encoded bitmapped image. # Encoded bitmapped image.
@ -306,7 +311,8 @@ class EpsImageFile(ImageFile.ImageFile):
break break
if not box: if not box:
raise OSError("cannot determine EPS bounding box") msg = "cannot determine EPS bounding box"
raise OSError(msg)
def _find_offset(self, fp): def _find_offset(self, fp):
@ -326,7 +332,8 @@ class EpsImageFile(ImageFile.ImageFile):
offset = i32(s, 4) offset = i32(s, 4)
length = i32(s, 8) length = i32(s, 8)
else: else:
raise SyntaxError("not an EPS file") msg = "not an EPS file"
raise SyntaxError(msg)
return length, offset return length, offset
@ -365,7 +372,8 @@ def _save(im, fp, filename, eps=1):
elif im.mode == "CMYK": elif im.mode == "CMYK":
operator = (8, 4, b"false 4 colorimage") operator = (8, 4, b"false 4 colorimage")
else: else:
raise ValueError("image mode is not supported") msg = "image mode is not supported"
raise ValueError(msg)
if eps: if eps:
# #

View File

@ -28,7 +28,8 @@ class FitsImageFile(ImageFile.ImageFile):
while True: while True:
header = self.fp.read(80) header = self.fp.read(80)
if not header: if not header:
raise OSError("Truncated FITS file") msg = "Truncated FITS file"
raise OSError(msg)
keyword = header[:8].strip() keyword = header[:8].strip()
if keyword == b"END": if keyword == b"END":
break break
@ -36,12 +37,14 @@ class FitsImageFile(ImageFile.ImageFile):
if value.startswith(b"="): if value.startswith(b"="):
value = value[1:].strip() value = value[1:].strip()
if not headers and (not _accept(keyword) or value != b"T"): if not headers and (not _accept(keyword) or value != b"T"):
raise SyntaxError("Not a FITS file") msg = "Not a FITS file"
raise SyntaxError(msg)
headers[keyword] = value headers[keyword] = value
naxis = int(headers[b"NAXIS"]) naxis = int(headers[b"NAXIS"])
if naxis == 0: if naxis == 0:
raise ValueError("No image data") msg = "No image data"
raise ValueError(msg)
elif naxis == 1: elif naxis == 1:
self._size = 1, int(headers[b"NAXIS1"]) self._size = 1, int(headers[b"NAXIS1"])
else: else:

View File

@ -67,7 +67,8 @@ class FITSStubImageFile(ImageFile.StubImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
raise OSError("FITS save handler not installed") msg = "FITS save handler not installed"
raise OSError(msg)
# -------------------------------------------------------------------- # --------------------------------------------------------------------

View File

@ -50,7 +50,8 @@ class FliImageFile(ImageFile.ImageFile):
# HEAD # HEAD
s = self.fp.read(128) s = self.fp.read(128)
if not (_accept(s) and s[20:22] == b"\x00\x00"): if not (_accept(s) and s[20:22] == b"\x00\x00"):
raise SyntaxError("not an FLI/FLC file") msg = "not an FLI/FLC file"
raise SyntaxError(msg)
# frames # frames
self.n_frames = i16(s, 6) self.n_frames = i16(s, 6)
@ -141,7 +142,8 @@ class FliImageFile(ImageFile.ImageFile):
self.load() self.load()
if frame != self.__frame + 1: if frame != self.__frame + 1:
raise ValueError(f"cannot seek to frame {frame}") msg = f"cannot seek to frame {frame}"
raise ValueError(msg)
self.__frame = frame self.__frame = frame
# move to next frame # move to next frame

View File

@ -60,10 +60,12 @@ class FpxImageFile(ImageFile.ImageFile):
try: try:
self.ole = olefile.OleFileIO(self.fp) self.ole = olefile.OleFileIO(self.fp)
except OSError as e: except OSError as e:
raise SyntaxError("not an FPX file; invalid OLE file") from e msg = "not an FPX file; invalid OLE file"
raise SyntaxError(msg) from e
if self.ole.root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B": if self.ole.root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B":
raise SyntaxError("not an FPX file; bad root CLSID") msg = "not an FPX file; bad root CLSID"
raise SyntaxError(msg)
self._open_index(1) self._open_index(1)
@ -99,7 +101,8 @@ class FpxImageFile(ImageFile.ImageFile):
colors = [] colors = []
bands = i32(s, 4) bands = i32(s, 4)
if bands > 4: if bands > 4:
raise OSError("Invalid number of bands") msg = "Invalid number of bands"
raise OSError(msg)
for i in range(bands): for i in range(bands):
# note: for now, we ignore the "uncalibrated" flag # note: for now, we ignore the "uncalibrated" flag
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF) colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)
@ -141,7 +144,8 @@ class FpxImageFile(ImageFile.ImageFile):
length = i32(s, 32) length = i32(s, 32)
if size != self.size: if size != self.size:
raise OSError("subimage mismatch") msg = "subimage mismatch"
raise OSError(msg)
# get tile descriptors # get tile descriptors
fp.seek(28 + offset) fp.seek(28 + offset)
@ -217,7 +221,8 @@ class FpxImageFile(ImageFile.ImageFile):
self.tile_prefix = self.jpeg[jpeg_tables] self.tile_prefix = self.jpeg[jpeg_tables]
else: else:
raise OSError("unknown/invalid compression") msg = "unknown/invalid compression"
raise OSError(msg)
x = x + xtile x = x + xtile
if x >= xsize: if x >= xsize:

View File

@ -73,7 +73,8 @@ def __getattr__(name):
if name in enum.__members__: if name in enum.__members__:
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
return enum[name] return enum[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'") msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)
class FtexImageFile(ImageFile.ImageFile): class FtexImageFile(ImageFile.ImageFile):
@ -82,7 +83,8 @@ class FtexImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
if not _accept(self.fp.read(4)): if not _accept(self.fp.read(4)):
raise SyntaxError("not an FTEX file") msg = "not an FTEX file"
raise SyntaxError(msg)
struct.unpack("<i", self.fp.read(4)) # version struct.unpack("<i", self.fp.read(4)) # version
self._size = struct.unpack("<2i", self.fp.read(8)) self._size = struct.unpack("<2i", self.fp.read(8))
mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8)) mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8))
@ -105,7 +107,8 @@ class FtexImageFile(ImageFile.ImageFile):
elif format == Format.UNCOMPRESSED: elif format == Format.UNCOMPRESSED:
self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))] self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
else: else:
raise ValueError(f"Invalid texture compression format: {repr(format)}") msg = f"Invalid texture compression format: {repr(format)}"
raise ValueError(msg)
self.fp.close() self.fp.close()
self.fp = BytesIO(data) self.fp = BytesIO(data)

View File

@ -44,18 +44,22 @@ class GbrImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
header_size = i32(self.fp.read(4)) header_size = i32(self.fp.read(4))
if header_size < 20: if header_size < 20:
raise SyntaxError("not a GIMP brush") msg = "not a GIMP brush"
raise SyntaxError(msg)
version = i32(self.fp.read(4)) version = i32(self.fp.read(4))
if version not in (1, 2): if version not in (1, 2):
raise SyntaxError(f"Unsupported GIMP brush version: {version}") msg = f"Unsupported GIMP brush version: {version}"
raise SyntaxError(msg)
width = i32(self.fp.read(4)) width = i32(self.fp.read(4))
height = i32(self.fp.read(4)) height = i32(self.fp.read(4))
color_depth = i32(self.fp.read(4)) color_depth = i32(self.fp.read(4))
if width <= 0 or height <= 0: if width <= 0 or height <= 0:
raise SyntaxError("not a GIMP brush") msg = "not a GIMP brush"
raise SyntaxError(msg)
if color_depth not in (1, 4): if color_depth not in (1, 4):
raise SyntaxError(f"Unsupported GIMP brush color depth: {color_depth}") msg = f"Unsupported GIMP brush color depth: {color_depth}"
raise SyntaxError(msg)
if version == 1: if version == 1:
comment_length = header_size - 20 comment_length = header_size - 20
@ -63,7 +67,8 @@ class GbrImageFile(ImageFile.ImageFile):
comment_length = header_size - 28 comment_length = header_size - 28
magic_number = self.fp.read(4) magic_number = self.fp.read(4)
if magic_number != b"GIMP": if magic_number != b"GIMP":
raise SyntaxError("not a GIMP brush, bad magic number") msg = "not a GIMP brush, bad magic number"
raise SyntaxError(msg)
self.info["spacing"] = i32(self.fp.read(4)) self.info["spacing"] = i32(self.fp.read(4))
comment = self.fp.read(comment_length)[:-1] comment = self.fp.read(comment_length)[:-1]

View File

@ -49,7 +49,8 @@ class GdImageFile(ImageFile.ImageFile):
s = self.fp.read(1037) s = self.fp.read(1037)
if not i16(s) in [65534, 65535]: if not i16(s) in [65534, 65535]:
raise SyntaxError("Not a valid GD 2.x .gd file") msg = "Not a valid GD 2.x .gd file"
raise SyntaxError(msg)
self.mode = "L" # FIXME: "P" self.mode = "L" # FIXME: "P"
self._size = i16(s, 2), i16(s, 4) self._size = i16(s, 2), i16(s, 4)
@ -87,9 +88,11 @@ def open(fp, mode="r"):
:raises OSError: If the image could not be read. :raises OSError: If the image could not be read.
""" """
if mode != "r": if mode != "r":
raise ValueError("bad mode") msg = "bad mode"
raise ValueError(msg)
try: try:
return GdImageFile(fp) return GdImageFile(fp)
except SyntaxError as e: except SyntaxError as e:
raise UnidentifiedImageError("cannot identify this image file") from e msg = "cannot identify this image file"
raise UnidentifiedImageError(msg) from e

View File

@ -85,7 +85,8 @@ class GifImageFile(ImageFile.ImageFile):
# Screen # Screen
s = self.fp.read(13) s = self.fp.read(13)
if not _accept(s): if not _accept(s):
raise SyntaxError("not a GIF file") msg = "not a GIF file"
raise SyntaxError(msg)
self.info["version"] = s[:6] self.info["version"] = s[:6]
self._size = i16(s, 6), i16(s, 8) self._size = i16(s, 6), i16(s, 8)
@ -152,7 +153,8 @@ class GifImageFile(ImageFile.ImageFile):
self._seek(f) self._seek(f)
except EOFError as e: except EOFError as e:
self.seek(last_frame) self.seek(last_frame)
raise EOFError("no more images in GIF file") from e msg = "no more images in GIF file"
raise EOFError(msg) from e
def _seek(self, frame, update_image=True): def _seek(self, frame, update_image=True):
@ -171,7 +173,8 @@ class GifImageFile(ImageFile.ImageFile):
self.load() self.load()
if frame != self.__frame + 1: if frame != self.__frame + 1:
raise ValueError(f"cannot seek to frame {frame}") msg = f"cannot seek to frame {frame}"
raise ValueError(msg)
self.fp = self._fp self.fp = self._fp
if self.__offset: if self.__offset:

View File

@ -107,7 +107,8 @@ class GimpGradientFile(GradientFile):
def __init__(self, fp): def __init__(self, fp):
if fp.readline()[:13] != b"GIMP Gradient": if fp.readline()[:13] != b"GIMP Gradient":
raise SyntaxError("not a GIMP gradient file") msg = "not a GIMP gradient file"
raise SyntaxError(msg)
line = fp.readline() line = fp.readline()
@ -133,7 +134,8 @@ class GimpGradientFile(GradientFile):
cspace = int(s[12]) cspace = int(s[12])
if cspace != 0: if cspace != 0:
raise OSError("cannot handle HSV colour space") msg = "cannot handle HSV colour space"
raise OSError(msg)
gradient.append((x0, x1, xm, rgb0, rgb1, segment)) gradient.append((x0, x1, xm, rgb0, rgb1, segment))

View File

@ -29,7 +29,8 @@ class GimpPaletteFile:
self.palette = [o8(i) * 3 for i in range(256)] self.palette = [o8(i) * 3 for i in range(256)]
if fp.readline()[:12] != b"GIMP Palette": if fp.readline()[:12] != b"GIMP Palette":
raise SyntaxError("not a GIMP palette file") msg = "not a GIMP palette file"
raise SyntaxError(msg)
for i in range(256): for i in range(256):
@ -41,11 +42,13 @@ class GimpPaletteFile:
if re.match(rb"\w+:|#", s): if re.match(rb"\w+:|#", s):
continue continue
if len(s) > 100: if len(s) > 100:
raise SyntaxError("bad palette file") msg = "bad palette file"
raise SyntaxError(msg)
v = tuple(map(int, s.split()[:3])) v = tuple(map(int, s.split()[:3]))
if len(v) != 3: if len(v) != 3:
raise ValueError("bad palette entry") msg = "bad palette entry"
raise ValueError(msg)
self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2]) self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2])

View File

@ -42,7 +42,8 @@ class GribStubImageFile(ImageFile.StubImageFile):
offset = self.fp.tell() offset = self.fp.tell()
if not _accept(self.fp.read(8)): if not _accept(self.fp.read(8)):
raise SyntaxError("Not a GRIB file") msg = "Not a GRIB file"
raise SyntaxError(msg)
self.fp.seek(offset) self.fp.seek(offset)
@ -60,7 +61,8 @@ class GribStubImageFile(ImageFile.StubImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if _handler is None or not hasattr(_handler, "save"): if _handler is None or not hasattr(_handler, "save"):
raise OSError("GRIB save handler not installed") msg = "GRIB save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename) _handler.save(im, fp, filename)

View File

@ -42,7 +42,8 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
offset = self.fp.tell() offset = self.fp.tell()
if not _accept(self.fp.read(8)): if not _accept(self.fp.read(8)):
raise SyntaxError("Not an HDF file") msg = "Not an HDF file"
raise SyntaxError(msg)
self.fp.seek(offset) self.fp.seek(offset)
@ -60,7 +61,8 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if _handler is None or not hasattr(_handler, "save"): if _handler is None or not hasattr(_handler, "save"):
raise OSError("HDF5 save handler not installed") msg = "HDF5 save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename) _handler.save(im, fp, filename)

View File

@ -42,7 +42,8 @@ def read_32t(fobj, start_length, size):
fobj.seek(start) fobj.seek(start)
sig = fobj.read(4) sig = fobj.read(4)
if sig != b"\x00\x00\x00\x00": if sig != b"\x00\x00\x00\x00":
raise SyntaxError("Unknown signature, expecting 0x00000000") msg = "Unknown signature, expecting 0x00000000"
raise SyntaxError(msg)
return read_32(fobj, (start + 4, length - 4), size) return read_32(fobj, (start + 4, length - 4), size)
@ -82,7 +83,8 @@ def read_32(fobj, start_length, size):
if bytesleft <= 0: if bytesleft <= 0:
break break
if bytesleft != 0: if bytesleft != 0:
raise SyntaxError(f"Error reading channel [{repr(bytesleft)} left]") msg = f"Error reading channel [{repr(bytesleft)} left]"
raise SyntaxError(msg)
band = Image.frombuffer("L", pixel_size, b"".join(data), "raw", "L", 0, 1) band = Image.frombuffer("L", pixel_size, b"".join(data), "raw", "L", 0, 1)
im.im.putband(band.im, band_ix) im.im.putband(band.im, band_ix)
return {"RGB": im} return {"RGB": im}
@ -113,10 +115,11 @@ def read_png_or_jpeg2000(fobj, start_length, size):
or sig == b"\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a" or sig == b"\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a"
): ):
if not enable_jpeg2k: if not enable_jpeg2k:
raise ValueError( msg = (
"Unsupported icon subimage format (rebuild PIL " "Unsupported icon subimage format (rebuild PIL "
"with JPEG 2000 support to fix this)" "with JPEG 2000 support to fix this)"
) )
raise ValueError(msg)
# j2k, jpc or j2c # j2k, jpc or j2c
fobj.seek(start) fobj.seek(start)
jp2kstream = fobj.read(length) jp2kstream = fobj.read(length)
@ -127,7 +130,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
im = im.convert("RGBA") im = im.convert("RGBA")
return {"RGBA": im} return {"RGBA": im}
else: else:
raise ValueError("Unsupported icon subimage format") msg = "Unsupported icon subimage format"
raise ValueError(msg)
class IcnsFile: class IcnsFile:
@ -168,12 +172,14 @@ class IcnsFile:
self.fobj = fobj self.fobj = fobj
sig, filesize = nextheader(fobj) sig, filesize = nextheader(fobj)
if not _accept(sig): if not _accept(sig):
raise SyntaxError("not an icns file") msg = "not an icns file"
raise SyntaxError(msg)
i = HEADERSIZE i = HEADERSIZE
while i < filesize: while i < filesize:
sig, blocksize = nextheader(fobj) sig, blocksize = nextheader(fobj)
if blocksize <= 0: if blocksize <= 0:
raise SyntaxError("invalid block header") msg = "invalid block header"
raise SyntaxError(msg)
i += HEADERSIZE i += HEADERSIZE
blocksize -= HEADERSIZE blocksize -= HEADERSIZE
dct[sig] = (i, blocksize) dct[sig] = (i, blocksize)
@ -192,7 +198,8 @@ class IcnsFile:
def bestsize(self): def bestsize(self):
sizes = self.itersizes() sizes = self.itersizes()
if not sizes: if not sizes:
raise SyntaxError("No 32bit icon resources found") msg = "No 32bit icon resources found"
raise SyntaxError(msg)
return max(sizes) return max(sizes)
def dataforsize(self, size): def dataforsize(self, size):
@ -275,7 +282,8 @@ class IcnsImageFile(ImageFile.ImageFile):
if value in simple_sizes: if value in simple_sizes:
info_size = self.info["sizes"][simple_sizes.index(value)] info_size = self.info["sizes"][simple_sizes.index(value)]
if info_size not in self.info["sizes"]: if info_size not in self.info["sizes"]:
raise ValueError("This is not one of the allowed sizes of this image") msg = "This is not one of the allowed sizes of this image"
raise ValueError(msg)
self._size = value self._size = value
def load(self): def load(self):

View File

@ -127,7 +127,8 @@ class IcoFile:
# check magic # check magic
s = buf.read(6) s = buf.read(6)
if not _accept(s): if not _accept(s):
raise SyntaxError("not an ICO file") msg = "not an ICO file"
raise SyntaxError(msg)
self.buf = buf self.buf = buf
self.entry = [] self.entry = []
@ -316,7 +317,8 @@ class IcoImageFile(ImageFile.ImageFile):
@size.setter @size.setter
def size(self, value): def size(self, value):
if value not in self.info["sizes"]: if value not in self.info["sizes"]:
raise ValueError("This is not one of the allowed sizes of this image") msg = "This is not one of the allowed sizes of this image"
raise ValueError(msg)
self._size = value self._size = value
def load(self): def load(self):

View File

@ -126,7 +126,8 @@ class ImImageFile(ImageFile.ImageFile):
# 100 bytes, this is (probably) not a text header. # 100 bytes, this is (probably) not a text header.
if b"\n" not in self.fp.read(100): if b"\n" not in self.fp.read(100):
raise SyntaxError("not an IM file") msg = "not an IM file"
raise SyntaxError(msg)
self.fp.seek(0) self.fp.seek(0)
n = 0 n = 0
@ -153,7 +154,8 @@ class ImImageFile(ImageFile.ImageFile):
s = s + self.fp.readline() s = s + self.fp.readline()
if len(s) > 100: if len(s) > 100:
raise SyntaxError("not an IM file") msg = "not an IM file"
raise SyntaxError(msg)
if s[-2:] == b"\r\n": if s[-2:] == b"\r\n":
s = s[:-2] s = s[:-2]
@ -163,7 +165,8 @@ class ImImageFile(ImageFile.ImageFile):
try: try:
m = split.match(s) m = split.match(s)
except re.error as e: except re.error as e:
raise SyntaxError("not an IM file") from e msg = "not an IM file"
raise SyntaxError(msg) from e
if m: if m:
@ -203,7 +206,8 @@ class ImImageFile(ImageFile.ImageFile):
) )
if not n: if not n:
raise SyntaxError("Not an IM file") msg = "Not an IM file"
raise SyntaxError(msg)
# Basic attributes # Basic attributes
self._size = self.info[SIZE] self._size = self.info[SIZE]
@ -213,7 +217,8 @@ class ImImageFile(ImageFile.ImageFile):
while s and s[:1] != b"\x1A": while s and s[:1] != b"\x1A":
s = self.fp.read(1) s = self.fp.read(1)
if not s: if not s:
raise SyntaxError("File truncated") msg = "File truncated"
raise SyntaxError(msg)
if LUT in self.info: if LUT in self.info:
# convert lookup table to palette or lut attribute # convert lookup table to palette or lut attribute
@ -332,7 +337,8 @@ def _save(im, fp, filename):
try: try:
image_type, rawmode = SAVE[im.mode] image_type, rawmode = SAVE[im.mode]
except KeyError as e: except KeyError as e:
raise ValueError(f"Cannot save {im.mode} images as IM") from e msg = f"Cannot save {im.mode} images as IM"
raise ValueError(msg) from e
frames = im.encoderinfo.get("frames", 1) frames = im.encoderinfo.get("frames", 1)

View File

@ -80,7 +80,8 @@ def __getattr__(name):
if name in enum.__members__: if name in enum.__members__:
deprecate(name, 10, f"{enum.__name__}.{name}") deprecate(name, 10, f"{enum.__name__}.{name}")
return enum[name] return enum[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'") msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -107,11 +108,12 @@ try:
from . import _imaging as core from . import _imaging as core
if __version__ != getattr(core, "PILLOW_VERSION", None): if __version__ != getattr(core, "PILLOW_VERSION", None):
raise ImportError( msg = (
"The _imaging extension was built for another version of Pillow or PIL:\n" "The _imaging extension was built for another version of Pillow or PIL:\n"
f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n" f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
f"Pillow version: {__version__}" f"Pillow version: {__version__}"
) )
raise ImportError(msg)
except ImportError as v: except ImportError as v:
core = DeferredError(ImportError("The _imaging C module is not installed.")) core = DeferredError(ImportError("The _imaging C module is not installed."))
@ -406,7 +408,8 @@ def _getdecoder(mode, decoder_name, args, extra=()):
# get decoder # get decoder
decoder = getattr(core, decoder_name + "_decoder") decoder = getattr(core, decoder_name + "_decoder")
except AttributeError as e: except AttributeError as e:
raise OSError(f"decoder {decoder_name} not available") from e msg = f"decoder {decoder_name} not available"
raise OSError(msg) from e
return decoder(mode, *args + extra) return decoder(mode, *args + extra)
@ -429,7 +432,8 @@ def _getencoder(mode, encoder_name, args, extra=()):
# get encoder # get encoder
encoder = getattr(core, encoder_name + "_encoder") encoder = getattr(core, encoder_name + "_encoder")
except AttributeError as e: except AttributeError as e:
raise OSError(f"encoder {encoder_name} not available") from e msg = f"encoder {encoder_name} not available"
raise OSError(msg) from e
return encoder(mode, *args + extra) return encoder(mode, *args + extra)
@ -675,7 +679,8 @@ class Image:
try: try:
self.save(b, "PNG") self.save(b, "PNG")
except Exception as e: except Exception as e:
raise ValueError("Could not save to PNG for display") from e msg = "Could not save to PNG for display"
raise ValueError(msg) from e
return b.getvalue() return b.getvalue()
@property @property
@ -767,7 +772,8 @@ class Image:
if s: if s:
break break
if s < 0: if s < 0:
raise RuntimeError(f"encoder error {s} in tobytes") msg = f"encoder error {s} in tobytes"
raise RuntimeError(msg)
return b"".join(data) return b"".join(data)
@ -784,7 +790,8 @@ class Image:
self.load() self.load()
if self.mode != "1": if self.mode != "1":
raise ValueError("not a bitmap") msg = "not a bitmap"
raise ValueError(msg)
data = self.tobytes("xbm") data = self.tobytes("xbm")
return b"".join( return b"".join(
[ [
@ -818,9 +825,11 @@ class Image:
s = d.decode(data) s = d.decode(data)
if s[0] >= 0: if s[0] >= 0:
raise ValueError("not enough image data") msg = "not enough image data"
raise ValueError(msg)
if s[1] != 0: if s[1] != 0:
raise ValueError("cannot decode image data") msg = "cannot decode image data"
raise ValueError(msg)
def load(self): def load(self):
""" """
@ -941,7 +950,8 @@ class Image:
if matrix: if matrix:
# matrix conversion # matrix conversion
if mode not in ("L", "RGB"): if mode not in ("L", "RGB"):
raise ValueError("illegal conversion") msg = "illegal conversion"
raise ValueError(msg)
im = self.im.convert_matrix(mode, matrix) im = self.im.convert_matrix(mode, matrix)
new = self._new(im) new = self._new(im)
if has_transparency and self.im.bands == 3: if has_transparency and self.im.bands == 3:
@ -1026,7 +1036,8 @@ class Image:
elif isinstance(t, int): elif isinstance(t, int):
self.im.putpalettealpha(t, 0) self.im.putpalettealpha(t, 0)
else: else:
raise ValueError("Transparency for P mode should be bytes or int") msg = "Transparency for P mode should be bytes or int"
raise ValueError(msg)
if mode == "P" and palette == Palette.ADAPTIVE: if mode == "P" and palette == Palette.ADAPTIVE:
im = self.im.quantize(colors) im = self.im.quantize(colors)
@ -1076,7 +1087,8 @@ class Image:
im = self.im.convert(modebase) im = self.im.convert(modebase)
im = im.convert(mode, dither) im = im.convert(mode, dither)
except KeyError as e: except KeyError as e:
raise ValueError("illegal conversion") from e msg = "illegal conversion"
raise ValueError(msg) from e
new_im = self._new(im) new_im = self._new(im)
if mode == "P" and palette != Palette.ADAPTIVE: if mode == "P" and palette != Palette.ADAPTIVE:
@ -1151,20 +1163,21 @@ class Image:
Quantize.LIBIMAGEQUANT, Quantize.LIBIMAGEQUANT,
): ):
# Caller specified an invalid mode. # Caller specified an invalid mode.
raise ValueError( msg = (
"Fast Octree (method == 2) and libimagequant (method == 3) " "Fast Octree (method == 2) and libimagequant (method == 3) "
"are the only valid methods for quantizing RGBA images" "are the only valid methods for quantizing RGBA images"
) )
raise ValueError(msg)
if palette: if palette:
# use palette from reference image # use palette from reference image
palette.load() palette.load()
if palette.mode != "P": if palette.mode != "P":
raise ValueError("bad mode for palette image") msg = "bad mode for palette image"
raise ValueError(msg)
if self.mode != "RGB" and self.mode != "L": if self.mode != "RGB" and self.mode != "L":
raise ValueError( msg = "only RGB or L mode images can be quantized to a palette"
"only RGB or L mode images can be quantized to a palette" raise ValueError(msg)
)
im = self.im.convert("P", dither, palette.im) im = self.im.convert("P", dither, palette.im)
new_im = self._new(im) new_im = self._new(im)
new_im.palette = palette.palette.copy() new_im.palette = palette.palette.copy()
@ -1210,9 +1223,11 @@ class Image:
return self.copy() return self.copy()
if box[2] < box[0]: if box[2] < box[0]:
raise ValueError("Coordinate 'right' is less than 'left'") msg = "Coordinate 'right' is less than 'left'"
raise ValueError(msg)
elif box[3] < box[1]: elif box[3] < box[1]:
raise ValueError("Coordinate 'lower' is less than 'upper'") msg = "Coordinate 'lower' is less than 'upper'"
raise ValueError(msg)
self.load() self.load()
return self._new(self._crop(self.im, box)) return self._new(self._crop(self.im, box))
@ -1280,9 +1295,8 @@ class Image:
if isinstance(filter, Callable): if isinstance(filter, Callable):
filter = filter() filter = filter()
if not hasattr(filter, "filter"): if not hasattr(filter, "filter"):
raise TypeError( msg = "filter argument should be ImageFilter.Filter instance or class"
"filter argument should be ImageFilter.Filter instance or class" raise TypeError(msg)
)
multiband = isinstance(filter, ImageFilter.MultibandFilter) multiband = isinstance(filter, ImageFilter.MultibandFilter)
if self.im.bands == 1 or multiband: if self.im.bands == 1 or multiband:
@ -1691,7 +1705,8 @@ class Image:
size = mask.size size = mask.size
else: else:
# FIXME: use self.size here? # FIXME: use self.size here?
raise ValueError("cannot determine region size; use 4-item box") msg = "cannot determine region size; use 4-item box"
raise ValueError(msg)
box += (box[0] + size[0], box[1] + size[1]) box += (box[0] + size[0], box[1] + size[1])
if isinstance(im, str): if isinstance(im, str):
@ -1730,15 +1745,20 @@ class Image:
""" """
if not isinstance(source, (list, tuple)): if not isinstance(source, (list, tuple)):
raise ValueError("Source must be a tuple") msg = "Source must be a tuple"
raise ValueError(msg)
if not isinstance(dest, (list, tuple)): if not isinstance(dest, (list, tuple)):
raise ValueError("Destination must be a tuple") msg = "Destination must be a tuple"
raise ValueError(msg)
if not len(source) in (2, 4): if not len(source) in (2, 4):
raise ValueError("Source must be a 2 or 4-tuple") msg = "Source must be a 2 or 4-tuple"
raise ValueError(msg)
if not len(dest) == 2: if not len(dest) == 2:
raise ValueError("Destination must be a 2-tuple") msg = "Destination must be a 2-tuple"
raise ValueError(msg)
if min(source) < 0: if min(source) < 0:
raise ValueError("Source must be non-negative") msg = "Source must be non-negative"
raise ValueError(msg)
if len(source) == 2: if len(source) == 2:
source = source + im.size source = source + im.size
@ -1803,7 +1823,8 @@ class Image:
if self.mode == "F": if self.mode == "F":
# FIXME: _imaging returns a confusing error message for this case # FIXME: _imaging returns a confusing error message for this case
raise ValueError("point operation not supported for this mode") msg = "point operation not supported for this mode"
raise ValueError(msg)
if mode != "F": if mode != "F":
lut = [round(i) for i in lut] lut = [round(i) for i in lut]
@ -1837,7 +1858,8 @@ class Image:
self.pyaccess = None self.pyaccess = None
self.mode = self.im.mode self.mode = self.im.mode
except KeyError as e: except KeyError as e:
raise ValueError("illegal image mode") from e msg = "illegal image mode"
raise ValueError(msg) from e
if self.mode in ("LA", "PA"): if self.mode in ("LA", "PA"):
band = 1 band = 1
@ -1847,7 +1869,8 @@ class Image:
if isImageType(alpha): if isImageType(alpha):
# alpha layer # alpha layer
if alpha.mode not in ("1", "L"): if alpha.mode not in ("1", "L"):
raise ValueError("illegal image mode") msg = "illegal image mode"
raise ValueError(msg)
alpha.load() alpha.load()
if alpha.mode == "1": if alpha.mode == "1":
alpha = alpha.convert("L") alpha = alpha.convert("L")
@ -1903,7 +1926,8 @@ class Image:
from . import ImagePalette from . import ImagePalette
if self.mode not in ("L", "LA", "P", "PA"): if self.mode not in ("L", "LA", "P", "PA"):
raise ValueError("illegal image mode") msg = "illegal image mode"
raise ValueError(msg)
if isinstance(data, ImagePalette.ImagePalette): if isinstance(data, ImagePalette.ImagePalette):
palette = ImagePalette.raw(data.rawmode, data.palette) palette = ImagePalette.raw(data.rawmode, data.palette)
else: else:
@ -1972,7 +1996,8 @@ class Image:
from . import ImagePalette from . import ImagePalette
if self.mode not in ("L", "P"): if self.mode not in ("L", "P"):
raise ValueError("illegal image mode") msg = "illegal image mode"
raise ValueError(msg)
bands = 3 bands = 3
palette_mode = "RGB" palette_mode = "RGB"
@ -2122,7 +2147,8 @@ class Image:
) )
if reducing_gap is not None and reducing_gap < 1.0: if reducing_gap is not None and reducing_gap < 1.0:
raise ValueError("reducing_gap must be 1.0 or greater") msg = "reducing_gap must be 1.0 or greater"
raise ValueError(msg)
size = tuple(size) size = tuple(size)
@ -2380,7 +2406,8 @@ class Image:
try: try:
format = EXTENSION[ext] format = EXTENSION[ext]
except KeyError as e: except KeyError as e:
raise ValueError(f"unknown file extension: {ext}") from e msg = f"unknown file extension: {ext}"
raise ValueError(msg) from e
if format.upper() not in SAVE: if format.upper() not in SAVE:
init() init()
@ -2494,7 +2521,8 @@ class Image:
try: try:
channel = self.getbands().index(channel) channel = self.getbands().index(channel)
except ValueError as e: except ValueError as e:
raise ValueError(f'The image has no channel "{channel}"') from e msg = f'The image has no channel "{channel}"'
raise ValueError(msg) from e
return self._new(self.im.getband(channel)) return self._new(self.im.getband(channel))
@ -2665,7 +2693,8 @@ class Image:
method, data = method.getdata() method, data = method.getdata()
if data is None: if data is None:
raise ValueError("missing method data") msg = "missing method data"
raise ValueError(msg)
im = new(self.mode, size, fillcolor) im = new(self.mode, size, fillcolor)
if self.mode == "P" and self.palette: if self.mode == "P" and self.palette:
@ -2726,7 +2755,8 @@ class Image:
) )
else: else:
raise ValueError("unknown transformation method") msg = "unknown transformation method"
raise ValueError(msg)
if resample not in ( if resample not in (
Resampling.NEAREST, Resampling.NEAREST,
@ -2791,7 +2821,8 @@ class Image:
from . import ImageQt from . import ImageQt
if not ImageQt.qt_is_installed: if not ImageQt.qt_is_installed:
raise ImportError("Qt bindings are not installed") msg = "Qt bindings are not installed"
raise ImportError(msg)
return ImageQt.toqimage(self) return ImageQt.toqimage(self)
def toqpixmap(self): def toqpixmap(self):
@ -2799,7 +2830,8 @@ class Image:
from . import ImageQt from . import ImageQt
if not ImageQt.qt_is_installed: if not ImageQt.qt_is_installed:
raise ImportError("Qt bindings are not installed") msg = "Qt bindings are not installed"
raise ImportError(msg)
return ImageQt.toqpixmap(self) return ImageQt.toqpixmap(self)
@ -2847,11 +2879,14 @@ def _check_size(size):
""" """
if not isinstance(size, (list, tuple)): if not isinstance(size, (list, tuple)):
raise ValueError("Size must be a tuple") msg = "Size must be a tuple"
raise ValueError(msg)
if len(size) != 2: if len(size) != 2:
raise ValueError("Size must be a tuple of length 2") msg = "Size must be a tuple of length 2"
raise ValueError(msg)
if size[0] < 0 or size[1] < 0: if size[0] < 0 or size[1] < 0:
raise ValueError("Width and height must be >= 0") msg = "Width and height must be >= 0"
raise ValueError(msg)
return True return True
@ -3037,7 +3072,8 @@ def fromarray(obj, mode=None):
try: try:
typekey = (1, 1) + shape[2:], arr["typestr"] typekey = (1, 1) + shape[2:], arr["typestr"]
except KeyError as e: except KeyError as e:
raise TypeError("Cannot handle this data type") from e msg = "Cannot handle this data type"
raise TypeError(msg) from e
try: try:
mode, rawmode = _fromarray_typemap[typekey] mode, rawmode = _fromarray_typemap[typekey]
except KeyError as e: except KeyError as e:
@ -3051,7 +3087,8 @@ def fromarray(obj, mode=None):
else: else:
ndmax = 4 ndmax = 4
if ndim > ndmax: if ndim > ndmax:
raise ValueError(f"Too many dimensions: {ndim} > {ndmax}.") msg = f"Too many dimensions: {ndim} > {ndmax}."
raise ValueError(msg)
size = 1 if ndim == 1 else shape[1], shape[0] size = 1 if ndim == 1 else shape[1], shape[0]
if strides is not None: if strides is not None:
@ -3068,7 +3105,8 @@ def fromqimage(im):
from . import ImageQt from . import ImageQt
if not ImageQt.qt_is_installed: if not ImageQt.qt_is_installed:
raise ImportError("Qt bindings are not installed") msg = "Qt bindings are not installed"
raise ImportError(msg)
return ImageQt.fromqimage(im) return ImageQt.fromqimage(im)
@ -3077,7 +3115,8 @@ def fromqpixmap(im):
from . import ImageQt from . import ImageQt
if not ImageQt.qt_is_installed: if not ImageQt.qt_is_installed:
raise ImportError("Qt bindings are not installed") msg = "Qt bindings are not installed"
raise ImportError(msg)
return ImageQt.fromqpixmap(im) return ImageQt.fromqpixmap(im)
@ -3115,10 +3154,11 @@ def _decompression_bomb_check(size):
pixels = size[0] * size[1] pixels = size[0] * size[1]
if pixels > 2 * MAX_IMAGE_PIXELS: if pixels > 2 * MAX_IMAGE_PIXELS:
raise DecompressionBombError( msg = (
f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
"pixels, could be decompression bomb DOS attack." "pixels, could be decompression bomb DOS attack."
) )
raise DecompressionBombError(msg)
if pixels > MAX_IMAGE_PIXELS: if pixels > MAX_IMAGE_PIXELS:
warnings.warn( warnings.warn(
@ -3158,17 +3198,20 @@ def open(fp, mode="r", formats=None):
""" """
if mode != "r": if mode != "r":
raise ValueError(f"bad mode {repr(mode)}") msg = f"bad mode {repr(mode)}"
raise ValueError(msg)
elif isinstance(fp, io.StringIO): elif isinstance(fp, io.StringIO):
raise ValueError( msg = (
"StringIO cannot be used to open an image. " "StringIO cannot be used to open an image. "
"Binary data must be used instead." "Binary data must be used instead."
) )
raise ValueError(msg)
if formats is None: if formats is None:
formats = ID formats = ID
elif not isinstance(formats, (list, tuple)): elif not isinstance(formats, (list, tuple)):
raise TypeError("formats must be a list or tuple") msg = "formats must be a list or tuple"
raise TypeError(msg)
exclusive_fp = False exclusive_fp = False
filename = "" filename = ""
@ -3326,12 +3369,15 @@ def merge(mode, bands):
""" """
if getmodebands(mode) != len(bands) or "*" in mode: if getmodebands(mode) != len(bands) or "*" in mode:
raise ValueError("wrong number of bands") msg = "wrong number of bands"
raise ValueError(msg)
for band in bands[1:]: for band in bands[1:]:
if band.mode != getmodetype(mode): if band.mode != getmodetype(mode):
raise ValueError("mode mismatch") msg = "mode mismatch"
raise ValueError(msg)
if band.size != bands[0].size: if band.size != bands[0].size:
raise ValueError("size mismatch") msg = "size mismatch"
raise ValueError(msg)
for band in bands: for band in bands:
band.load() band.load()
return bands[0]._new(core.merge(mode, *[b.im for b in bands])) return bands[0]._new(core.merge(mode, *[b.im for b in bands]))

View File

@ -124,7 +124,8 @@ def __getattr__(name):
if name in enum.__members__: if name in enum.__members__:
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
return enum[name] return enum[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'") msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)
# #
@ -191,7 +192,8 @@ class ImageCmsProfile:
elif isinstance(profile, _imagingcms.CmsProfile): elif isinstance(profile, _imagingcms.CmsProfile):
self._set(profile) self._set(profile)
else: else:
raise TypeError("Invalid type for Profile") msg = "Invalid type for Profile"
raise TypeError(msg)
def _set(self, profile, filename=None): def _set(self, profile, filename=None):
self.profile = profile self.profile = profile
@ -269,7 +271,8 @@ class ImageCmsTransform(Image.ImagePointHandler):
def apply_in_place(self, im): def apply_in_place(self, im):
im.load() im.load()
if im.mode != self.output_mode: if im.mode != self.output_mode:
raise ValueError("mode mismatch") # wrong output mode msg = "mode mismatch"
raise ValueError(msg) # wrong output mode
self.transform.apply(im.im.id, im.im.id) self.transform.apply(im.im.id, im.im.id)
im.info["icc_profile"] = self.output_profile.tobytes() im.info["icc_profile"] = self.output_profile.tobytes()
return im return im
@ -374,10 +377,12 @@ def profileToProfile(
outputMode = im.mode outputMode = im.mode
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3): if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
raise PyCMSError("renderingIntent must be an integer between 0 and 3") msg = "renderingIntent must be an integer between 0 and 3"
raise PyCMSError(msg)
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG): if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
raise PyCMSError(f"flags must be an integer between 0 and {_MAX_FLAG}") msg = f"flags must be an integer between 0 and {_MAX_FLAG}"
raise PyCMSError(msg)
try: try:
if not isinstance(inputProfile, ImageCmsProfile): if not isinstance(inputProfile, ImageCmsProfile):
@ -489,7 +494,8 @@ def buildTransform(
""" """
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3): if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
raise PyCMSError("renderingIntent must be an integer between 0 and 3") msg = "renderingIntent must be an integer between 0 and 3"
raise PyCMSError(msg)
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG): if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
@ -591,7 +597,8 @@ def buildProofTransform(
""" """
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3): if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
raise PyCMSError("renderingIntent must be an integer between 0 and 3") msg = "renderingIntent must be an integer between 0 and 3"
raise PyCMSError(msg)
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG): if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
@ -705,17 +712,17 @@ def createProfile(colorSpace, colorTemp=-1):
""" """
if colorSpace not in ["LAB", "XYZ", "sRGB"]: if colorSpace not in ["LAB", "XYZ", "sRGB"]:
raise PyCMSError( msg = (
f"Color space not supported for on-the-fly profile creation ({colorSpace})" f"Color space not supported for on-the-fly profile creation ({colorSpace})"
) )
raise PyCMSError(msg)
if colorSpace == "LAB": if colorSpace == "LAB":
try: try:
colorTemp = float(colorTemp) colorTemp = float(colorTemp)
except (TypeError, ValueError) as e: except (TypeError, ValueError) as e:
raise PyCMSError( msg = f'Color temperature must be numeric, "{colorTemp}" not valid'
f'Color temperature must be numeric, "{colorTemp}" not valid' raise PyCMSError(msg) from e
) from e
try: try:
return core.createProfile(colorSpace, colorTemp) return core.createProfile(colorSpace, colorTemp)

View File

@ -33,7 +33,8 @@ def getrgb(color):
:return: ``(red, green, blue[, alpha])`` :return: ``(red, green, blue[, alpha])``
""" """
if len(color) > 100: if len(color) > 100:
raise ValueError("color specifier is too long") msg = "color specifier is too long"
raise ValueError(msg)
color = color.lower() color = color.lower()
rgb = colormap.get(color, None) rgb = colormap.get(color, None)
@ -115,7 +116,8 @@ def getrgb(color):
m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
if m: if m:
return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)) return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
raise ValueError(f"unknown color specifier: {repr(color)}") msg = f"unknown color specifier: {repr(color)}"
raise ValueError(msg)
def getcolor(color, mode): def getcolor(color, mode):

View File

@ -69,7 +69,8 @@ class ImageDraw:
if mode == "RGBA" and im.mode == "RGB": if mode == "RGBA" and im.mode == "RGB":
blend = 1 blend = 1
else: else:
raise ValueError("mode mismatch") msg = "mode mismatch"
raise ValueError(msg)
if mode == "P": if mode == "P":
self.palette = im.palette self.palette = im.palette
else: else:
@ -437,7 +438,8 @@ class ImageDraw:
) )
if embedded_color and self.mode not in ("RGB", "RGBA"): if embedded_color and self.mode not in ("RGB", "RGBA"):
raise ValueError("Embedded color supported only in RGB and RGBA modes") msg = "Embedded color supported only in RGB and RGBA modes"
raise ValueError(msg)
if font is None: if font is None:
font = self.getfont() font = self.getfont()
@ -534,14 +536,17 @@ class ImageDraw:
embedded_color=False, embedded_color=False,
): ):
if direction == "ttb": if direction == "ttb":
raise ValueError("ttb direction is unsupported for multiline text") msg = "ttb direction is unsupported for multiline text"
raise ValueError(msg)
if anchor is None: if anchor is None:
anchor = "la" anchor = "la"
elif len(anchor) != 2: elif len(anchor) != 2:
raise ValueError("anchor must be a 2 character string") msg = "anchor must be a 2 character string"
raise ValueError(msg)
elif anchor[1] in "tb": elif anchor[1] in "tb":
raise ValueError("anchor not supported for multiline text") msg = "anchor not supported for multiline text"
raise ValueError(msg)
widths = [] widths = []
max_width = 0 max_width = 0
@ -578,7 +583,8 @@ class ImageDraw:
elif align == "right": elif align == "right":
left += width_difference left += width_difference
else: else:
raise ValueError('align must be "left", "center" or "right"') msg = 'align must be "left", "center" or "right"'
raise ValueError(msg)
self.text( self.text(
(left, top), (left, top),
@ -672,9 +678,11 @@ class ImageDraw:
): ):
"""Get the length of a given string, in pixels with 1/64 precision.""" """Get the length of a given string, in pixels with 1/64 precision."""
if self._multiline_check(text): if self._multiline_check(text):
raise ValueError("can't measure length of multiline text") msg = "can't measure length of multiline text"
raise ValueError(msg)
if embedded_color and self.mode not in ("RGB", "RGBA"): if embedded_color and self.mode not in ("RGB", "RGBA"):
raise ValueError("Embedded color supported only in RGB and RGBA modes") msg = "Embedded color supported only in RGB and RGBA modes"
raise ValueError(msg)
if font is None: if font is None:
font = self.getfont() font = self.getfont()
@ -712,7 +720,8 @@ class ImageDraw:
): ):
"""Get the bounding box of a given string, in pixels.""" """Get the bounding box of a given string, in pixels."""
if embedded_color and self.mode not in ("RGB", "RGBA"): if embedded_color and self.mode not in ("RGB", "RGBA"):
raise ValueError("Embedded color supported only in RGB and RGBA modes") msg = "Embedded color supported only in RGB and RGBA modes"
raise ValueError(msg)
if self._multiline_check(text): if self._multiline_check(text):
return self.multiline_textbbox( return self.multiline_textbbox(
@ -752,14 +761,17 @@ class ImageDraw:
embedded_color=False, embedded_color=False,
): ):
if direction == "ttb": if direction == "ttb":
raise ValueError("ttb direction is unsupported for multiline text") msg = "ttb direction is unsupported for multiline text"
raise ValueError(msg)
if anchor is None: if anchor is None:
anchor = "la" anchor = "la"
elif len(anchor) != 2: elif len(anchor) != 2:
raise ValueError("anchor must be a 2 character string") msg = "anchor must be a 2 character string"
raise ValueError(msg)
elif anchor[1] in "tb": elif anchor[1] in "tb":
raise ValueError("anchor not supported for multiline text") msg = "anchor not supported for multiline text"
raise ValueError(msg)
widths = [] widths = []
max_width = 0 max_width = 0
@ -803,7 +815,8 @@ class ImageDraw:
elif align == "right": elif align == "right":
left += width_difference left += width_difference
else: else:
raise ValueError('align must be "left", "center" or "right"') msg = 'align must be "left", "center" or "right"'
raise ValueError(msg)
bbox_line = self.textbbox( bbox_line = self.textbbox(
(left, top), (left, top),
@ -979,38 +992,44 @@ def _compute_regular_polygon_vertices(bounding_circle, n_sides, rotation):
# 1. Error Handling # 1. Error Handling
# 1.1 Check `n_sides` has an appropriate value # 1.1 Check `n_sides` has an appropriate value
if not isinstance(n_sides, int): if not isinstance(n_sides, int):
raise TypeError("n_sides should be an int") msg = "n_sides should be an int"
raise TypeError(msg)
if n_sides < 3: if n_sides < 3:
raise ValueError("n_sides should be an int > 2") msg = "n_sides should be an int > 2"
raise ValueError(msg)
# 1.2 Check `bounding_circle` has an appropriate value # 1.2 Check `bounding_circle` has an appropriate value
if not isinstance(bounding_circle, (list, tuple)): if not isinstance(bounding_circle, (list, tuple)):
raise TypeError("bounding_circle should be a tuple") msg = "bounding_circle should be a tuple"
raise TypeError(msg)
if len(bounding_circle) == 3: if len(bounding_circle) == 3:
*centroid, polygon_radius = bounding_circle *centroid, polygon_radius = bounding_circle
elif len(bounding_circle) == 2: elif len(bounding_circle) == 2:
centroid, polygon_radius = bounding_circle centroid, polygon_radius = bounding_circle
else: else:
raise ValueError( msg = (
"bounding_circle should contain 2D coordinates " "bounding_circle should contain 2D coordinates "
"and a radius (e.g. (x, y, r) or ((x, y), r) )" "and a radius (e.g. (x, y, r) or ((x, y), r) )"
) )
raise ValueError(msg)
if not all(isinstance(i, (int, float)) for i in (*centroid, polygon_radius)): if not all(isinstance(i, (int, float)) for i in (*centroid, polygon_radius)):
raise ValueError("bounding_circle should only contain numeric data") msg = "bounding_circle should only contain numeric data"
raise ValueError(msg)
if not len(centroid) == 2: if not len(centroid) == 2:
raise ValueError( msg = "bounding_circle centre should contain 2D coordinates (e.g. (x, y))"
"bounding_circle centre should contain 2D coordinates (e.g. (x, y))" raise ValueError(msg)
)
if polygon_radius <= 0: if polygon_radius <= 0:
raise ValueError("bounding_circle radius should be > 0") msg = "bounding_circle radius should be > 0"
raise ValueError(msg)
# 1.3 Check `rotation` has an appropriate value # 1.3 Check `rotation` has an appropriate value
if not isinstance(rotation, (int, float)): if not isinstance(rotation, (int, float)):
raise ValueError("rotation should be an int or float") msg = "rotation should be an int or float"
raise ValueError(msg)
# 2. Define Helper Functions # 2. Define Helper Functions
def _apply_rotation(point, degrees, centroid): def _apply_rotation(point, degrees, centroid):

View File

@ -124,7 +124,8 @@ class ImageFile(Image.Image):
raise SyntaxError(v) from v raise SyntaxError(v) from v
if not self.mode or self.size[0] <= 0 or self.size[1] <= 0: if not self.mode or self.size[0] <= 0 or self.size[1] <= 0:
raise SyntaxError("not identified by this driver") msg = "not identified by this driver"
raise SyntaxError(msg)
except BaseException: except BaseException:
# close the file only if we have opened it this constructor # close the file only if we have opened it this constructor
if self._exclusive_fp: if self._exclusive_fp:
@ -154,7 +155,8 @@ class ImageFile(Image.Image):
"""Load image data based on tile list""" """Load image data based on tile list"""
if self.tile is None: if self.tile is None:
raise OSError("cannot load this image") msg = "cannot load this image"
raise OSError(msg)
pixel = Image.Image.load(self) pixel = Image.Image.load(self)
if not self.tile: if not self.tile:
@ -249,16 +251,18 @@ class ImageFile(Image.Image):
if LOAD_TRUNCATED_IMAGES: if LOAD_TRUNCATED_IMAGES:
break break
else: else:
raise OSError("image file is truncated") from e msg = "image file is truncated"
raise OSError(msg) from e
if not s: # truncated jpeg if not s: # truncated jpeg
if LOAD_TRUNCATED_IMAGES: if LOAD_TRUNCATED_IMAGES:
break break
else: else:
raise OSError( msg = (
"image file is truncated " "image file is truncated "
f"({len(b)} bytes not processed)" f"({len(b)} bytes not processed)"
) )
raise OSError(msg)
b = b + s b = b + s
n, err_code = decoder.decode(b) n, err_code = decoder.decode(b)
@ -314,7 +318,8 @@ class ImageFile(Image.Image):
and frame >= self.n_frames + self._min_frame and frame >= self.n_frames + self._min_frame
) )
): ):
raise EOFError("attempt to seek outside sequence") msg = "attempt to seek outside sequence"
raise EOFError(msg)
return self.tell() != frame return self.tell() != frame
@ -328,12 +333,14 @@ class StubImageFile(ImageFile):
""" """
def _open(self): def _open(self):
raise NotImplementedError("StubImageFile subclass must implement _open") msg = "StubImageFile subclass must implement _open"
raise NotImplementedError(msg)
def load(self): def load(self):
loader = self._load() loader = self._load()
if loader is None: if loader is None:
raise OSError(f"cannot find loader for this {self.format} file") msg = f"cannot find loader for this {self.format} file"
raise OSError(msg)
image = loader.load(self) image = loader.load(self)
assert image is not None assert image is not None
# become the other object (!) # become the other object (!)
@ -343,7 +350,8 @@ class StubImageFile(ImageFile):
def _load(self): def _load(self):
"""(Hook) Find actual image loader.""" """(Hook) Find actual image loader."""
raise NotImplementedError("StubImageFile subclass must implement _load") msg = "StubImageFile subclass must implement _load"
raise NotImplementedError(msg)
class Parser: class Parser:
@ -468,9 +476,11 @@ class Parser:
self.feed(b"") self.feed(b"")
self.data = self.decoder = None self.data = self.decoder = None
if not self.finished: if not self.finished:
raise OSError("image was incomplete") msg = "image was incomplete"
raise OSError(msg)
if not self.image: if not self.image:
raise OSError("cannot parse this image") msg = "cannot parse this image"
raise OSError(msg)
if self.data: if self.data:
# incremental parsing not possible; reopen the file # incremental parsing not possible; reopen the file
# not that we have all data # not that we have all data
@ -535,7 +545,8 @@ def _encode_tile(im, fp, tile, bufsize, fh, exc=None):
# slight speedup: compress to real file object # slight speedup: compress to real file object
s = encoder.encode_to_file(fh, bufsize) s = encoder.encode_to_file(fh, bufsize)
if s < 0: if s < 0:
raise OSError(f"encoder error {s} when writing image file") from exc msg = f"encoder error {s} when writing image file"
raise OSError(msg) from exc
finally: finally:
encoder.cleanup() encoder.cleanup()
@ -558,7 +569,8 @@ def _safe_read(fp, size):
if size <= SAFEBLOCK: if size <= SAFEBLOCK:
data = fp.read(size) data = fp.read(size)
if len(data) < size: if len(data) < size:
raise OSError("Truncated File Read") msg = "Truncated File Read"
raise OSError(msg)
return data return data
data = [] data = []
remaining_size = size remaining_size = size
@ -569,7 +581,8 @@ def _safe_read(fp, size):
data.append(block) data.append(block)
remaining_size -= len(block) remaining_size -= len(block)
if sum(len(d) for d in data) < size: if sum(len(d) for d in data) < size:
raise OSError("Truncated File Read") msg = "Truncated File Read"
raise OSError(msg)
return b"".join(data) return b"".join(data)
@ -645,13 +658,15 @@ class PyCodec:
self.state.ysize = y1 - y0 self.state.ysize = y1 - y0
if self.state.xsize <= 0 or self.state.ysize <= 0: if self.state.xsize <= 0 or self.state.ysize <= 0:
raise ValueError("Size cannot be negative") msg = "Size cannot be negative"
raise ValueError(msg)
if ( if (
self.state.xsize + self.state.xoff > self.im.size[0] self.state.xsize + self.state.xoff > self.im.size[0]
or self.state.ysize + self.state.yoff > self.im.size[1] or self.state.ysize + self.state.yoff > self.im.size[1]
): ):
raise ValueError("Tile cannot extend outside image") msg = "Tile cannot extend outside image"
raise ValueError(msg)
class PyDecoder(PyCodec): class PyDecoder(PyCodec):
@ -696,9 +711,11 @@ class PyDecoder(PyCodec):
s = d.decode(data) s = d.decode(data)
if s[0] >= 0: if s[0] >= 0:
raise ValueError("not enough image data") msg = "not enough image data"
raise ValueError(msg)
if s[1] != 0: if s[1] != 0:
raise ValueError("cannot decode image data") msg = "cannot decode image data"
raise ValueError(msg)
class PyEncoder(PyCodec): class PyEncoder(PyCodec):

View File

@ -28,7 +28,8 @@ class MultibandFilter(Filter):
class BuiltinFilter(MultibandFilter): class BuiltinFilter(MultibandFilter):
def filter(self, image): def filter(self, image):
if image.mode == "P": if image.mode == "P":
raise ValueError("cannot filter palette images") msg = "cannot filter palette images"
raise ValueError(msg)
return image.filter(*self.filterargs) return image.filter(*self.filterargs)
@ -57,7 +58,8 @@ class Kernel(BuiltinFilter):
# default scale is sum of kernel # default scale is sum of kernel
scale = functools.reduce(lambda a, b: a + b, kernel) scale = functools.reduce(lambda a, b: a + b, kernel)
if size[0] * size[1] != len(kernel): if size[0] * size[1] != len(kernel):
raise ValueError("not enough coefficients in kernel") msg = "not enough coefficients in kernel"
raise ValueError(msg)
self.filterargs = size, scale, offset, kernel self.filterargs = size, scale, offset, kernel
@ -80,7 +82,8 @@ class RankFilter(Filter):
def filter(self, image): def filter(self, image):
if image.mode == "P": if image.mode == "P":
raise ValueError("cannot filter palette images") msg = "cannot filter palette images"
raise ValueError(msg)
image = image.expand(self.size // 2, self.size // 2) image = image.expand(self.size // 2, self.size // 2)
return image.rankfilter(self.size, self.rank) return image.rankfilter(self.size, self.rank)
@ -355,7 +358,8 @@ class Color3DLUT(MultibandFilter):
def __init__(self, size, table, channels=3, target_mode=None, **kwargs): def __init__(self, size, table, channels=3, target_mode=None, **kwargs):
if channels not in (3, 4): if channels not in (3, 4):
raise ValueError("Only 3 or 4 output channels are supported") msg = "Only 3 or 4 output channels are supported"
raise ValueError(msg)
self.size = size = self._check_size(size) self.size = size = self._check_size(size)
self.channels = channels self.channels = channels
self.mode = target_mode self.mode = target_mode
@ -395,19 +399,21 @@ class Color3DLUT(MultibandFilter):
table, raw_table = [], table table, raw_table = [], table
for pixel in raw_table: for pixel in raw_table:
if len(pixel) != channels: if len(pixel) != channels:
raise ValueError( msg = (
"The elements of the table should " "The elements of the table should "
"have a length of {}.".format(channels) f"have a length of {channels}."
) )
raise ValueError(msg)
table.extend(pixel) table.extend(pixel)
if wrong_size or len(table) != items * channels: if wrong_size or len(table) != items * channels:
raise ValueError( msg = (
"The table should have either channels * size**3 float items " "The table should have either channels * size**3 float items "
"or size**3 items of channels-sized tuples with floats. " "or size**3 items of channels-sized tuples with floats. "
f"Table should be: {channels}x{size[0]}x{size[1]}x{size[2]}. " f"Table should be: {channels}x{size[0]}x{size[1]}x{size[2]}. "
f"Actual length: {len(table)}" f"Actual length: {len(table)}"
) )
raise ValueError(msg)
self.table = table self.table = table
@staticmethod @staticmethod
@ -415,15 +421,15 @@ class Color3DLUT(MultibandFilter):
try: try:
_, _, _ = size _, _, _ = size
except ValueError as e: except ValueError as e:
raise ValueError( msg = "Size should be either an integer or a tuple of three integers."
"Size should be either an integer or a tuple of three integers." raise ValueError(msg) from e
) from e
except TypeError: except TypeError:
size = (size, size, size) size = (size, size, size)
size = [int(x) for x in size] size = [int(x) for x in size]
for size_1d in size: for size_1d in size:
if not 2 <= size_1d <= 65: if not 2 <= size_1d <= 65:
raise ValueError("Size should be in [2, 65] range.") msg = "Size should be in [2, 65] range."
raise ValueError(msg)
return size return size
@classmethod @classmethod
@ -441,7 +447,8 @@ class Color3DLUT(MultibandFilter):
""" """
size_1d, size_2d, size_3d = cls._check_size(size) size_1d, size_2d, size_3d = cls._check_size(size)
if channels not in (3, 4): if channels not in (3, 4):
raise ValueError("Only 3 or 4 output channels are supported") msg = "Only 3 or 4 output channels are supported"
raise ValueError(msg)
table = [0] * (size_1d * size_2d * size_3d * channels) table = [0] * (size_1d * size_2d * size_3d * channels)
idx_out = 0 idx_out = 0
@ -481,7 +488,8 @@ class Color3DLUT(MultibandFilter):
lookup table. lookup table.
""" """
if channels not in (None, 3, 4): if channels not in (None, 3, 4):
raise ValueError("Only 3 or 4 output channels are supported") msg = "Only 3 or 4 output channels are supported"
raise ValueError(msg)
ch_in = self.channels ch_in = self.channels
ch_out = channels or ch_in ch_out = channels or ch_in
size_1d, size_2d, size_3d = self.size size_1d, size_2d, size_3d = self.size

View File

@ -50,13 +50,15 @@ def __getattr__(name):
if name in enum.__members__: if name in enum.__members__:
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
return enum[name] return enum[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'") msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)
class _ImagingFtNotInstalled: class _ImagingFtNotInstalled:
# module placeholder # module placeholder
def __getattr__(self, id): def __getattr__(self, id):
raise ImportError("The _imagingft C module is not installed") msg = "The _imagingft C module is not installed"
raise ImportError(msg)
try: try:
@ -105,7 +107,8 @@ class ImageFont:
else: else:
if image: if image:
image.close() image.close()
raise OSError("cannot find glyph data file") msg = "cannot find glyph data file"
raise OSError(msg)
self.file = fullname self.file = fullname
@ -116,7 +119,8 @@ class ImageFont:
# read PILfont header # read PILfont header
if file.readline() != b"PILfont\n": if file.readline() != b"PILfont\n":
raise SyntaxError("Not a PILfont file") msg = "Not a PILfont file"
raise SyntaxError(msg)
file.readline().split(b";") file.readline().split(b";")
self.info = [] # FIXME: should be a dictionary self.info = [] # FIXME: should be a dictionary
while True: while True:
@ -130,7 +134,8 @@ class ImageFont:
# check image # check image
if image.mode not in ("1", "L"): if image.mode not in ("1", "L"):
raise TypeError("invalid font image mode") msg = "invalid font image mode"
raise TypeError(msg)
image.load() image.load()
@ -817,7 +822,8 @@ class FreeTypeFont:
try: try:
names = self.font.getvarnames() names = self.font.getvarnames()
except AttributeError as e: except AttributeError as e:
raise NotImplementedError("FreeType 2.9.1 or greater is required") from e msg = "FreeType 2.9.1 or greater is required"
raise NotImplementedError(msg) from e
return [name.replace(b"\x00", b"") for name in names] return [name.replace(b"\x00", b"") for name in names]
def set_variation_by_name(self, name): def set_variation_by_name(self, name):
@ -847,7 +853,8 @@ class FreeTypeFont:
try: try:
axes = self.font.getvaraxes() axes = self.font.getvaraxes()
except AttributeError as e: except AttributeError as e:
raise NotImplementedError("FreeType 2.9.1 or greater is required") from e msg = "FreeType 2.9.1 or greater is required"
raise NotImplementedError(msg) from e
for axis in axes: for axis in axes:
axis["name"] = axis["name"].replace(b"\x00", b"") axis["name"] = axis["name"].replace(b"\x00", b"")
return axes return axes
@ -860,7 +867,8 @@ class FreeTypeFont:
try: try:
self.font.setvaraxes(axes) self.font.setvaraxes(axes)
except AttributeError as e: except AttributeError as e:
raise NotImplementedError("FreeType 2.9.1 or greater is required") from e msg = "FreeType 2.9.1 or greater is required"
raise NotImplementedError(msg) from e
class TransposedFont: class TransposedFont:
@ -914,9 +922,8 @@ class TransposedFont:
def getlength(self, text, *args, **kwargs): def getlength(self, text, *args, **kwargs):
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270): if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
raise ValueError( msg = "text length is undefined for text rotated by 90 or 270 degrees"
"text length is undefined for text rotated by 90 or 270 degrees" raise ValueError(msg)
)
return self.font.getlength(text, *args, **kwargs) return self.font.getlength(text, *args, **kwargs)
@ -1061,7 +1068,8 @@ def load_path(filename):
return load(os.path.join(directory, filename)) return load(os.path.join(directory, filename))
except OSError: except OSError:
pass pass
raise OSError("cannot find font file") msg = "cannot find font file"
raise OSError(msg)
def load_default(): def load_default():

View File

@ -75,7 +75,8 @@ def grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=N
return im return im
# use xdisplay=None for default display on non-win32/macOS systems # use xdisplay=None for default display on non-win32/macOS systems
if not Image.core.HAVE_XCB: if not Image.core.HAVE_XCB:
raise OSError("Pillow was built without XCB support") msg = "Pillow was built without XCB support"
raise OSError(msg)
size, data = Image.core.grabscreen_x11(xdisplay) size, data = Image.core.grabscreen_x11(xdisplay)
im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1) im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1)
if bbox: if bbox:
@ -137,9 +138,8 @@ def grabclipboard():
elif shutil.which("xclip"): elif shutil.which("xclip"):
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"] args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
else: else:
raise NotImplementedError( msg = "wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
"wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux" raise NotImplementedError(msg)
)
fh, filepath = tempfile.mkstemp() fh, filepath = tempfile.mkstemp()
subprocess.call(args, stdout=fh) subprocess.call(args, stdout=fh)
os.close(fh) os.close(fh)

View File

@ -39,7 +39,8 @@ class _Operand:
elif im1.im.mode in ("I", "F"): elif im1.im.mode in ("I", "F"):
return im1.im return im1.im
else: else:
raise ValueError(f"unsupported mode: {im1.im.mode}") msg = f"unsupported mode: {im1.im.mode}"
raise ValueError(msg)
else: else:
# argument was a constant # argument was a constant
if _isconstant(im1) and self.im.mode in ("1", "L", "I"): if _isconstant(im1) and self.im.mode in ("1", "L", "I"):
@ -56,7 +57,8 @@ class _Operand:
try: try:
op = getattr(_imagingmath, op + "_" + im1.mode) op = getattr(_imagingmath, op + "_" + im1.mode)
except AttributeError as e: except AttributeError as e:
raise TypeError(f"bad operand type for '{op}'") from e msg = f"bad operand type for '{op}'"
raise TypeError(msg) from e
_imagingmath.unop(op, out.im.id, im1.im.id) _imagingmath.unop(op, out.im.id, im1.im.id)
else: else:
# binary operation # binary operation
@ -80,7 +82,8 @@ class _Operand:
try: try:
op = getattr(_imagingmath, op + "_" + im1.mode) op = getattr(_imagingmath, op + "_" + im1.mode)
except AttributeError as e: except AttributeError as e:
raise TypeError(f"bad operand type for '{op}'") from e msg = f"bad operand type for '{op}'"
raise TypeError(msg) from e
_imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id) _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id)
return _Operand(out) return _Operand(out)
@ -249,7 +252,8 @@ def eval(expression, _dict={}, **kw):
for name in code.co_names: for name in code.co_names:
if name not in args and name != "abs": if name not in args and name != "abs":
raise ValueError(f"'{name}' not allowed") msg = f"'{name}' not allowed"
raise ValueError(msg)
scan(compiled_code) scan(compiled_code)
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args) out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)

View File

@ -81,7 +81,8 @@ class LutBuilder:
], ],
} }
if op_name not in known_patterns: if op_name not in known_patterns:
raise Exception("Unknown pattern " + op_name + "!") msg = "Unknown pattern " + op_name + "!"
raise Exception(msg)
self.patterns = known_patterns[op_name] self.patterns = known_patterns[op_name]
@ -193,10 +194,12 @@ class MorphOp:
Returns a tuple of the number of changed pixels and the Returns a tuple of the number of changed pixels and the
morphed image""" morphed image"""
if self.lut is None: if self.lut is None:
raise Exception("No operator loaded") msg = "No operator loaded"
raise Exception(msg)
if image.mode != "L": if image.mode != "L":
raise ValueError("Image mode must be L") msg = "Image mode must be L"
raise ValueError(msg)
outimage = Image.new(image.mode, image.size, None) outimage = Image.new(image.mode, image.size, None)
count = _imagingmorph.apply(bytes(self.lut), image.im.id, outimage.im.id) count = _imagingmorph.apply(bytes(self.lut), image.im.id, outimage.im.id)
return count, outimage return count, outimage
@ -208,10 +211,12 @@ class MorphOp:
Returns a list of tuples of (x,y) coordinates Returns a list of tuples of (x,y) coordinates
of all matching pixels. See :ref:`coordinate-system`.""" of all matching pixels. See :ref:`coordinate-system`."""
if self.lut is None: if self.lut is None:
raise Exception("No operator loaded") msg = "No operator loaded"
raise Exception(msg)
if image.mode != "L": if image.mode != "L":
raise ValueError("Image mode must be L") msg = "Image mode must be L"
raise ValueError(msg)
return _imagingmorph.match(bytes(self.lut), image.im.id) return _imagingmorph.match(bytes(self.lut), image.im.id)
def get_on_pixels(self, image): def get_on_pixels(self, image):
@ -221,7 +226,8 @@ class MorphOp:
of all matching pixels. See :ref:`coordinate-system`.""" of all matching pixels. See :ref:`coordinate-system`."""
if image.mode != "L": if image.mode != "L":
raise ValueError("Image mode must be L") msg = "Image mode must be L"
raise ValueError(msg)
return _imagingmorph.get_on_pixels(image.im.id) return _imagingmorph.get_on_pixels(image.im.id)
def load_lut(self, filename): def load_lut(self, filename):
@ -231,12 +237,14 @@ class MorphOp:
if len(self.lut) != LUT_SIZE: if len(self.lut) != LUT_SIZE:
self.lut = None self.lut = None
raise Exception("Wrong size operator file!") msg = "Wrong size operator file!"
raise Exception(msg)
def save_lut(self, filename): def save_lut(self, filename):
"""Save an operator to an mrl file""" """Save an operator to an mrl file"""
if self.lut is None: if self.lut is None:
raise Exception("No operator loaded") msg = "No operator loaded"
raise Exception(msg)
with open(filename, "wb") as f: with open(filename, "wb") as f:
f.write(self.lut) f.write(self.lut)

View File

@ -49,13 +49,15 @@ def _color(color, mode):
def _lut(image, lut): def _lut(image, lut):
if image.mode == "P": if image.mode == "P":
# FIXME: apply to lookup table, not image data # FIXME: apply to lookup table, not image data
raise NotImplementedError("mode P support coming soon") msg = "mode P support coming soon"
raise NotImplementedError(msg)
elif image.mode in ("L", "RGB"): elif image.mode in ("L", "RGB"):
if image.mode == "RGB" and len(lut) == 256: if image.mode == "RGB" and len(lut) == 256:
lut = lut + lut + lut lut = lut + lut + lut
return image.point(lut) return image.point(lut)
else: else:
raise OSError("not supported for this image mode") msg = "not supported for this image mode"
raise OSError(msg)
# #
@ -332,7 +334,8 @@ def scale(image, factor, resample=Image.Resampling.BICUBIC):
if factor == 1: if factor == 1:
return image.copy() return image.copy()
elif factor <= 0: elif factor <= 0:
raise ValueError("the factor must be greater than 0") msg = "the factor must be greater than 0"
raise ValueError(msg)
else: else:
size = (round(factor * image.width), round(factor * image.height)) size = (round(factor * image.width), round(factor * image.height))
return image.resize(size, resample) return image.resize(size, resample)

View File

@ -42,7 +42,8 @@ class ImagePalette:
if size != 0: if size != 0:
deprecate("The size parameter", 10, None) deprecate("The size parameter", 10, None)
if size != len(self.palette): if size != len(self.palette):
raise ValueError("wrong palette size") msg = "wrong palette size"
raise ValueError(msg)
@property @property
def palette(self): def palette(self):
@ -97,7 +98,8 @@ class ImagePalette:
.. warning:: This method is experimental. .. warning:: This method is experimental.
""" """
if self.rawmode: if self.rawmode:
raise ValueError("palette contains raw palette data") msg = "palette contains raw palette data"
raise ValueError(msg)
if isinstance(self.palette, bytes): if isinstance(self.palette, bytes):
return self.palette return self.palette
arr = array.array("B", self.palette) arr = array.array("B", self.palette)
@ -112,14 +114,14 @@ class ImagePalette:
.. warning:: This method is experimental. .. warning:: This method is experimental.
""" """
if self.rawmode: if self.rawmode:
raise ValueError("palette contains raw palette data") msg = "palette contains raw palette data"
raise ValueError(msg)
if isinstance(color, tuple): if isinstance(color, tuple):
if self.mode == "RGB": if self.mode == "RGB":
if len(color) == 4: if len(color) == 4:
if color[3] != 255: if color[3] != 255:
raise ValueError( msg = "cannot add non-opaque RGBA color to RGB palette"
"cannot add non-opaque RGBA color to RGB palette" raise ValueError(msg)
)
color = color[:3] color = color[:3]
elif self.mode == "RGBA": elif self.mode == "RGBA":
if len(color) == 3: if len(color) == 3:
@ -147,7 +149,8 @@ class ImagePalette:
index = i index = i
break break
if index >= 256: if index >= 256:
raise ValueError("cannot allocate more than 256 colors") from e msg = "cannot allocate more than 256 colors"
raise ValueError(msg) from e
self.colors[color] = index self.colors[color] = index
if index * 3 < len(self.palette): if index * 3 < len(self.palette):
self._palette = ( self._palette = (
@ -160,7 +163,8 @@ class ImagePalette:
self.dirty = 1 self.dirty = 1
return index return index
else: else:
raise ValueError(f"unknown color specifier: {repr(color)}") msg = f"unknown color specifier: {repr(color)}"
raise ValueError(msg)
def save(self, fp): def save(self, fp):
"""Save palette to text file. """Save palette to text file.
@ -168,7 +172,8 @@ class ImagePalette:
.. warning:: This method is experimental. .. warning:: This method is experimental.
""" """
if self.rawmode: if self.rawmode:
raise ValueError("palette contains raw palette data") msg = "palette contains raw palette data"
raise ValueError(msg)
if isinstance(fp, str): if isinstance(fp, str):
fp = open(fp, "w") fp = open(fp, "w")
fp.write("# Palette\n") fp.write("# Palette\n")
@ -263,6 +268,7 @@ def load(filename):
# traceback.print_exc() # traceback.print_exc()
pass pass
else: else:
raise OSError("cannot load palette") msg = "cannot load palette"
raise OSError(msg)
return lut # data, rawmode return lut # data, rawmode

View File

@ -179,7 +179,8 @@ def _toqclass_helper(im):
else: else:
if exclusive_fp: if exclusive_fp:
im.close() im.close()
raise ValueError(f"unsupported image mode {repr(im.mode)}") msg = f"unsupported image mode {repr(im.mode)}"
raise ValueError(msg)
size = im.size size = im.size
__data = data or align8to32(im.tobytes(), size[0], im.mode) __data = data or align8to32(im.tobytes(), size[0], im.mode)

View File

@ -30,7 +30,8 @@ class Iterator:
def __init__(self, im): def __init__(self, im):
if not hasattr(im, "seek"): if not hasattr(im, "seek"):
raise AttributeError("im must have seek method") msg = "im must have seek method"
raise AttributeError(msg)
self.im = im self.im = im
self.position = getattr(self.im, "_min_frame", 0) self.position = getattr(self.im, "_min_frame", 0)

View File

@ -124,7 +124,8 @@ class Viewer:
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
os.system(self.get_command(path, **options)) # nosec os.system(self.get_command(path, **options)) # nosec
return 1 return 1
@ -176,7 +177,8 @@ class MacViewer(Viewer):
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
subprocess.call(["open", "-a", "Preview.app", path]) subprocess.call(["open", "-a", "Preview.app", path])
executable = sys.executable or shutil.which("python3") executable = sys.executable or shutil.which("python3")
if executable: if executable:
@ -226,7 +228,8 @@ class XDGViewer(UnixViewer):
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
subprocess.Popen(["xdg-open", path]) subprocess.Popen(["xdg-open", path])
return 1 return 1
@ -255,7 +258,8 @@ class DisplayViewer(UnixViewer):
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
args = ["display"] args = ["display"]
title = options.get("title") title = options.get("title")
if title: if title:
@ -286,7 +290,8 @@ class GmDisplayViewer(UnixViewer):
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
subprocess.Popen(["gm", "display", path]) subprocess.Popen(["gm", "display", path])
return 1 return 1
@ -311,7 +316,8 @@ class EogViewer(UnixViewer):
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
subprocess.Popen(["eog", "-n", path]) subprocess.Popen(["eog", "-n", path])
return 1 return 1
@ -342,7 +348,8 @@ class XVViewer(UnixViewer):
deprecate("The 'file' argument", 10, "'path'") deprecate("The 'file' argument", 10, "'path'")
path = options.pop("file") path = options.pop("file")
else: else:
raise TypeError("Missing required argument: 'path'") msg = "Missing required argument: 'path'"
raise TypeError(msg)
args = ["xv"] args = ["xv"]
title = options.get("title") title = options.get("title")
if title: if title:

View File

@ -36,7 +36,8 @@ class Stat:
except AttributeError: except AttributeError:
self.h = image_or_list # assume it to be a histogram list self.h = image_or_list # assume it to be a histogram list
if not isinstance(self.h, list): if not isinstance(self.h, list):
raise TypeError("first argument must be image or list") msg = "first argument must be image or list"
raise TypeError(msg)
self.bands = list(range(len(self.h) // 256)) self.bands = list(range(len(self.h) // 256))
def __getattr__(self, id): def __getattr__(self, id):

View File

@ -284,7 +284,8 @@ def _show(image, title):
super().__init__(master, image=self.image, bg="black", bd=0) super().__init__(master, image=self.image, bg="black", bd=0)
if not tkinter._default_root: if not tkinter._default_root:
raise OSError("tkinter not initialized") msg = "tkinter not initialized"
raise OSError(msg)
top = tkinter.Toplevel() top = tkinter.Toplevel()
if title: if title:
top.title(title) top.title(title)

View File

@ -41,7 +41,8 @@ class ImtImageFile(ImageFile.ImageFile):
buffer = self.fp.read(100) buffer = self.fp.read(100)
if b"\n" not in buffer: if b"\n" not in buffer:
raise SyntaxError("not an IM file") msg = "not an IM file"
raise SyntaxError(msg)
xsize = ysize = 0 xsize = ysize = 0

View File

@ -66,12 +66,14 @@ class IptcImageFile(ImageFile.ImageFile):
# syntax # syntax
if s[0] != 0x1C or tag[0] < 1 or tag[0] > 9: if s[0] != 0x1C or tag[0] < 1 or tag[0] > 9:
raise SyntaxError("invalid IPTC/NAA file") msg = "invalid IPTC/NAA file"
raise SyntaxError(msg)
# field size # field size
size = s[3] size = s[3]
if size > 132: if size > 132:
raise OSError("illegal field length in IPTC/NAA file") msg = "illegal field length in IPTC/NAA file"
raise OSError(msg)
elif size == 128: elif size == 128:
size = 0 size = 0
elif size > 128: elif size > 128:
@ -122,7 +124,8 @@ class IptcImageFile(ImageFile.ImageFile):
try: try:
compression = COMPRESSION[self.getint((3, 120))] compression = COMPRESSION[self.getint((3, 120))]
except KeyError as e: except KeyError as e:
raise OSError("Unknown IPTC image compression") from e msg = "Unknown IPTC image compression"
raise OSError(msg) from e
# tile # tile
if tag == (8, 10): if tag == (8, 10):

View File

@ -44,13 +44,13 @@ class BoxReader:
def _read_bytes(self, num_bytes): def _read_bytes(self, num_bytes):
if not self._can_read(num_bytes): if not self._can_read(num_bytes):
raise SyntaxError("Not enough data in header") msg = "Not enough data in header"
raise SyntaxError(msg)
data = self.fp.read(num_bytes) data = self.fp.read(num_bytes)
if len(data) < num_bytes: if len(data) < num_bytes:
raise OSError( msg = f"Expected to read {num_bytes} bytes but only got {len(data)}."
f"Expected to read {num_bytes} bytes but only got {len(data)}." raise OSError(msg)
)
if self.remaining_in_box > 0: if self.remaining_in_box > 0:
self.remaining_in_box -= num_bytes self.remaining_in_box -= num_bytes
@ -87,7 +87,8 @@ class BoxReader:
hlen = 8 hlen = 8
if lbox < hlen or not self._can_read(lbox - hlen): if lbox < hlen or not self._can_read(lbox - hlen):
raise SyntaxError("Invalid header length") msg = "Invalid header length"
raise SyntaxError(msg)
self.remaining_in_box = lbox - hlen self.remaining_in_box = lbox - hlen
return tbox return tbox
@ -189,7 +190,8 @@ def _parse_jp2_header(fp):
break break
if size is None or mode is None: if size is None or mode is None:
raise SyntaxError("Malformed JP2 header") msg = "Malformed JP2 header"
raise SyntaxError(msg)
return size, mode, mimetype, dpi return size, mode, mimetype, dpi
@ -217,10 +219,12 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
if dpi is not None: if dpi is not None:
self.info["dpi"] = dpi self.info["dpi"] = dpi
else: else:
raise SyntaxError("not a JPEG 2000 file") msg = "not a JPEG 2000 file"
raise SyntaxError(msg)
if self.size is None or self.mode is None: if self.size is None or self.mode is None:
raise SyntaxError("unable to determine size/mode") msg = "unable to determine size/mode"
raise SyntaxError(msg)
self._reduce = 0 self._reduce = 0
self.layers = 0 self.layers = 0
@ -312,7 +316,8 @@ def _save(im, fp, filename):
] ]
) )
): ):
raise ValueError("quality_layers must be a sequence of numbers") msg = "quality_layers must be a sequence of numbers"
raise ValueError(msg)
num_resolutions = info.get("num_resolutions", 0) num_resolutions = info.get("num_resolutions", 0)
cblk_size = info.get("codeblock_size", None) cblk_size = info.get("codeblock_size", None)

View File

@ -204,7 +204,8 @@ def SOF(self, marker):
self.bits = s[0] self.bits = s[0]
if self.bits != 8: if self.bits != 8:
raise SyntaxError(f"cannot handle {self.bits}-bit layers") msg = f"cannot handle {self.bits}-bit layers"
raise SyntaxError(msg)
self.layers = s[5] self.layers = s[5]
if self.layers == 1: if self.layers == 1:
@ -214,7 +215,8 @@ def SOF(self, marker):
elif self.layers == 4: elif self.layers == 4:
self.mode = "CMYK" self.mode = "CMYK"
else: else:
raise SyntaxError(f"cannot handle {self.layers}-layer images") msg = f"cannot handle {self.layers}-layer images"
raise SyntaxError(msg)
if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]: if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
self.info["progressive"] = self.info["progression"] = 1 self.info["progressive"] = self.info["progression"] = 1
@ -253,7 +255,8 @@ def DQT(self, marker):
precision = 1 if (v // 16 == 0) else 2 # in bytes precision = 1 if (v // 16 == 0) else 2 # in bytes
qt_length = 1 + precision * 64 qt_length = 1 + precision * 64
if len(s) < qt_length: if len(s) < qt_length:
raise SyntaxError("bad quantization table marker") msg = "bad quantization table marker"
raise SyntaxError(msg)
data = array.array("B" if precision == 1 else "H", s[1:qt_length]) data = array.array("B" if precision == 1 else "H", s[1:qt_length])
if sys.byteorder == "little" and precision > 1: if sys.byteorder == "little" and precision > 1:
data.byteswap() # the values are always big-endian data.byteswap() # the values are always big-endian
@ -350,7 +353,8 @@ class JpegImageFile(ImageFile.ImageFile):
s = self.fp.read(3) s = self.fp.read(3)
if not _accept(s): if not _accept(s):
raise SyntaxError("not a JPEG file") msg = "not a JPEG file"
raise SyntaxError(msg)
s = b"\xFF" s = b"\xFF"
# Create attributes # Create attributes
@ -394,7 +398,8 @@ class JpegImageFile(ImageFile.ImageFile):
elif i == 0xFF00: # Skip extraneous data (escaped 0xFF) elif i == 0xFF00: # Skip extraneous data (escaped 0xFF)
s = self.fp.read(1) s = self.fp.read(1)
else: else:
raise SyntaxError("no marker found") msg = "no marker found"
raise SyntaxError(msg)
def load_read(self, read_bytes): def load_read(self, read_bytes):
""" """
@ -458,7 +463,8 @@ class JpegImageFile(ImageFile.ImageFile):
if os.path.exists(self.filename): if os.path.exists(self.filename):
subprocess.check_call(["djpeg", "-outfile", path, self.filename]) subprocess.check_call(["djpeg", "-outfile", path, self.filename])
else: else:
raise ValueError("Invalid Filename") msg = "Invalid Filename"
raise ValueError(msg)
try: try:
with Image.open(path) as _im: with Image.open(path) as _im:
@ -524,12 +530,14 @@ def _getmp(self):
info.load(file_contents) info.load(file_contents)
mp = dict(info) mp = dict(info)
except Exception as e: except Exception as e:
raise SyntaxError("malformed MP Index (unreadable directory)") from e msg = "malformed MP Index (unreadable directory)"
raise SyntaxError(msg) from e
# it's an error not to have a number of images # it's an error not to have a number of images
try: try:
quant = mp[0xB001] quant = mp[0xB001]
except KeyError as e: except KeyError as e:
raise SyntaxError("malformed MP Index (no number of images)") from e msg = "malformed MP Index (no number of images)"
raise SyntaxError(msg) from e
# get MP entries # get MP entries
mpentries = [] mpentries = []
try: try:
@ -551,7 +559,8 @@ def _getmp(self):
if mpentryattr["ImageDataFormat"] == 0: if mpentryattr["ImageDataFormat"] == 0:
mpentryattr["ImageDataFormat"] = "JPEG" mpentryattr["ImageDataFormat"] = "JPEG"
else: else:
raise SyntaxError("unsupported picture format in MPO") msg = "unsupported picture format in MPO"
raise SyntaxError(msg)
mptypemap = { mptypemap = {
0x000000: "Undefined", 0x000000: "Undefined",
0x010001: "Large Thumbnail (VGA Equivalent)", 0x010001: "Large Thumbnail (VGA Equivalent)",
@ -566,7 +575,8 @@ def _getmp(self):
mpentries.append(mpentry) mpentries.append(mpentry)
mp[0xB002] = mpentries mp[0xB002] = mpentries
except KeyError as e: except KeyError as e:
raise SyntaxError("malformed MP Index (bad MP Entry)") from e msg = "malformed MP Index (bad MP Entry)"
raise SyntaxError(msg) from e
# Next we should try and parse the individual image unique ID list; # Next we should try and parse the individual image unique ID list;
# we don't because I've never seen this actually used in a real MPO # we don't because I've never seen this actually used in a real MPO
# file and so can't test it. # file and so can't test it.
@ -626,12 +636,14 @@ def get_sampling(im):
def _save(im, fp, filename): def _save(im, fp, filename):
if im.width == 0 or im.height == 0: if im.width == 0 or im.height == 0:
raise ValueError("cannot write empty image as JPEG") msg = "cannot write empty image as JPEG"
raise ValueError(msg)
try: try:
rawmode = RAWMODE[im.mode] rawmode = RAWMODE[im.mode]
except KeyError as e: except KeyError as e:
raise OSError(f"cannot write mode {im.mode} as JPEG") from e msg = f"cannot write mode {im.mode} as JPEG"
raise OSError(msg) from e
info = im.encoderinfo info = im.encoderinfo
@ -651,7 +663,8 @@ def _save(im, fp, filename):
subsampling = preset.get("subsampling", -1) subsampling = preset.get("subsampling", -1)
qtables = preset.get("quantization") qtables = preset.get("quantization")
elif not isinstance(quality, int): elif not isinstance(quality, int):
raise ValueError("Invalid quality setting") msg = "Invalid quality setting"
raise ValueError(msg)
else: else:
if subsampling in presets: if subsampling in presets:
subsampling = presets[subsampling].get("subsampling", -1) subsampling = presets[subsampling].get("subsampling", -1)
@ -670,7 +683,8 @@ def _save(im, fp, filename):
subsampling = 2 subsampling = 2
elif subsampling == "keep": elif subsampling == "keep":
if im.format != "JPEG": if im.format != "JPEG":
raise ValueError("Cannot use 'keep' when original image is not a JPEG") msg = "Cannot use 'keep' when original image is not a JPEG"
raise ValueError(msg)
subsampling = get_sampling(im) subsampling = get_sampling(im)
def validate_qtables(qtables): def validate_qtables(qtables):
@ -684,7 +698,8 @@ def _save(im, fp, filename):
for num in line.split("#", 1)[0].split() for num in line.split("#", 1)[0].split()
] ]
except ValueError as e: except ValueError as e:
raise ValueError("Invalid quantization table") from e msg = "Invalid quantization table"
raise ValueError(msg) from e
else: else:
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)] qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
if isinstance(qtables, (tuple, list, dict)): if isinstance(qtables, (tuple, list, dict)):
@ -695,21 +710,24 @@ def _save(im, fp, filename):
elif isinstance(qtables, tuple): elif isinstance(qtables, tuple):
qtables = list(qtables) qtables = list(qtables)
if not (0 < len(qtables) < 5): if not (0 < len(qtables) < 5):
raise ValueError("None or too many quantization tables") msg = "None or too many quantization tables"
raise ValueError(msg)
for idx, table in enumerate(qtables): for idx, table in enumerate(qtables):
try: try:
if len(table) != 64: if len(table) != 64:
raise TypeError raise TypeError
table = array.array("H", table) table = array.array("H", table)
except TypeError as e: except TypeError as e:
raise ValueError("Invalid quantization table") from e msg = "Invalid quantization table"
raise ValueError(msg) from e
else: else:
qtables[idx] = list(table) qtables[idx] = list(table)
return qtables return qtables
if qtables == "keep": if qtables == "keep":
if im.format != "JPEG": if im.format != "JPEG":
raise ValueError("Cannot use 'keep' when original image is not a JPEG") msg = "Cannot use 'keep' when original image is not a JPEG"
raise ValueError(msg)
qtables = getattr(im, "quantization", None) qtables = getattr(im, "quantization", None)
qtables = validate_qtables(qtables) qtables = validate_qtables(qtables)

View File

@ -39,7 +39,8 @@ class McIdasImageFile(ImageFile.ImageFile):
# parse area file directory # parse area file directory
s = self.fp.read(256) s = self.fp.read(256)
if not _accept(s) or len(s) != 256: if not _accept(s) or len(s) != 256:
raise SyntaxError("not an McIdas area file") msg = "not an McIdas area file"
raise SyntaxError(msg)
self.area_descriptor_raw = s self.area_descriptor_raw = s
self.area_descriptor = w = [0] + list(struct.unpack("!64i", s)) self.area_descriptor = w = [0] + list(struct.unpack("!64i", s))
@ -56,7 +57,8 @@ class McIdasImageFile(ImageFile.ImageFile):
mode = "I" mode = "I"
rawmode = "I;32B" rawmode = "I;32B"
else: else:
raise SyntaxError("unsupported McIdas format") msg = "unsupported McIdas format"
raise SyntaxError(msg)
self.mode = mode self.mode = mode
self._size = w[10], w[9] self._size = w[10], w[9]

View File

@ -47,7 +47,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
try: try:
self.ole = olefile.OleFileIO(self.fp) self.ole = olefile.OleFileIO(self.fp)
except OSError as e: except OSError as e:
raise SyntaxError("not an MIC file; invalid OLE file") from e msg = "not an MIC file; invalid OLE file"
raise SyntaxError(msg) from e
# find ACI subfiles with Image members (maybe not the # find ACI subfiles with Image members (maybe not the
# best way to identify MIC files, but what the... ;-) # best way to identify MIC files, but what the... ;-)
@ -60,7 +61,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
# if we didn't find any images, this is probably not # if we didn't find any images, this is probably not
# an MIC file. # an MIC file.
if not self.images: if not self.images:
raise SyntaxError("not an MIC file; no image entries") msg = "not an MIC file; no image entries"
raise SyntaxError(msg)
self.frame = None self.frame = None
self._n_frames = len(self.images) self._n_frames = len(self.images)
@ -77,7 +79,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
try: try:
filename = self.images[frame] filename = self.images[frame]
except IndexError as e: except IndexError as e:
raise EOFError("no such frame") from e msg = "no such frame"
raise EOFError(msg) from e
self.fp = self.ole.openstream(filename) self.fp = self.ole.openstream(filename)

View File

@ -67,7 +67,8 @@ class MpegImageFile(ImageFile.ImageFile):
s = BitStream(self.fp) s = BitStream(self.fp)
if s.read(32) != 0x1B3: if s.read(32) != 0x1B3:
raise SyntaxError("not an MPEG file") msg = "not an MPEG file"
raise SyntaxError(msg)
self.mode = "RGB" self.mode = "RGB"
self._size = s.read(12), s.read(12) self._size = s.read(12), s.read(12)

View File

@ -143,7 +143,8 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
self.fp.seek(self.offset + 2) # skip SOI marker self.fp.seek(self.offset + 2) # skip SOI marker
segment = self.fp.read(2) segment = self.fp.read(2)
if not segment: if not segment:
raise ValueError("No data found for frame") msg = "No data found for frame"
raise ValueError(msg)
self._size = self._initial_size self._size = self._initial_size
if i16(segment) == 0xFFE1: # APP1 if i16(segment) == 0xFFE1: # APP1
n = i16(self.fp.read(2)) - 2 n = i16(self.fp.read(2)) - 2

View File

@ -53,14 +53,16 @@ class MspImageFile(ImageFile.ImageFile):
# Header # Header
s = self.fp.read(32) s = self.fp.read(32)
if not _accept(s): if not _accept(s):
raise SyntaxError("not an MSP file") msg = "not an MSP file"
raise SyntaxError(msg)
# Header checksum # Header checksum
checksum = 0 checksum = 0
for i in range(0, 32, 2): for i in range(0, 32, 2):
checksum = checksum ^ i16(s, i) checksum = checksum ^ i16(s, i)
if checksum != 0: if checksum != 0:
raise SyntaxError("bad MSP checksum") msg = "bad MSP checksum"
raise SyntaxError(msg)
self.mode = "1" self.mode = "1"
self._size = i16(s, 4), i16(s, 6) self._size = i16(s, 4), i16(s, 6)
@ -118,7 +120,8 @@ class MspDecoder(ImageFile.PyDecoder):
f"<{self.state.ysize}H", self.fd.read(self.state.ysize * 2) f"<{self.state.ysize}H", self.fd.read(self.state.ysize * 2)
) )
except struct.error as e: except struct.error as e:
raise OSError("Truncated MSP file in row map") from e msg = "Truncated MSP file in row map"
raise OSError(msg) from e
for x, rowlen in enumerate(rowmap): for x, rowlen in enumerate(rowmap):
try: try:
@ -127,9 +130,8 @@ class MspDecoder(ImageFile.PyDecoder):
continue continue
row = self.fd.read(rowlen) row = self.fd.read(rowlen)
if len(row) != rowlen: if len(row) != rowlen:
raise OSError( msg = f"Truncated MSP file, expected {rowlen} bytes on row {x}"
"Truncated MSP file, expected %d bytes on row %s", (rowlen, x) raise OSError(msg)
)
idx = 0 idx = 0
while idx < rowlen: while idx < rowlen:
runtype = row[idx] runtype = row[idx]
@ -144,7 +146,8 @@ class MspDecoder(ImageFile.PyDecoder):
idx += runcount idx += runcount
except struct.error as e: except struct.error as e:
raise OSError(f"Corrupted MSP file in row {x}") from e msg = f"Corrupted MSP file in row {x}"
raise OSError(msg) from e
self.set_as_raw(img.getvalue(), ("1", 0, 1)) self.set_as_raw(img.getvalue(), ("1", 0, 1))
@ -161,7 +164,8 @@ Image.register_decoder("MSP", MspDecoder)
def _save(im, fp, filename): def _save(im, fp, filename):
if im.mode != "1": if im.mode != "1":
raise OSError(f"cannot write mode {im.mode} as MSP") msg = f"cannot write mode {im.mode} as MSP"
raise OSError(msg)
# create MSP header # create MSP header
header = [0] * 16 header = [0] * 16

View File

@ -34,7 +34,8 @@ class PaletteFile:
if s[:1] == b"#": if s[:1] == b"#":
continue continue
if len(s) > 100: if len(s) > 100:
raise SyntaxError("bad palette file") msg = "bad palette file"
raise SyntaxError(msg)
v = [int(x) for x in s.split()] v = [int(x) for x in s.split()]
try: try:

View File

@ -138,7 +138,8 @@ def _save(im, fp, filename):
bpp = im.info["bpp"] bpp = im.info["bpp"]
im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval)) im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval))
else: else:
raise OSError(f"cannot write mode {im.mode} as Palm") msg = f"cannot write mode {im.mode} as Palm"
raise OSError(msg)
# we ignore the palette here # we ignore the palette here
im.mode = "P" im.mode = "P"
@ -154,7 +155,8 @@ def _save(im, fp, filename):
else: else:
raise OSError(f"cannot write mode {im.mode} as Palm") msg = f"cannot write mode {im.mode} as Palm"
raise OSError(msg)
# #
# make sure image data is available # make sure image data is available

View File

@ -35,7 +35,8 @@ class PcdImageFile(ImageFile.ImageFile):
s = self.fp.read(2048) s = self.fp.read(2048)
if s[:4] != b"PCD_": if s[:4] != b"PCD_":
raise SyntaxError("not a PCD file") msg = "not a PCD file"
raise SyntaxError(msg)
orientation = s[1538] & 3 orientation = s[1538] & 3
self.tile_post_rotate = None self.tile_post_rotate = None

View File

@ -63,7 +63,8 @@ class PcfFontFile(FontFile.FontFile):
magic = l32(fp.read(4)) magic = l32(fp.read(4))
if magic != PCF_MAGIC: if magic != PCF_MAGIC:
raise SyntaxError("not a PCF file") msg = "not a PCF file"
raise SyntaxError(msg)
super().__init__() super().__init__()
@ -186,7 +187,8 @@ class PcfFontFile(FontFile.FontFile):
nbitmaps = i32(fp.read(4)) nbitmaps = i32(fp.read(4))
if nbitmaps != len(metrics): if nbitmaps != len(metrics):
raise OSError("Wrong number of bitmaps") msg = "Wrong number of bitmaps"
raise OSError(msg)
offsets = [] offsets = []
for i in range(nbitmaps): for i in range(nbitmaps):

View File

@ -54,12 +54,14 @@ class PcxImageFile(ImageFile.ImageFile):
# header # header
s = self.fp.read(128) s = self.fp.read(128)
if not _accept(s): if not _accept(s):
raise SyntaxError("not a PCX file") msg = "not a PCX file"
raise SyntaxError(msg)
# image # image
bbox = i16(s, 4), i16(s, 6), i16(s, 8) + 1, i16(s, 10) + 1 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]: if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
raise SyntaxError("bad PCX image size") msg = "bad PCX image size"
raise SyntaxError(msg)
logger.debug("BBox: %s %s %s %s", *bbox) logger.debug("BBox: %s %s %s %s", *bbox)
# format # format
@ -105,7 +107,8 @@ class PcxImageFile(ImageFile.ImageFile):
rawmode = "RGB;L" rawmode = "RGB;L"
else: else:
raise OSError("unknown PCX mode") msg = "unknown PCX mode"
raise OSError(msg)
self.mode = mode self.mode = mode
self._size = bbox[2] - bbox[0], bbox[3] - bbox[1] self._size = bbox[2] - bbox[0], bbox[3] - bbox[1]
@ -144,7 +147,8 @@ def _save(im, fp, filename):
try: try:
version, bits, planes, rawmode = SAVE[im.mode] version, bits, planes, rawmode = SAVE[im.mode]
except KeyError as e: except KeyError as e:
raise ValueError(f"Cannot save {im.mode} images as PCX") from e msg = f"Cannot save {im.mode} images as PCX"
raise ValueError(msg) from e
# bytes per plane # bytes per plane
stride = (im.size[0] * bits + 7) // 8 stride = (im.size[0] * bits + 7) // 8

View File

@ -174,7 +174,8 @@ def _save(im, fp, filename, save_all=False):
procset = "ImageC" # color images procset = "ImageC" # color images
decode = [1, 0, 1, 0, 1, 0, 1, 0] decode = [1, 0, 1, 0, 1, 0, 1, 0]
else: else:
raise ValueError(f"cannot save mode {im.mode}") msg = f"cannot save mode {im.mode}"
raise ValueError(msg)
# #
# image # image
@ -198,7 +199,8 @@ def _save(im, fp, filename, save_all=False):
elif filter == "RunLengthDecode": elif filter == "RunLengthDecode":
ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)]) ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)])
else: else:
raise ValueError(f"unsupported PDF filter ({filter})") msg = f"unsupported PDF filter ({filter})"
raise ValueError(msg)
stream = op.getvalue() stream = op.getvalue()
if filter == "CCITTFaxDecode": if filter == "CCITTFaxDecode":

View File

@ -138,9 +138,10 @@ class XrefTable:
elif key in self.deleted_entries: elif key in self.deleted_entries:
generation = self.deleted_entries[key] generation = self.deleted_entries[key]
else: else:
raise IndexError( msg = (
"object ID " + str(key) + " cannot be deleted because it doesn't exist" "object ID " + str(key) + " cannot be deleted because it doesn't exist"
) )
raise IndexError(msg)
def __contains__(self, key): def __contains__(self, key):
return key in self.existing_entries or key in self.new_entries return key in self.existing_entries or key in self.new_entries
@ -314,9 +315,8 @@ class PdfStream:
expected_length = self.dictionary.Length expected_length = self.dictionary.Length
return zlib.decompress(self.buf, bufsize=int(expected_length)) return zlib.decompress(self.buf, bufsize=int(expected_length))
else: else:
raise NotImplementedError( msg = f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported"
f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported" raise NotImplementedError(msg)
)
def pdf_repr(x): def pdf_repr(x):
@ -358,7 +358,8 @@ class PdfParser:
def __init__(self, filename=None, f=None, buf=None, start_offset=0, mode="rb"): def __init__(self, filename=None, f=None, buf=None, start_offset=0, mode="rb"):
if buf and f: if buf and f:
raise RuntimeError("specify buf or f or filename, but not both buf and f") msg = "specify buf or f or filename, but not both buf and f"
raise RuntimeError(msg)
self.filename = filename self.filename = filename
self.buf = buf self.buf = buf
self.f = f self.f = f
@ -920,7 +921,8 @@ class PdfParser:
result.extend(b")") result.extend(b")")
nesting_depth -= 1 nesting_depth -= 1
offset = m.end() offset = m.end()
raise PdfFormatError("unfinished literal string") msg = "unfinished literal string"
raise PdfFormatError(msg)
re_xref_section_start = re.compile(whitespace_optional + rb"xref" + newline) re_xref_section_start = re.compile(whitespace_optional + rb"xref" + newline)
re_xref_subsection_start = re.compile( re_xref_subsection_start = re.compile(

View File

@ -44,7 +44,8 @@ class PixarImageFile(ImageFile.ImageFile):
# assuming a 4-byte magic label # assuming a 4-byte magic label
s = self.fp.read(4) s = self.fp.read(4)
if not _accept(s): if not _accept(s):
raise SyntaxError("not a PIXAR file") msg = "not a PIXAR file"
raise SyntaxError(msg)
# read rest of header # read rest of header
s = s + self.fp.read(508) s = s + self.fp.read(508)

View File

@ -138,14 +138,16 @@ def __getattr__(name):
if name in enum.__members__: if name in enum.__members__:
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
return enum[name] return enum[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'") msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)
def _safe_zlib_decompress(s): def _safe_zlib_decompress(s):
dobj = zlib.decompressobj() dobj = zlib.decompressobj()
plaintext = dobj.decompress(s, MAX_TEXT_CHUNK) plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
if dobj.unconsumed_tail: if dobj.unconsumed_tail:
raise ValueError("Decompressed Data Too Large") msg = "Decompressed Data Too Large"
raise ValueError(msg)
return plaintext return plaintext
@ -178,7 +180,8 @@ class ChunkStream:
if not is_cid(cid): if not is_cid(cid):
if not ImageFile.LOAD_TRUNCATED_IMAGES: if not ImageFile.LOAD_TRUNCATED_IMAGES:
raise SyntaxError(f"broken PNG file (chunk {repr(cid)})") msg = f"broken PNG file (chunk {repr(cid)})"
raise SyntaxError(msg)
return cid, pos, length return cid, pos, length
@ -215,13 +218,11 @@ class ChunkStream:
crc1 = _crc32(data, _crc32(cid)) crc1 = _crc32(data, _crc32(cid))
crc2 = i32(self.fp.read(4)) crc2 = i32(self.fp.read(4))
if crc1 != crc2: if crc1 != crc2:
raise SyntaxError( msg = f"broken PNG file (bad header checksum in {repr(cid)})"
f"broken PNG file (bad header checksum in {repr(cid)})" raise SyntaxError(msg)
)
except struct.error as e: except struct.error as e:
raise SyntaxError( msg = f"broken PNG file (incomplete checksum in {repr(cid)})"
f"broken PNG file (incomplete checksum in {repr(cid)})" raise SyntaxError(msg) from e
) from e
def crc_skip(self, cid, data): def crc_skip(self, cid, data):
"""Read checksum""" """Read checksum"""
@ -239,7 +240,8 @@ class ChunkStream:
try: try:
cid, pos, length = self.read() cid, pos, length = self.read()
except struct.error as e: except struct.error as e:
raise OSError("truncated PNG file") from e msg = "truncated PNG file"
raise OSError(msg) from e
if cid == endchunk: if cid == endchunk:
break break
@ -376,10 +378,11 @@ class PngStream(ChunkStream):
def check_text_memory(self, chunklen): def check_text_memory(self, chunklen):
self.text_memory += chunklen self.text_memory += chunklen
if self.text_memory > MAX_TEXT_MEMORY: if self.text_memory > MAX_TEXT_MEMORY:
raise ValueError( msg = (
"Too much memory used in text chunks: " "Too much memory used in text chunks: "
f"{self.text_memory}>MAX_TEXT_MEMORY" f"{self.text_memory}>MAX_TEXT_MEMORY"
) )
raise ValueError(msg)
def save_rewind(self): def save_rewind(self):
self.rewind_state = { self.rewind_state = {
@ -407,7 +410,8 @@ class PngStream(ChunkStream):
logger.debug("Compression method %s", s[i]) logger.debug("Compression method %s", s[i])
comp_method = s[i] comp_method = s[i]
if comp_method != 0: if comp_method != 0:
raise SyntaxError(f"Unknown compression method {comp_method} in iCCP chunk") msg = f"Unknown compression method {comp_method} in iCCP chunk"
raise SyntaxError(msg)
try: try:
icc_profile = _safe_zlib_decompress(s[i + 2 :]) icc_profile = _safe_zlib_decompress(s[i + 2 :])
except ValueError: except ValueError:
@ -427,7 +431,8 @@ class PngStream(ChunkStream):
if length < 13: if length < 13:
if ImageFile.LOAD_TRUNCATED_IMAGES: if ImageFile.LOAD_TRUNCATED_IMAGES:
return s return s
raise ValueError("Truncated IHDR chunk") msg = "Truncated IHDR chunk"
raise ValueError(msg)
self.im_size = i32(s, 0), i32(s, 4) self.im_size = i32(s, 0), i32(s, 4)
try: try:
self.im_mode, self.im_rawmode = _MODES[(s[8], s[9])] self.im_mode, self.im_rawmode = _MODES[(s[8], s[9])]
@ -436,7 +441,8 @@ class PngStream(ChunkStream):
if s[12]: if s[12]:
self.im_info["interlace"] = 1 self.im_info["interlace"] = 1
if s[11]: if s[11]:
raise SyntaxError("unknown filter category") msg = "unknown filter category"
raise SyntaxError(msg)
return s return s
def chunk_IDAT(self, pos, length): def chunk_IDAT(self, pos, length):
@ -512,7 +518,8 @@ class PngStream(ChunkStream):
if length < 1: if length < 1:
if ImageFile.LOAD_TRUNCATED_IMAGES: if ImageFile.LOAD_TRUNCATED_IMAGES:
return s return s
raise ValueError("Truncated sRGB chunk") msg = "Truncated sRGB chunk"
raise ValueError(msg)
self.im_info["srgb"] = s[0] self.im_info["srgb"] = s[0]
return s return s
@ -523,7 +530,8 @@ class PngStream(ChunkStream):
if length < 9: if length < 9:
if ImageFile.LOAD_TRUNCATED_IMAGES: if ImageFile.LOAD_TRUNCATED_IMAGES:
return s return s
raise ValueError("Truncated pHYs chunk") msg = "Truncated pHYs chunk"
raise ValueError(msg)
px, py = i32(s, 0), i32(s, 4) px, py = i32(s, 0), i32(s, 4)
unit = s[8] unit = s[8]
if unit == 1: # meter if unit == 1: # meter
@ -567,7 +575,8 @@ class PngStream(ChunkStream):
else: else:
comp_method = 0 comp_method = 0
if comp_method != 0: if comp_method != 0:
raise SyntaxError(f"Unknown compression method {comp_method} in zTXt chunk") msg = f"Unknown compression method {comp_method} in zTXt chunk"
raise SyntaxError(msg)
try: try:
v = _safe_zlib_decompress(v[1:]) v = _safe_zlib_decompress(v[1:])
except ValueError: except ValueError:
@ -639,7 +648,8 @@ class PngStream(ChunkStream):
if length < 8: if length < 8:
if ImageFile.LOAD_TRUNCATED_IMAGES: if ImageFile.LOAD_TRUNCATED_IMAGES:
return s return s
raise ValueError("APNG contains truncated acTL chunk") msg = "APNG contains truncated acTL chunk"
raise ValueError(msg)
if self.im_n_frames is not None: if self.im_n_frames is not None:
self.im_n_frames = None self.im_n_frames = None
warnings.warn("Invalid APNG, will use default PNG image if possible") warnings.warn("Invalid APNG, will use default PNG image if possible")
@ -658,18 +668,21 @@ class PngStream(ChunkStream):
if length < 26: if length < 26:
if ImageFile.LOAD_TRUNCATED_IMAGES: if ImageFile.LOAD_TRUNCATED_IMAGES:
return s return s
raise ValueError("APNG contains truncated fcTL chunk") msg = "APNG contains truncated fcTL chunk"
raise ValueError(msg)
seq = i32(s) seq = i32(s)
if (self._seq_num is None and seq != 0) or ( if (self._seq_num is None and seq != 0) or (
self._seq_num is not None and self._seq_num != seq - 1 self._seq_num is not None and self._seq_num != seq - 1
): ):
raise SyntaxError("APNG contains frame sequence errors") msg = "APNG contains frame sequence errors"
raise SyntaxError(msg)
self._seq_num = seq self._seq_num = seq
width, height = i32(s, 4), i32(s, 8) width, height = i32(s, 4), i32(s, 8)
px, py = i32(s, 12), i32(s, 16) px, py = i32(s, 12), i32(s, 16)
im_w, im_h = self.im_size im_w, im_h = self.im_size
if px + width > im_w or py + height > im_h: if px + width > im_w or py + height > im_h:
raise SyntaxError("APNG contains invalid frames") msg = "APNG contains invalid frames"
raise SyntaxError(msg)
self.im_info["bbox"] = (px, py, px + width, py + height) self.im_info["bbox"] = (px, py, px + width, py + height)
delay_num, delay_den = i16(s, 20), i16(s, 22) delay_num, delay_den = i16(s, 20), i16(s, 22)
if delay_den == 0: if delay_den == 0:
@ -684,11 +697,13 @@ class PngStream(ChunkStream):
if ImageFile.LOAD_TRUNCATED_IMAGES: if ImageFile.LOAD_TRUNCATED_IMAGES:
s = ImageFile._safe_read(self.fp, length) s = ImageFile._safe_read(self.fp, length)
return s return s
raise ValueError("APNG contains truncated fDAT chunk") msg = "APNG contains truncated fDAT chunk"
raise ValueError(msg)
s = ImageFile._safe_read(self.fp, 4) s = ImageFile._safe_read(self.fp, 4)
seq = i32(s) seq = i32(s)
if self._seq_num != seq - 1: if self._seq_num != seq - 1:
raise SyntaxError("APNG contains frame sequence errors") msg = "APNG contains frame sequence errors"
raise SyntaxError(msg)
self._seq_num = seq self._seq_num = seq
return self.chunk_IDAT(pos + 4, length - 4) return self.chunk_IDAT(pos + 4, length - 4)
@ -713,7 +728,8 @@ class PngImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
if not _accept(self.fp.read(8)): if not _accept(self.fp.read(8)):
raise SyntaxError("not a PNG file") msg = "not a PNG file"
raise SyntaxError(msg)
self._fp = self.fp self._fp = self.fp
self.__frame = 0 self.__frame = 0
@ -797,7 +813,8 @@ class PngImageFile(ImageFile.ImageFile):
"""Verify PNG file""" """Verify PNG file"""
if self.fp is None: if self.fp is None:
raise RuntimeError("verify must be called directly after open") msg = "verify must be called directly after open"
raise RuntimeError(msg)
# back up to beginning of IDAT block # back up to beginning of IDAT block
self.fp.seek(self.tile[0][2] - 8) self.fp.seek(self.tile[0][2] - 8)
@ -821,7 +838,8 @@ class PngImageFile(ImageFile.ImageFile):
self._seek(f) self._seek(f)
except EOFError as e: except EOFError as e:
self.seek(last_frame) self.seek(last_frame)
raise EOFError("no more images in APNG file") from e msg = "no more images in APNG file"
raise EOFError(msg) from e
def _seek(self, frame, rewind=False): def _seek(self, frame, rewind=False):
if frame == 0: if frame == 0:
@ -844,7 +862,8 @@ class PngImageFile(ImageFile.ImageFile):
self.__frame = 0 self.__frame = 0
else: else:
if frame != self.__frame + 1: if frame != self.__frame + 1:
raise ValueError(f"cannot seek to frame {frame}") msg = f"cannot seek to frame {frame}"
raise ValueError(msg)
# ensure previous frame was loaded # ensure previous frame was loaded
self.load() self.load()
@ -869,11 +888,13 @@ class PngImageFile(ImageFile.ImageFile):
break break
if cid == b"IEND": if cid == b"IEND":
raise EOFError("No more images in APNG file") msg = "No more images in APNG file"
raise EOFError(msg)
if cid == b"fcTL": if cid == b"fcTL":
if frame_start: if frame_start:
# there must be at least one fdAT chunk between fcTL chunks # there must be at least one fdAT chunk between fcTL chunks
raise SyntaxError("APNG missing frame data") msg = "APNG missing frame data"
raise SyntaxError(msg)
frame_start = True frame_start = True
try: try:
@ -1277,7 +1298,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
try: try:
rawmode, mode = _OUTMODES[mode] rawmode, mode = _OUTMODES[mode]
except KeyError as e: except KeyError as e:
raise OSError(f"cannot write mode {mode} as PNG") from e msg = f"cannot write mode {mode} as PNG"
raise OSError(msg) from e
# #
# write minimal PNG file # write minimal PNG file
@ -1358,7 +1380,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
if "transparency" in im.encoderinfo: if "transparency" in im.encoderinfo:
# don't bother with transparency if it's an RGBA # don't bother with transparency if it's an RGBA
# and it's in the info dict. It's probably just stale. # and it's in the info dict. It's probably just stale.
raise OSError("cannot use transparency for this mode") msg = "cannot use transparency for this mode"
raise OSError(msg)
else: else:
if im.mode == "P" and im.im.getpalettemode() == "RGBA": if im.mode == "P" and im.im.getpalettemode() == "RGBA":
alpha = im.im.getpalette("RGBA", "A") alpha = im.im.getpalette("RGBA", "A")

View File

@ -84,9 +84,11 @@ class PpmImageFile(ImageFile.ImageFile):
token += c token += c
if not token: if not token:
# Token was not even 1 byte # Token was not even 1 byte
raise ValueError("Reached EOF while reading header") msg = "Reached EOF while reading header"
raise ValueError(msg)
elif len(token) > 10: elif len(token) > 10:
raise ValueError(f"Token too long in file header: {token.decode()}") msg = f"Token too long in file header: {token.decode()}"
raise ValueError(msg)
return token return token
def _open(self): def _open(self):
@ -94,7 +96,8 @@ class PpmImageFile(ImageFile.ImageFile):
try: try:
mode = MODES[magic_number] mode = MODES[magic_number]
except KeyError: except KeyError:
raise SyntaxError("not a PPM file") msg = "not a PPM file"
raise SyntaxError(msg)
if magic_number in (b"P1", b"P4"): if magic_number in (b"P1", b"P4"):
self.custom_mimetype = "image/x-portable-bitmap" self.custom_mimetype = "image/x-portable-bitmap"
@ -122,9 +125,8 @@ class PpmImageFile(ImageFile.ImageFile):
elif ix == 2: # token is maxval elif ix == 2: # token is maxval
maxval = token maxval = token
if not 0 < maxval < 65536: if not 0 < maxval < 65536:
raise ValueError( msg = "maxval must be greater than 0 and less than 65536"
"maxval must be greater than 0 and less than 65536" raise ValueError(msg)
)
if maxval > 255 and mode == "L": if maxval > 255 and mode == "L":
self.mode = "I" self.mode = "I"
@ -208,9 +210,8 @@ class PpmPlainDecoder(ImageFile.PyDecoder):
tokens = b"".join(block.split()) tokens = b"".join(block.split())
for token in tokens: for token in tokens:
if token not in (48, 49): if token not in (48, 49):
raise ValueError( msg = b"Invalid token for this mode: %s" % bytes([token])
b"Invalid token for this mode: %s" % bytes([token]) raise ValueError(msg)
)
data = (data + tokens)[:total_bytes] data = (data + tokens)[:total_bytes]
invert = bytes.maketrans(b"01", b"\xFF\x00") invert = bytes.maketrans(b"01", b"\xFF\x00")
return data.translate(invert) return data.translate(invert)
@ -243,18 +244,19 @@ class PpmPlainDecoder(ImageFile.PyDecoder):
if block and not block[-1:].isspace(): # block might split token if block and not block[-1:].isspace(): # block might split token
half_token = tokens.pop() # save half token for later half_token = tokens.pop() # save half token for later
if len(half_token) > max_len: # prevent buildup of half_token if len(half_token) > max_len: # prevent buildup of half_token
raise ValueError( msg = (
b"Token too long found in data: %s" % half_token[: max_len + 1] b"Token too long found in data: %s" % half_token[: max_len + 1]
) )
raise ValueError(msg)
for token in tokens: for token in tokens:
if len(token) > max_len: if len(token) > max_len:
raise ValueError( msg = b"Token too long found in data: %s" % token[: max_len + 1]
b"Token too long found in data: %s" % token[: max_len + 1] raise ValueError(msg)
)
value = int(token) value = int(token)
if value > maxval: if value > maxval:
raise ValueError(f"Channel value too large for this mode: {value}") msg = f"Channel value too large for this mode: {value}"
raise ValueError(msg)
value = round(value / maxval * out_max) value = round(value / maxval * out_max)
data += o32(value) if self.mode == "I" else o8(value) data += o32(value) if self.mode == "I" else o8(value)
if len(data) == total_bytes: # finished! if len(data) == total_bytes: # finished!
@ -314,7 +316,8 @@ def _save(im, fp, filename):
elif im.mode in ("RGB", "RGBA"): elif im.mode in ("RGB", "RGBA"):
rawmode, head = "RGB", b"P6" rawmode, head = "RGB", b"P6"
else: else:
raise OSError(f"cannot write mode {im.mode} as PPM") msg = f"cannot write mode {im.mode} as PPM"
raise OSError(msg)
fp.write(head + b"\n%d %d\n" % im.size) fp.write(head + b"\n%d %d\n" % im.size)
if head == b"P6": if head == b"P6":
fp.write(b"255\n") fp.write(b"255\n")

View File

@ -65,7 +65,8 @@ class PsdImageFile(ImageFile.ImageFile):
s = read(26) s = read(26)
if not _accept(s) or i16(s, 4) != 1: if not _accept(s) or i16(s, 4) != 1:
raise SyntaxError("not a PSD file") msg = "not a PSD file"
raise SyntaxError(msg)
psd_bits = i16(s, 22) psd_bits = i16(s, 22)
psd_channels = i16(s, 12) psd_channels = i16(s, 12)
@ -74,7 +75,8 @@ class PsdImageFile(ImageFile.ImageFile):
mode, channels = MODES[(psd_mode, psd_bits)] mode, channels = MODES[(psd_mode, psd_bits)]
if channels > psd_channels: if channels > psd_channels:
raise OSError("not enough channels") msg = "not enough channels"
raise OSError(msg)
if mode == "RGB" and psd_channels == 4: if mode == "RGB" and psd_channels == 4:
mode = "RGBA" mode = "RGBA"
channels = 4 channels = 4
@ -152,7 +154,8 @@ class PsdImageFile(ImageFile.ImageFile):
self.fp = self._fp self.fp = self._fp
return name, bbox return name, bbox
except IndexError as e: except IndexError as e:
raise EOFError("no such layer") from e msg = "no such layer"
raise EOFError(msg) from e
def tell(self): def tell(self):
# return layer number (0=image, 1..max=layers) # return layer number (0=image, 1..max=layers)
@ -170,7 +173,8 @@ def _layerinfo(fp, ct_bytes):
# sanity check # sanity check
if ct_bytes < (abs(ct) * 20): if ct_bytes < (abs(ct) * 20):
raise SyntaxError("Layer block too short for number of layers requested") msg = "Layer block too short for number of layers requested"
raise SyntaxError(msg)
for _ in range(abs(ct)): for _ in range(abs(ct)):

View File

@ -79,7 +79,8 @@ class PyAccess:
:param color: The pixel value. :param color: The pixel value.
""" """
if self.readonly: if self.readonly:
raise ValueError("Attempt to putpixel a read only image") msg = "Attempt to putpixel a read only image"
raise ValueError(msg)
(x, y) = xy (x, y) = xy
if x < 0: if x < 0:
x = self.xsize + x x = self.xsize + x
@ -127,7 +128,8 @@ class PyAccess:
def check_xy(self, xy): def check_xy(self, xy):
(x, y) = xy (x, y) = xy
if not (0 <= x < self.xsize and 0 <= y < self.ysize): if not (0 <= x < self.xsize and 0 <= y < self.ysize):
raise ValueError("pixel location out of range") msg = "pixel location out of range"
raise ValueError(msg)
return xy return xy

View File

@ -60,7 +60,8 @@ class SgiImageFile(ImageFile.ImageFile):
s = self.fp.read(headlen) s = self.fp.read(headlen)
if not _accept(s): if not _accept(s):
raise ValueError("Not an SGI image file") msg = "Not an SGI image file"
raise ValueError(msg)
# compression : verbatim or RLE # compression : verbatim or RLE
compression = s[2] compression = s[2]
@ -91,7 +92,8 @@ class SgiImageFile(ImageFile.ImageFile):
pass pass
if rawmode == "": if rawmode == "":
raise ValueError("Unsupported SGI image mode") msg = "Unsupported SGI image mode"
raise ValueError(msg)
self._size = xsize, ysize self._size = xsize, ysize
self.mode = rawmode.split(";")[0] self.mode = rawmode.split(";")[0]
@ -124,7 +126,8 @@ class SgiImageFile(ImageFile.ImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if im.mode != "RGB" and im.mode != "RGBA" and im.mode != "L": if im.mode != "RGB" and im.mode != "RGBA" and im.mode != "L":
raise ValueError("Unsupported SGI image mode") msg = "Unsupported SGI image mode"
raise ValueError(msg)
# Get the keyword arguments # Get the keyword arguments
info = im.encoderinfo info = im.encoderinfo
@ -133,7 +136,8 @@ def _save(im, fp, filename):
bpc = info.get("bpc", 1) bpc = info.get("bpc", 1)
if bpc not in (1, 2): if bpc not in (1, 2):
raise ValueError("Unsupported number of bytes per pixel") msg = "Unsupported number of bytes per pixel"
raise ValueError(msg)
# Flip the image, since the origin of SGI file is the bottom-left corner # Flip the image, since the origin of SGI file is the bottom-left corner
orientation = -1 orientation = -1
@ -158,9 +162,8 @@ def _save(im, fp, filename):
# assert we've got the right number of bands. # assert we've got the right number of bands.
if len(im.getbands()) != z: if len(im.getbands()) != z:
raise ValueError( msg = f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}"
f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}" raise ValueError(msg)
)
# Minimum Byte value # Minimum Byte value
pinmin = 0 pinmin = 0

View File

@ -110,14 +110,17 @@ class SpiderImageFile(ImageFile.ImageFile):
t = struct.unpack("<27f", f) # little-endian t = struct.unpack("<27f", f) # little-endian
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
if hdrlen == 0: if hdrlen == 0:
raise SyntaxError("not a valid Spider file") msg = "not a valid Spider file"
raise SyntaxError(msg)
except struct.error as e: except struct.error as e:
raise SyntaxError("not a valid Spider file") from e msg = "not a valid Spider file"
raise SyntaxError(msg) from e
h = (99,) + t # add 1 value : spider header index starts at 1 h = (99,) + t # add 1 value : spider header index starts at 1
iform = int(h[5]) iform = int(h[5])
if iform != 1: if iform != 1:
raise SyntaxError("not a Spider 2D image") msg = "not a Spider 2D image"
raise SyntaxError(msg)
self._size = int(h[12]), int(h[2]) # size in pixels (width, height) self._size = int(h[12]), int(h[2]) # size in pixels (width, height)
self.istack = int(h[24]) self.istack = int(h[24])
@ -140,7 +143,8 @@ class SpiderImageFile(ImageFile.ImageFile):
offset = hdrlen + self.stkoffset offset = hdrlen + self.stkoffset
self.istack = 2 # So Image knows it's still a stack self.istack = 2 # So Image knows it's still a stack
else: else:
raise SyntaxError("inconsistent stack header values") msg = "inconsistent stack header values"
raise SyntaxError(msg)
if self.bigendian: if self.bigendian:
self.rawmode = "F;32BF" self.rawmode = "F;32BF"
@ -168,7 +172,8 @@ class SpiderImageFile(ImageFile.ImageFile):
def seek(self, frame): def seek(self, frame):
if self.istack == 0: if self.istack == 0:
raise EOFError("attempt to seek in a non-stack file") msg = "attempt to seek in a non-stack file"
raise EOFError(msg)
if not self._seek_check(frame): if not self._seek_check(frame):
return return
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes) self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
@ -260,7 +265,8 @@ def _save(im, fp, filename):
hdr = makeSpiderHeader(im) hdr = makeSpiderHeader(im)
if len(hdr) < 256: if len(hdr) < 256:
raise OSError("Error creating Spider header") msg = "Error creating Spider header"
raise OSError(msg)
# write the SPIDER header # write the SPIDER header
fp.writelines(hdr) fp.writelines(hdr)

View File

@ -54,7 +54,8 @@ class SunImageFile(ImageFile.ImageFile):
# HEAD # HEAD
s = self.fp.read(32) s = self.fp.read(32)
if not _accept(s): if not _accept(s):
raise SyntaxError("not an SUN raster file") msg = "not an SUN raster file"
raise SyntaxError(msg)
offset = 32 offset = 32
@ -83,14 +84,17 @@ class SunImageFile(ImageFile.ImageFile):
else: else:
self.mode, rawmode = "RGB", "BGRX" self.mode, rawmode = "RGB", "BGRX"
else: else:
raise SyntaxError("Unsupported Mode/Bit Depth") msg = "Unsupported Mode/Bit Depth"
raise SyntaxError(msg)
if palette_length: if palette_length:
if palette_length > 1024: if palette_length > 1024:
raise SyntaxError("Unsupported Color Palette Length") msg = "Unsupported Color Palette Length"
raise SyntaxError(msg)
if palette_type != 1: if palette_type != 1:
raise SyntaxError("Unsupported Palette Type") msg = "Unsupported Palette Type"
raise SyntaxError(msg)
offset = offset + palette_length offset = offset + palette_length
self.palette = ImagePalette.raw("RGB;L", self.fp.read(palette_length)) self.palette = ImagePalette.raw("RGB;L", self.fp.read(palette_length))
@ -124,7 +128,8 @@ class SunImageFile(ImageFile.ImageFile):
elif file_type == 2: elif file_type == 2:
self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)] self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)]
else: else:
raise SyntaxError("Unsupported Sun Raster file type") msg = "Unsupported Sun Raster file type"
raise SyntaxError(msg)
# #

View File

@ -35,12 +35,14 @@ class TarIO(ContainerIO.ContainerIO):
s = self.fh.read(512) s = self.fh.read(512)
if len(s) != 512: if len(s) != 512:
raise OSError("unexpected end of tar file") msg = "unexpected end of tar file"
raise OSError(msg)
name = s[:100].decode("utf-8") name = s[:100].decode("utf-8")
i = name.find("\0") i = name.find("\0")
if i == 0: if i == 0:
raise OSError("cannot find subfile") msg = "cannot find subfile"
raise OSError(msg)
if i > 0: if i > 0:
name = name[:i] name = name[:i]

View File

@ -73,7 +73,8 @@ class TgaImageFile(ImageFile.ImageFile):
or self.size[1] <= 0 or self.size[1] <= 0
or depth not in (1, 8, 16, 24, 32) or depth not in (1, 8, 16, 24, 32)
): ):
raise SyntaxError("not a TGA file") msg = "not a TGA file"
raise SyntaxError(msg)
# image mode # image mode
if imagetype in (3, 11): if imagetype in (3, 11):
@ -89,7 +90,8 @@ class TgaImageFile(ImageFile.ImageFile):
if depth == 32: if depth == 32:
self.mode = "RGBA" self.mode = "RGBA"
else: else:
raise SyntaxError("unknown TGA mode") msg = "unknown TGA mode"
raise SyntaxError(msg)
# orientation # orientation
orientation = flags & 0x30 orientation = flags & 0x30
@ -99,7 +101,8 @@ class TgaImageFile(ImageFile.ImageFile):
elif orientation in [0, 0x10]: elif orientation in [0, 0x10]:
orientation = -1 orientation = -1
else: else:
raise SyntaxError("unknown TGA orientation") msg = "unknown TGA orientation"
raise SyntaxError(msg)
self.info["orientation"] = orientation self.info["orientation"] = orientation
@ -175,7 +178,8 @@ def _save(im, fp, filename):
try: try:
rawmode, bits, colormaptype, imagetype = SAVE[im.mode] rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
except KeyError as e: except KeyError as e:
raise OSError(f"cannot write mode {im.mode} as TGA") from e msg = f"cannot write mode {im.mode} as TGA"
raise OSError(msg) from e
if "rle" in im.encoderinfo: if "rle" in im.encoderinfo:
rle = im.encoderinfo["rle"] rle = im.encoderinfo["rle"]

View File

@ -500,14 +500,16 @@ class ImageFileDirectory_v2(MutableMapping):
:param prefix: Override the endianness of the file. :param prefix: Override the endianness of the file.
""" """
if not _accept(ifh): if not _accept(ifh):
raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)") msg = f"not a TIFF file (header {repr(ifh)} not valid)"
raise SyntaxError(msg)
self._prefix = prefix if prefix is not None else ifh[:2] self._prefix = prefix if prefix is not None else ifh[:2]
if self._prefix == MM: if self._prefix == MM:
self._endian = ">" self._endian = ">"
elif self._prefix == II: elif self._prefix == II:
self._endian = "<" self._endian = "<"
else: else:
raise SyntaxError("not a TIFF IFD") msg = "not a TIFF IFD"
raise SyntaxError(msg)
self._bigtiff = ifh[2] == 43 self._bigtiff = ifh[2] == 43
self.group = group self.group = group
self.tagtype = {} self.tagtype = {}
@ -524,7 +526,8 @@ class ImageFileDirectory_v2(MutableMapping):
@legacy_api.setter @legacy_api.setter
def legacy_api(self, value): def legacy_api(self, value):
raise Exception("Not allowing setting of legacy api") msg = "Not allowing setting of legacy api"
raise Exception(msg)
def reset(self): def reset(self):
self._tags_v1 = {} # will remain empty if legacy_api is false self._tags_v1 = {} # will remain empty if legacy_api is false
@ -780,10 +783,11 @@ class ImageFileDirectory_v2(MutableMapping):
def _ensure_read(self, fp, size): def _ensure_read(self, fp, size):
ret = fp.read(size) ret = fp.read(size)
if len(ret) != size: if len(ret) != size:
raise OSError( msg = (
"Corrupt EXIF data. " "Corrupt EXIF data. "
f"Expecting to read {size} bytes but only got {len(ret)}. " f"Expecting to read {size} bytes but only got {len(ret)}. "
) )
raise OSError(msg)
return ret return ret
def load(self, fp): def load(self, fp):
@ -910,7 +914,8 @@ class ImageFileDirectory_v2(MutableMapping):
if stripoffsets is not None: if stripoffsets is not None:
tag, typ, count, value, data = entries[stripoffsets] tag, typ, count, value, data = entries[stripoffsets]
if data: if data:
raise NotImplementedError("multistrip support not yet implemented") msg = "multistrip support not yet implemented"
raise NotImplementedError(msg)
value = self._pack("L", self._unpack("L", value)[0] + offset) value = self._pack("L", self._unpack("L", value)[0] + offset)
entries[stripoffsets] = tag, typ, count, value, data entries[stripoffsets] = tag, typ, count, value, data
@ -1123,7 +1128,8 @@ class TiffImageFile(ImageFile.ImageFile):
while len(self._frame_pos) <= frame: while len(self._frame_pos) <= frame:
if not self.__next: if not self.__next:
raise EOFError("no more images in TIFF file") msg = "no more images in TIFF file"
raise EOFError(msg)
logger.debug( logger.debug(
f"Seeking to frame {frame}, on frame {self.__frame}, " f"Seeking to frame {frame}, on frame {self.__frame}, "
f"__next {self.__next}, location: {self.fp.tell()}" f"__next {self.__next}, location: {self.fp.tell()}"
@ -1230,7 +1236,8 @@ class TiffImageFile(ImageFile.ImageFile):
self.load_prepare() self.load_prepare()
if not len(self.tile) == 1: if not len(self.tile) == 1:
raise OSError("Not exactly one tile") msg = "Not exactly one tile"
raise OSError(msg)
# (self._compression, (extents tuple), # (self._compression, (extents tuple),
# 0, (rawmode, self._compression, fp)) # 0, (rawmode, self._compression, fp))
@ -1262,7 +1269,8 @@ class TiffImageFile(ImageFile.ImageFile):
try: try:
decoder.setimage(self.im, extents) decoder.setimage(self.im, extents)
except ValueError as e: except ValueError as e:
raise OSError("Couldn't set the image") from e msg = "Couldn't set the image"
raise OSError(msg) from e
close_self_fp = self._exclusive_fp and not self.is_animated close_self_fp = self._exclusive_fp and not self.is_animated
if hasattr(self.fp, "getvalue"): if hasattr(self.fp, "getvalue"):
@ -1316,7 +1324,8 @@ class TiffImageFile(ImageFile.ImageFile):
"""Setup this image object based on current tags""" """Setup this image object based on current tags"""
if 0xBC01 in self.tag_v2: if 0xBC01 in self.tag_v2:
raise OSError("Windows Media Photo files not yet supported") msg = "Windows Media Photo files not yet supported"
raise OSError(msg)
# extract relevant tags # extract relevant tags
self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)] self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
@ -1375,7 +1384,8 @@ class TiffImageFile(ImageFile.ImageFile):
logger.error( logger.error(
"More samples per pixel than can be decoded: %s", samples_per_pixel "More samples per pixel than can be decoded: %s", samples_per_pixel
) )
raise SyntaxError("Invalid value for samples per pixel") msg = "Invalid value for samples per pixel"
raise SyntaxError(msg)
if samples_per_pixel < bps_actual_count: if samples_per_pixel < bps_actual_count:
# If a file has more values in bps_tuple than expected, # If a file has more values in bps_tuple than expected,
@ -1387,7 +1397,8 @@ class TiffImageFile(ImageFile.ImageFile):
bps_tuple = bps_tuple * samples_per_pixel bps_tuple = bps_tuple * samples_per_pixel
if len(bps_tuple) != samples_per_pixel: if len(bps_tuple) != samples_per_pixel:
raise SyntaxError("unknown data organization") msg = "unknown data organization"
raise SyntaxError(msg)
# mode: check photometric interpretation and bits per pixel # mode: check photometric interpretation and bits per pixel
key = ( key = (
@ -1403,7 +1414,8 @@ class TiffImageFile(ImageFile.ImageFile):
self.mode, rawmode = OPEN_INFO[key] self.mode, rawmode = OPEN_INFO[key]
except KeyError as e: except KeyError as e:
logger.debug("- unsupported format") logger.debug("- unsupported format")
raise SyntaxError("unknown pixel mode") from e msg = "unknown pixel mode"
raise SyntaxError(msg) from e
logger.debug(f"- raw mode: {rawmode}") logger.debug(f"- raw mode: {rawmode}")
logger.debug(f"- pil mode: {self.mode}") logger.debug(f"- pil mode: {self.mode}")
@ -1519,7 +1531,8 @@ class TiffImageFile(ImageFile.ImageFile):
layer += 1 layer += 1
else: else:
logger.debug("- unsupported data organization") logger.debug("- unsupported data organization")
raise SyntaxError("unknown data organization") msg = "unknown data organization"
raise SyntaxError(msg)
# Fix up info. # Fix up info.
if ICCPROFILE in self.tag_v2: if ICCPROFILE in self.tag_v2:
@ -1571,7 +1584,8 @@ def _save(im, fp, filename):
try: try:
rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode] rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
except KeyError as e: except KeyError as e:
raise OSError(f"cannot write mode {im.mode} as TIFF") from e msg = f"cannot write mode {im.mode} as TIFF"
raise OSError(msg) from e
ifd = ImageFileDirectory_v2(prefix=prefix) ifd = ImageFileDirectory_v2(prefix=prefix)
@ -1736,11 +1750,11 @@ def _save(im, fp, filename):
if "quality" in encoderinfo: if "quality" in encoderinfo:
quality = encoderinfo["quality"] quality = encoderinfo["quality"]
if not isinstance(quality, int) or quality < 0 or quality > 100: if not isinstance(quality, int) or quality < 0 or quality > 100:
raise ValueError("Invalid quality setting") msg = "Invalid quality setting"
raise ValueError(msg)
if compression != "jpeg": if compression != "jpeg":
raise ValueError( msg = "quality setting only supported for 'jpeg' compression"
"quality setting only supported for 'jpeg' compression" raise ValueError(msg)
)
ifd[JPEGQUALITY] = quality ifd[JPEGQUALITY] = quality
logger.debug("Saving using libtiff encoder") logger.debug("Saving using libtiff encoder")
@ -1837,7 +1851,8 @@ def _save(im, fp, filename):
if s: if s:
break break
if s < 0: if s < 0:
raise OSError(f"encoder error {s} when writing image file") msg = f"encoder error {s} when writing image file"
raise OSError(msg)
else: else:
for tag in blocklist: for tag in blocklist:
@ -1912,7 +1927,8 @@ class AppendingTiffWriter:
elif iimm == b"MM\x00\x2a": elif iimm == b"MM\x00\x2a":
self.setEndian(">") self.setEndian(">")
else: else:
raise RuntimeError("Invalid TIFF file header") msg = "Invalid TIFF file header"
raise RuntimeError(msg)
self.skipIFDs() self.skipIFDs()
self.goToEnd() self.goToEnd()
@ -1926,12 +1942,14 @@ class AppendingTiffWriter:
iimm = self.f.read(4) iimm = self.f.read(4)
if not iimm: if not iimm:
# raise RuntimeError("nothing written into new page") # msg = "nothing written into new page"
# raise RuntimeError(msg)
# Make it easy to finish a frame without committing to a new one. # Make it easy to finish a frame without committing to a new one.
return return
if iimm != self.IIMM: if iimm != self.IIMM:
raise RuntimeError("IIMM of new page doesn't match IIMM of first page") msg = "IIMM of new page doesn't match IIMM of first page"
raise RuntimeError(msg)
ifd_offset = self.readLong() ifd_offset = self.readLong()
ifd_offset += self.offsetOfNewPage ifd_offset += self.offsetOfNewPage
@ -2005,29 +2023,34 @@ class AppendingTiffWriter:
self.f.seek(-2, os.SEEK_CUR) self.f.seek(-2, os.SEEK_CUR)
bytes_written = self.f.write(struct.pack(self.longFmt, value)) bytes_written = self.f.write(struct.pack(self.longFmt, value))
if bytes_written is not None and bytes_written != 4: if bytes_written is not None and bytes_written != 4:
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 4") msg = f"wrote only {bytes_written} bytes but wanted 4"
raise RuntimeError(msg)
def rewriteLastShort(self, value): def rewriteLastShort(self, value):
self.f.seek(-2, os.SEEK_CUR) self.f.seek(-2, os.SEEK_CUR)
bytes_written = self.f.write(struct.pack(self.shortFmt, value)) bytes_written = self.f.write(struct.pack(self.shortFmt, value))
if bytes_written is not None and bytes_written != 2: if bytes_written is not None and bytes_written != 2:
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 2") msg = f"wrote only {bytes_written} bytes but wanted 2"
raise RuntimeError(msg)
def rewriteLastLong(self, value): def rewriteLastLong(self, value):
self.f.seek(-4, os.SEEK_CUR) self.f.seek(-4, os.SEEK_CUR)
bytes_written = self.f.write(struct.pack(self.longFmt, value)) bytes_written = self.f.write(struct.pack(self.longFmt, value))
if bytes_written is not None and bytes_written != 4: if bytes_written is not None and bytes_written != 4:
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 4") msg = f"wrote only {bytes_written} bytes but wanted 4"
raise RuntimeError(msg)
def writeShort(self, value): def writeShort(self, value):
bytes_written = self.f.write(struct.pack(self.shortFmt, value)) bytes_written = self.f.write(struct.pack(self.shortFmt, value))
if bytes_written is not None and bytes_written != 2: if bytes_written is not None and bytes_written != 2:
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 2") msg = f"wrote only {bytes_written} bytes but wanted 2"
raise RuntimeError(msg)
def writeLong(self, value): def writeLong(self, value):
bytes_written = self.f.write(struct.pack(self.longFmt, value)) bytes_written = self.f.write(struct.pack(self.longFmt, value))
if bytes_written is not None and bytes_written != 4: if bytes_written is not None and bytes_written != 4:
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 4") msg = f"wrote only {bytes_written} bytes but wanted 4"
raise RuntimeError(msg)
def close(self): def close(self):
self.finalize() self.finalize()
@ -2070,7 +2093,8 @@ class AppendingTiffWriter:
def fixOffsets(self, count, isShort=False, isLong=False): def fixOffsets(self, count, isShort=False, isLong=False):
if not isShort and not isLong: if not isShort and not isLong:
raise RuntimeError("offset is neither short nor long") msg = "offset is neither short nor long"
raise RuntimeError(msg)
for i in range(count): for i in range(count):
offset = self.readShort() if isShort else self.readLong() offset = self.readShort() if isShort else self.readLong()
@ -2078,7 +2102,8 @@ class AppendingTiffWriter:
if isShort and offset >= 65536: if isShort and offset >= 65536:
# offset is now too large - we must convert shorts to longs # offset is now too large - we must convert shorts to longs
if count != 1: if count != 1:
raise RuntimeError("not implemented") # XXX TODO msg = "not implemented"
raise RuntimeError(msg) # XXX TODO
# simple case - the offset is just one and therefore it is # simple case - the offset is just one and therefore it is
# local (not referenced with another offset) # local (not referenced with another offset)

View File

@ -130,7 +130,8 @@ class WebPImageFile(ImageFile.ImageFile):
if ret is None: if ret is None:
self._reset() # Reset just to be safe self._reset() # Reset just to be safe
self.seek(0) self.seek(0)
raise EOFError("failed to decode next frame in WebP file") msg = "failed to decode next frame in WebP file"
raise EOFError(msg)
# Compute duration # Compute duration
data, timestamp = ret data, timestamp = ret
@ -233,9 +234,8 @@ def _save_all(im, fp, filename):
or len(background) != 4 or len(background) != 4
or not all(0 <= v < 256 for v in background) or not all(0 <= v < 256 for v in background)
): ):
raise OSError( msg = f"Background color is not an RGBA tuple clamped to (0-255): {background}"
f"Background color is not an RGBA tuple clamped to (0-255): {background}" raise OSError(msg)
)
# Convert to packed uint # Convert to packed uint
bg_r, bg_g, bg_b, bg_a = background bg_r, bg_g, bg_b, bg_a = background
@ -311,7 +311,8 @@ def _save_all(im, fp, filename):
# Get the final output from the encoder # Get the final output from the encoder
data = enc.assemble(icc_profile, exif, xmp) data = enc.assemble(icc_profile, exif, xmp)
if data is None: if data is None:
raise OSError("cannot write file as WebP (encoder returned None)") msg = "cannot write file as WebP (encoder returned None)"
raise OSError(msg)
fp.write(data) fp.write(data)
@ -351,7 +352,8 @@ def _save(im, fp, filename):
xmp, xmp,
) )
if data is None: if data is None:
raise OSError("cannot write file as WebP (encoder returned None)") msg = "cannot write file as WebP (encoder returned None)"
raise OSError(msg)
fp.write(data) fp.write(data)

View File

@ -109,7 +109,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
# sanity check (standard metafile header) # sanity check (standard metafile header)
if s[22:26] != b"\x01\x00\t\x00": if s[22:26] != b"\x01\x00\t\x00":
raise SyntaxError("Unsupported WMF file format") msg = "Unsupported WMF file format"
raise SyntaxError(msg)
elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF": elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF":
# enhanced metafile # enhanced metafile
@ -137,7 +138,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
self.info["dpi"] = xdpi, ydpi self.info["dpi"] = xdpi, ydpi
else: else:
raise SyntaxError("Unsupported file format") msg = "Unsupported file format"
raise SyntaxError(msg)
self.mode = "RGB" self.mode = "RGB"
self._size = size self._size = size
@ -162,7 +164,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if _handler is None or not hasattr(_handler, "save"): if _handler is None or not hasattr(_handler, "save"):
raise OSError("WMF save handler not installed") msg = "WMF save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename) _handler.save(im, fp, filename)

View File

@ -49,7 +49,8 @@ class XVThumbImageFile(ImageFile.ImageFile):
# check magic # check magic
if not _accept(self.fp.read(6)): if not _accept(self.fp.read(6)):
raise SyntaxError("not an XV thumbnail file") msg = "not an XV thumbnail file"
raise SyntaxError(msg)
# Skip to beginning of next line # Skip to beginning of next line
self.fp.readline() self.fp.readline()
@ -58,7 +59,8 @@ class XVThumbImageFile(ImageFile.ImageFile):
while True: while True:
s = self.fp.readline() s = self.fp.readline()
if not s: if not s:
raise SyntaxError("Unexpected EOF reading XV thumbnail file") msg = "Unexpected EOF reading XV thumbnail file"
raise SyntaxError(msg)
if s[0] != 35: # ie. when not a comment: '#' if s[0] != 35: # ie. when not a comment: '#'
break break

View File

@ -53,7 +53,8 @@ class XbmImageFile(ImageFile.ImageFile):
m = xbm_head.match(self.fp.read(512)) m = xbm_head.match(self.fp.read(512))
if not m: if not m:
raise SyntaxError("not a XBM file") msg = "not a XBM file"
raise SyntaxError(msg)
xsize = int(m.group("width")) xsize = int(m.group("width"))
ysize = int(m.group("height")) ysize = int(m.group("height"))
@ -70,7 +71,8 @@ class XbmImageFile(ImageFile.ImageFile):
def _save(im, fp, filename): def _save(im, fp, filename):
if im.mode != "1": if im.mode != "1":
raise OSError(f"cannot write mode {im.mode} as XBM") msg = f"cannot write mode {im.mode} as XBM"
raise OSError(msg)
fp.write(f"#define im_width {im.size[0]}\n".encode("ascii")) fp.write(f"#define im_width {im.size[0]}\n".encode("ascii"))
fp.write(f"#define im_height {im.size[1]}\n".encode("ascii")) fp.write(f"#define im_height {im.size[1]}\n".encode("ascii"))

View File

@ -40,13 +40,15 @@ class XpmImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
if not _accept(self.fp.read(9)): if not _accept(self.fp.read(9)):
raise SyntaxError("not an XPM file") msg = "not an XPM file"
raise SyntaxError(msg)
# skip forward to next string # skip forward to next string
while True: while True:
s = self.fp.readline() s = self.fp.readline()
if not s: if not s:
raise SyntaxError("broken XPM file") msg = "broken XPM file"
raise SyntaxError(msg)
m = xpm_head.match(s) m = xpm_head.match(s)
if m: if m:
break break
@ -57,7 +59,8 @@ class XpmImageFile(ImageFile.ImageFile):
bpp = int(m.group(4)) bpp = int(m.group(4))
if pal > 256 or bpp != 1: if pal > 256 or bpp != 1:
raise ValueError("cannot read this XPM file") msg = "cannot read this XPM file"
raise ValueError(msg)
# #
# load palette description # load palette description
@ -91,13 +94,15 @@ class XpmImageFile(ImageFile.ImageFile):
) )
else: else:
# unknown colour # unknown colour
raise ValueError("cannot read this XPM file") msg = "cannot read this XPM file"
raise ValueError(msg)
break break
else: else:
# missing colour key # missing colour key
raise ValueError("cannot read this XPM file") msg = "cannot read this XPM file"
raise ValueError(msg)
self.mode = "P" self.mode = "P"
self.palette = ImagePalette.raw("RGB", b"".join(palette)) self.palette = ImagePalette.raw("RGB", b"".join(palette))

View File

@ -43,14 +43,17 @@ def deprecate(
if when is None: if when is None:
removed = "a future version" removed = "a future version"
elif when <= int(__version__.split(".")[0]): elif when <= int(__version__.split(".")[0]):
raise RuntimeError(f"{deprecated} {is_} deprecated and should be removed.") msg = f"{deprecated} {is_} deprecated and should be removed."
raise RuntimeError(msg)
elif when == 10: elif when == 10:
removed = "Pillow 10 (2023-07-01)" removed = "Pillow 10 (2023-07-01)"
else: else:
raise ValueError(f"Unknown removal version, update {__name__}?") msg = f"Unknown removal version, update {__name__}?"
raise ValueError(msg)
if replacement and action: if replacement and action:
raise ValueError("Use only one of 'replacement' and 'action'") msg = "Use only one of 'replacement' and 'action'"
raise ValueError(msg)
if replacement: if replacement:
action = f". Use {replacement} instead." action = f". Use {replacement} instead."

View File

@ -25,7 +25,8 @@ def check_module(feature):
:raises ValueError: If the module is not defined in this version of Pillow. :raises ValueError: If the module is not defined in this version of Pillow.
""" """
if not (feature in modules): if not (feature in modules):
raise ValueError(f"Unknown module {feature}") msg = f"Unknown module {feature}"
raise ValueError(msg)
module, ver = modules[feature] module, ver = modules[feature]
@ -78,7 +79,8 @@ def check_codec(feature):
:raises ValueError: If the codec is not defined in this version of Pillow. :raises ValueError: If the codec is not defined in this version of Pillow.
""" """
if feature not in codecs: if feature not in codecs:
raise ValueError(f"Unknown codec {feature}") msg = f"Unknown codec {feature}"
raise ValueError(msg)
codec, lib = codecs[feature] codec, lib = codecs[feature]
@ -135,7 +137,8 @@ def check_feature(feature):
:raises ValueError: If the feature is not defined in this version of Pillow. :raises ValueError: If the feature is not defined in this version of Pillow.
""" """
if feature not in features: if feature not in features:
raise ValueError(f"Unknown feature {feature}") msg = f"Unknown feature {feature}"
raise ValueError(msg)
module, flag, ver = features[feature] module, flag, ver = features[feature]

View File

@ -478,7 +478,8 @@ def extract_dep(url, filename):
member_abspath = os.path.abspath(os.path.join(sources_dir, member)) member_abspath = os.path.abspath(os.path.join(sources_dir, member))
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath]) member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
if sources_dir_abs != member_prefix: if sources_dir_abs != member_prefix:
raise RuntimeError("Attempted Path Traversal in Zip File") msg = "Attempted Path Traversal in Zip File"
raise RuntimeError(msg)
zf.extractall(sources_dir) zf.extractall(sources_dir)
elif filename.endswith(".tar.gz") or filename.endswith(".tgz"): elif filename.endswith(".tar.gz") or filename.endswith(".tgz"):
with tarfile.open(file, "r:gz") as tgz: with tarfile.open(file, "r:gz") as tgz:
@ -486,7 +487,8 @@ def extract_dep(url, filename):
member_abspath = os.path.abspath(os.path.join(sources_dir, member)) member_abspath = os.path.abspath(os.path.join(sources_dir, member))
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath]) member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
if sources_dir_abs != member_prefix: if sources_dir_abs != member_prefix:
raise RuntimeError("Attempted Path Traversal in Tar File") msg = "Attempted Path Traversal in Tar File"
raise RuntimeError(msg)
tgz.extractall(sources_dir) tgz.extractall(sources_dir)
else: else:
raise RuntimeError("Unknown archive type: " + filename) raise RuntimeError("Unknown archive type: " + filename)
@ -642,9 +644,8 @@ if __name__ == "__main__":
msvs = find_msvs() msvs = find_msvs()
if msvs is None: if msvs is None:
raise RuntimeError( msg = "Visual Studio not found. Please install Visual Studio 2017 or newer."
"Visual Studio not found. Please install Visual Studio 2017 or newer." raise RuntimeError(msg)
)
print("Found Visual Studio at:", msvs["vs_dir"]) print("Found Visual Studio at:", msvs["vs_dir"])
print("Using output directory:", build_dir) print("Using output directory:", build_dir)