diff --git a/Tests/bench_cffi_access.py b/Tests/bench_cffi_access.py index f196757dc..f9edcf09a 100644 --- a/Tests/bench_cffi_access.py +++ b/Tests/bench_cffi_access.py @@ -28,15 +28,17 @@ def timer(func, label, *args): func(*args) if time.time() - starttime > 10: print( - "%s: breaking at %s iterations, %.6f per iteration" - % (label, x + 1, (time.time() - starttime) / (x + 1.0)) + "{}: breaking at {} iterations, {:.6f} per iteration".format( + label, x + 1, (time.time() - starttime) / (x + 1.0) + ) ) break if x == iterations - 1: endtime = time.time() print( - "%s: %.4f s %.6f per iteration" - % (label, endtime - starttime, (endtime - starttime) / (x + 1.0)) + "{}: {:.4f} s {:.6f} per iteration".format( + label, endtime - starttime, (endtime - starttime) / (x + 1.0) + ) ) diff --git a/Tests/check_imaging_leaks.py b/Tests/check_imaging_leaks.py index db12d00e3..ae05ebade 100755 --- a/Tests/check_imaging_leaks.py +++ b/Tests/check_imaging_leaks.py @@ -25,7 +25,7 @@ def _test_leak(min_iterations, max_iterations, fn, *args, **kwargs): if i < min_iterations: mem_limit = mem + 1 continue - msg = "memory usage limit exceeded after %d iterations" % (i + 1) + msg = f"memory usage limit exceeded after {i + 1} iterations" assert mem <= mem_limit, msg diff --git a/Tests/check_png_dos.py b/Tests/check_png_dos.py index 86eb937e9..d8d645189 100644 --- a/Tests/check_png_dos.py +++ b/Tests/check_png_dos.py @@ -42,8 +42,8 @@ def test_dos_total_memory(): info = PngImagePlugin.PngInfo() for x in range(64): - info.add_text("t%s" % x, compressed_data, zip=True) - info.add_itxt("i%s" % x, compressed_data, zip=True) + info.add_text(f"t{x}", compressed_data, zip=True) + info.add_itxt(f"i{x}", compressed_data, zip=True) b = BytesIO() im.save(b, "PNG", pnginfo=info) diff --git a/Tests/conftest.py b/Tests/conftest.py index 624eab73c..082f2f7c3 100644 --- a/Tests/conftest.py +++ b/Tests/conftest.py @@ -9,4 +9,4 @@ def pytest_report_header(config): features.pilinfo(out=out, supported_formats=False) return out.getvalue() except Exception as e: - return "pytest_report_header failed: %s" % e + return f"pytest_report_header failed: {e}" diff --git a/Tests/createfontdatachunk.py b/Tests/createfontdatachunk.py index c7055995e..011bb0bed 100755 --- a/Tests/createfontdatachunk.py +++ b/Tests/createfontdatachunk.py @@ -6,7 +6,7 @@ if __name__ == "__main__": # create font data chunk for embedding font = "Tests/images/courB08" print(" f._load_pilfont_data(") - print(" # %s" % os.path.basename(font)) + print(f" # {os.path.basename(font)}") print(" BytesIO(base64.decodestring(b'''") with open(font + ".pil", "rb") as fp: print(base64.b64encode(fp.read()).decode()) diff --git a/Tests/helper.py b/Tests/helper.py index cdc5f4efe..4c5f2198e 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -67,37 +67,31 @@ def convert_to_comparable(a, b): def assert_deep_equal(a, b, msg=None): try: - assert len(a) == len(b), msg or "got length {}, expected {}".format( - len(a), len(b) - ) + assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}" except Exception: assert a == b, msg def assert_image(im, mode, size, msg=None): if mode is not None: - assert im.mode == mode, msg or "got mode {!r}, expected {!r}".format( - im.mode, mode + assert im.mode == mode, ( + msg or f"got mode {repr(im.mode)}, expected {repr(mode)}" ) if size is not None: - assert im.size == size, msg or "got size {!r}, expected {!r}".format( - im.size, size + assert im.size == size, ( + msg or f"got size {repr(im.size)}, expected {repr(size)}" ) def assert_image_equal(a, b, msg=None): - assert a.mode == b.mode, msg or "got mode {!r}, expected {!r}".format( - a.mode, b.mode - ) - assert a.size == b.size, msg or "got size {!r}, expected {!r}".format( - a.size, b.size - ) + assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}" + assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}" if a.tobytes() != b.tobytes(): if HAS_UPLOADER: try: url = test_image_results.upload(a, b) - logger.error("Url for test images: %s" % url) + logger.error(f"Url for test images: {url}") except Exception: pass @@ -112,12 +106,8 @@ def assert_image_equal_tofile(a, filename, msg=None, mode=None): def assert_image_similar(a, b, epsilon, msg=None): - assert a.mode == b.mode, msg or "got mode {!r}, expected {!r}".format( - a.mode, b.mode - ) - assert a.size == b.size, msg or "got size {!r}, expected {!r}".format( - a.size, b.size - ) + assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}" + assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}" a, b = convert_to_comparable(a, b) @@ -129,13 +119,14 @@ def assert_image_similar(a, b, epsilon, msg=None): ave_diff = diff / (a.size[0] * a.size[1]) try: assert epsilon >= ave_diff, ( - msg or "" - ) + " average pixel value difference %.4f > epsilon %.4f" % (ave_diff, epsilon) + (msg or "") + + f" average pixel value difference {ave_diff:.4f} > epsilon {epsilon:.4f}" + ) except Exception as e: if HAS_UPLOADER: try: url = test_image_results.upload(a, b) - logger.error("Url for test images: %s" % url) + logger.error(f"Url for test images: {url}") except Exception: pass raise e @@ -166,7 +157,7 @@ def assert_tuple_approx_equal(actuals, targets, threshold, msg): def skip_unless_feature(feature): - reason = "%s not available" % feature + reason = f"{feature} not available" return pytest.mark.skipif(not features.check(feature), reason=reason) @@ -204,7 +195,7 @@ class PillowLeakTestCase: for cycle in range(self.iterations): core() mem = self._get_mem_usage() - start_mem - msg = "memory usage limit exceeded in iteration %d" % cycle + msg = f"memory usage limit exceeded in iteration {cycle}" assert mem < self.mem_limit, msg diff --git a/Tests/test_bmp_reference.py b/Tests/test_bmp_reference.py index ade2901b7..64156a4ec 100644 --- a/Tests/test_bmp_reference.py +++ b/Tests/test_bmp_reference.py @@ -49,7 +49,7 @@ def test_questionable(): with Image.open(f) as im: im.load() if os.path.basename(f) not in supported: - print("Please add %s to the partially supported bmp specs." % f) + print(f"Please add {f} to the partially supported bmp specs.") except Exception: # as msg: if os.path.basename(f) in supported: raise @@ -84,7 +84,7 @@ def test_good(): if name in file_map: return os.path.join(base, "html", file_map[name]) name = os.path.splitext(name)[0] - return os.path.join(base, "html", "%s.png" % name) + return os.path.join(base, "html", f"{name}.png") for f in get_files("g"): try: @@ -107,4 +107,4 @@ def test_good(): os.path.join(base, "g", "pal8rle.bmp"), os.path.join(base, "g", "pal4rle.bmp"), ) - assert f in unsupported, "Unsupported Image {}: {}".format(f, msg) + assert f in unsupported, f"Unsupported Image {f}: {msg}" diff --git a/Tests/test_file_apng.py b/Tests/test_file_apng.py index 0eca78690..7a46f4019 100644 --- a/Tests/test_file_apng.py +++ b/Tests/test_file_apng.py @@ -311,7 +311,7 @@ def test_apng_sequence_errors(): ] for f in test_files: with pytest.raises(SyntaxError): - with Image.open("Tests/images/apng/{0}".format(f)) as im: + with Image.open(f"Tests/images/apng/{f}") as im: im.seek(im.n_frames - 1) im.load() diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 300967a30..19a06a15d 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -173,18 +173,18 @@ class TestFileLibTiff(LibTiffTestCase): assert ( c_float(val[0][0] / val[0][1]).value == c_float(value[0][0] / value[0][1]).value - ), ("%s didn't roundtrip" % tag) + ), f"{tag} didn't roundtrip" else: - assert c_float(val).value == c_float(value).value, ( - "%s didn't roundtrip" % tag - ) + assert ( + c_float(val).value == c_float(value).value + ), f"{tag} didn't roundtrip" else: - assert val == value, "%s didn't roundtrip" % tag + assert val == value, f"{tag} didn't roundtrip" # https://github.com/python-pillow/Pillow/issues/1561 requested_fields = ["StripByteCounts", "RowsPerStrip", "StripOffsets"] for field in requested_fields: - assert field in reloaded, "%s not in metadata" % field + assert field in reloaded, f"{field} not in metadata" def test_additional_metadata(self, tmp_path): # these should not crash. Seriously dummy data, most of it doesn't make diff --git a/Tests/test_file_sun.py b/Tests/test_file_sun.py index 03e26ef8b..b2bfb5b9e 100644 --- a/Tests/test_file_sun.py +++ b/Tests/test_file_sun.py @@ -45,7 +45,7 @@ def test_others(): with Image.open(path) as im: im.load() assert isinstance(im, SunImagePlugin.SunImageFile) - target_path = "%s.png" % os.path.splitext(path)[0] + target_path = f"{os.path.splitext(path)[0]}.png" # im.save(target_file) with Image.open(target_path) as target: assert_image_equal(im, target) diff --git a/Tests/test_file_tga.py b/Tests/test_file_tga.py index 4919ad766..bac1b4dd6 100644 --- a/Tests/test_file_tga.py +++ b/Tests/test_file_tga.py @@ -35,9 +35,7 @@ def test_sanity(tmp_path): assert_image_equal(saved_im, original_im) - png_paths = glob( - os.path.join(_TGA_DIR_COMMON, "*x*_{}.png".format(mode.lower())) - ) + png_paths = glob(os.path.join(_TGA_DIR_COMMON, f"*x*_{mode.lower()}.png")) for png_path in png_paths: with Image.open(png_path) as reference_im: diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index d57f63717..179d1adf3 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -144,16 +144,16 @@ def test_write_metadata(tmp_path): assert_deep_equal( original[tag], value, - "{} didn't roundtrip, {}, {}".format(tag, original[tag], value), + f"{tag} didn't roundtrip, {original[tag]}, {value}", ) else: - assert original[tag] == value, "{} didn't roundtrip, {}, {}".format( - tag, original[tag], value - ) + assert ( + original[tag] == value + ), f"{tag} didn't roundtrip, {original[tag]}, {value}" for tag, value in original.items(): if tag not in ignored: - assert value == reloaded[tag], "%s didn't roundtrip" % tag + assert value == reloaded[tag], f"{tag} didn't roundtrip" def test_change_stripbytecounts_tag_type(tmp_path): diff --git a/Tests/test_font_pcf_charsets.py b/Tests/test_font_pcf_charsets.py index 4a39803be..d7d1bf200 100644 --- a/Tests/test_font_pcf_charsets.py +++ b/Tests/test_font_pcf_charsets.py @@ -47,11 +47,11 @@ def save_font(request, tmp_path, encoding): font.save(tempname) with Image.open(tempname.replace(".pil", ".pbm")) as loaded: - with Image.open("Tests/fonts/ter-x20b-%s.pbm" % encoding) as target: + with Image.open(f"Tests/fonts/ter-x20b-{encoding}.pbm") as target: assert_image_equal(loaded, target) with open(tempname, "rb") as f_loaded: - with open("Tests/fonts/ter-x20b-%s.pil" % encoding, "rb") as f_target: + with open(f"Tests/fonts/ter-x20b-{encoding}.pil", "rb") as f_target: assert f_loaded.read() == f_target.read() return tempname diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 25cc9fef4..af51a4fb3 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -125,14 +125,13 @@ class TestImageGetPixel(AccessTest): im.putpixel((0, 0), c) assert ( im.getpixel((0, 0)) == c - ), "put/getpixel roundtrip failed for mode {}, color {}".format(mode, c) + ), f"put/getpixel roundtrip failed for mode {mode}, color {c}" # check putpixel negative index im.putpixel((-1, -1), c) - assert im.getpixel((-1, -1)) == c, ( - "put/getpixel roundtrip negative index failed for mode %s, color %s" - % (mode, c) - ) + assert ( + im.getpixel((-1, -1)) == c + ), f"put/getpixel roundtrip negative index failed for mode {mode}, color {c}" # Check 0 im = Image.new(mode, (0, 0), None) @@ -150,11 +149,11 @@ class TestImageGetPixel(AccessTest): im = Image.new(mode, (1, 1), c) assert ( im.getpixel((0, 0)) == c - ), "initial color failed for mode {}, color {} ".format(mode, c) + ), f"initial color failed for mode {mode}, color {c} " # check initial color negative index assert ( im.getpixel((-1, -1)) == c - ), "initial color failed with negative index for mode %s, color %s " % (mode, c) + ), f"initial color failed with negative index for mode {mode}, color {c} " # Check 0 im = Image.new(mode, (0, 0), c) diff --git a/Tests/test_image_reduce.py b/Tests/test_image_reduce.py index 0f92b87f8..b11269918 100644 --- a/Tests/test_image_reduce.py +++ b/Tests/test_image_reduce.py @@ -161,8 +161,8 @@ def compare_reduce_with_reference(im, factor, average_diff=0.4, max_diff=1): def assert_compare_images(a, b, max_average_diff, max_diff=255): - assert a.mode == b.mode, "got mode %r, expected %r" % (a.mode, b.mode) - assert a.size == b.size, "got size %r, expected %r" % (a.size, b.size) + assert a.mode == b.mode, f"got mode {repr(a.mode)}, expected {repr(b.mode)}" + assert a.size == b.size, f"got size {repr(a.size)}, expected {repr(b.size)}" a, b = convert_to_comparable(a, b) @@ -175,16 +175,15 @@ def assert_compare_images(a, b, max_average_diff, max_diff=255): a.size[0] * a.size[1] ) msg = ( - "average pixel value difference {:.4f} > expected {:.4f} " - "for '{}' band".format(average_diff, max_average_diff, band) + f"average pixel value difference {average_diff:.4f} > " + f"expected {max_average_diff:.4f} for '{band}' band" ) assert max_average_diff >= average_diff, msg last_diff = [i for i, num in enumerate(ch_hist) if num > 0][-1] - assert ( - max_diff >= last_diff - ), "max pixel value difference {} > expected {} for '{}' band".format( - last_diff, max_diff, band + assert max_diff >= last_diff, ( + f"max pixel value difference {last_diff} > expected {max_diff} " + f"for '{band}' band" ) diff --git a/Tests/test_image_resample.py b/Tests/test_image_resample.py index 35eae128b..a6d861520 100644 --- a/Tests/test_image_resample.py +++ b/Tests/test_image_resample.py @@ -81,15 +81,16 @@ class TestImagingCoreResampleAccuracy: for y in range(case.size[1]): for x in range(case.size[0]): if c_px[x, y] != s_px[x, y]: - message = "\nHave: \n{}\n\nExpected: \n{}".format( - self.serialize_image(case), self.serialize_image(sample) + message = ( + f"\nHave: \n{self.serialize_image(case)}\n" + f"\nExpected: \n{self.serialize_image(sample)}" ) assert s_px[x, y] == c_px[x, y], message def serialize_image(self, image): s_px = image.load() return "\n".join( - " ".join("{:02x}".format(s_px[x, y]) for x in range(image.size[0])) + " ".join(f"{s_px[x, y]:02x}" for x in range(image.size[0])) for y in range(image.size[1]) ) @@ -229,7 +230,7 @@ class TestCoreResampleConsistency: for x in range(channel.size[0]): for y in range(channel.size[1]): if px[x, y] != color: - message = "{} != {} for pixel {}".format(px[x, y], color, (x, y)) + message = f"{px[x, y]} != {color} for pixel {(x, y)}" assert px[x, y] == color, message def test_8u(self): @@ -268,10 +269,9 @@ class TestCoreResampleAlphaCorrect: px = i.load() for y in range(i.size[1]): used_colors = {px[x, y][0] for x in range(i.size[0])} - assert 256 == len( - used_colors - ), "All colors should present in resized image. Only {} on {} line.".format( - len(used_colors), y + assert 256 == len(used_colors), ( + "All colors should be present in resized image. " + f"Only {len(used_colors)} on {y} line." ) @pytest.mark.xfail(reason="Current implementation isn't precise enough") @@ -307,8 +307,9 @@ class TestCoreResampleAlphaCorrect: for y in range(i.size[1]): for x in range(i.size[0]): if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel: - message = "pixel at ({}, {}) is differ:\n{}\n{}".format( - x, y, px[x, y], clean_pixel + message = ( + f"pixel at ({x}, {y}) is different:\n" + f"{px[x, y]}\n{clean_pixel}" ) assert px[x, y][:3] == clean_pixel, message @@ -503,7 +504,7 @@ class TestCoreResampleBox: ]: res = im.resize(size, Image.LANCZOS, box) assert res.size == size - assert_image_equal(res, im.crop(box), ">>> {} {}".format(size, box)) + assert_image_equal(res, im.crop(box), f">>> {size} {box}") def test_no_passthrough(self): # When resize is required @@ -519,9 +520,7 @@ class TestCoreResampleBox: assert res.size == size with pytest.raises(AssertionError, match=r"difference \d"): # check that the difference at least that much - assert_image_similar( - res, im.crop(box), 20, ">>> {} {}".format(size, box) - ) + assert_image_similar(res, im.crop(box), 20, f">>> {size} {box}") def test_skip_horizontal(self): # Can skip resize for one dimension @@ -538,10 +537,7 @@ class TestCoreResampleBox: assert res.size == size # Borders should be slightly different assert_image_similar( - res, - im.crop(box).resize(size, flt), - 0.4, - ">>> {} {} {}".format(size, box, flt), + res, im.crop(box).resize(size, flt), 0.4, f">>> {size} {box} {flt}", ) def test_skip_vertical(self): @@ -559,8 +555,5 @@ class TestCoreResampleBox: assert res.size == size # Borders should be slightly different assert_image_similar( - res, - im.crop(box).resize(size, flt), - 0.4, - ">>> {} {} {}".format(size, box, flt), + res, im.crop(box).resize(size, flt), 0.4, f">>> {size} {box} {flt}", ) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 56b189ecd..283006b3d 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -181,7 +181,7 @@ def helper_chord(mode, bbox, start, end): # Arrange im = Image.new(mode, (W, H)) draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_chord_{}.png".format(mode) + expected = f"Tests/images/imagedraw_chord_{mode}.png" # Act draw.chord(bbox, start, end, fill="red", outline="yellow") @@ -243,7 +243,7 @@ def helper_ellipse(mode, bbox): # Arrange im = Image.new(mode, (W, H)) draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) + expected = f"Tests/images/imagedraw_ellipse_{mode}.png" # Act draw.ellipse(bbox, fill="green", outline="blue") @@ -513,7 +513,7 @@ def test_polygon_kite(): # Arrange im = Image.new(mode, (W, H)) draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_polygon_kite_{}.png".format(mode) + expected = f"Tests/images/imagedraw_polygon_kite_{mode}.png" # Act draw.polygon(KITE_POINTS, fill="blue", outline="yellow") @@ -1087,7 +1087,5 @@ def test_same_color_outline(): draw_method(*args) # Assert - expected = "Tests/images/imagedraw_outline_{}_{}.png".format( - operation, mode - ) + expected = f"Tests/images/imagedraw_outline_{operation}_{mode}.png" assert_image_similar_tofile(im, expected, 1) diff --git a/Tests/test_imagedraw2.py b/Tests/test_imagedraw2.py index 72cbb79b8..0d9f16ce8 100644 --- a/Tests/test_imagedraw2.py +++ b/Tests/test_imagedraw2.py @@ -55,7 +55,7 @@ def helper_ellipse(mode, bbox): draw = ImageDraw2.Draw(im) pen = ImageDraw2.Pen("blue", width=2) brush = ImageDraw2.Brush("green") - expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) + expected = f"Tests/images/imagedraw_ellipse_{mode}.png" # Act draw.ellipse(bbox, pen, brush) diff --git a/Tests/test_imageenhance.py b/Tests/test_imageenhance.py index 32ab05f17..32222c1d3 100644 --- a/Tests/test_imageenhance.py +++ b/Tests/test_imageenhance.py @@ -33,9 +33,7 @@ def _half_transparent_image(): def _check_alpha(im, original, op, amount): assert im.getbands() == original.getbands() assert_image_equal( - im.getchannel("A"), - original.getchannel("A"), - "Diff on {}: {}".format(op, amount), + im.getchannel("A"), original.getchannel("A"), f"Diff on {op}: {amount}", ) diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py index bc4f1af28..239806796 100644 --- a/Tests/test_imagemath.py +++ b/Tests/test_imagemath.py @@ -3,7 +3,7 @@ from PIL import Image, ImageMath def pixel(im): if hasattr(im, "im"): - return "{} {!r}".format(im.mode, im.getpixel((0, 0))) + return "{} {}".format(im.mode, repr(im.getpixel((0, 0)))) else: if isinstance(im, int): return int(im) # hack to deal with booleans diff --git a/Tests/test_imagemorph.py b/Tests/test_imagemorph.py index 62119e4b3..5b0be938a 100644 --- a/Tests/test_imagemorph.py +++ b/Tests/test_imagemorph.py @@ -64,7 +64,7 @@ def create_lut(): for op in ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge"): lb = ImageMorph.LutBuilder(op_name=op) lut = lb.build_lut() - with open("Tests/images/%s.lut" % op, "wb") as f: + with open(f"Tests/images/{op}.lut", "wb") as f: f.write(lut) @@ -75,7 +75,7 @@ def test_lut(): assert lb.get_lut() is None lut = lb.build_lut() - with open("Tests/images/%s.lut" % op, "rb") as f: + with open(f"Tests/images/{op}.lut", "rb") as f: assert lut == bytearray(f.read()) diff --git a/Tests/test_imagetk.py b/Tests/test_imagetk.py index d13920c16..7e87ac902 100644 --- a/Tests/test_imagetk.py +++ b/Tests/test_imagetk.py @@ -26,7 +26,7 @@ def setup_module(): tk.Frame() # root = tk.Tk() except tk.TclError as v: - pytest.skip("TCL Error: %s" % v) + pytest.skip(f"TCL Error: {v}") def test_kw(): diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index 19e16f2c4..0571aabf4 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -15,9 +15,9 @@ def verify(im1): xy = x, y p1 = pix1[xy] p2 = pix2[xy] - assert p1 == p2, "got {!r} from mode {} at {}, expected {!r}".format( - p1, im1.mode, xy, p2 - ) + assert ( + p1 == p2 + ), f"got {repr(p1)} from mode {im1.mode} at {xy}, expected {repr(p2)}" def test_basic(tmp_path): diff --git a/Tests/test_qt_image_toqimage.py b/Tests/test_qt_image_toqimage.py index 4c98bf0b4..fcb8c2f2a 100644 --- a/Tests/test_qt_image_toqimage.py +++ b/Tests/test_qt_image_toqimage.py @@ -42,7 +42,7 @@ def test_sanity(tmp_path): continue # Test saving the file - tempfile = str(tmp_path / "temp_{}.png".format(mode)) + tempfile = str(tmp_path / f"temp_{mode}.png") data.save(tempfile) # Check that it actually worked. diff --git a/Tests/test_qt_image_toqpixmap.py b/Tests/test_qt_image_toqpixmap.py index af281da69..f38cc7f13 100644 --- a/Tests/test_qt_image_toqpixmap.py +++ b/Tests/test_qt_image_toqpixmap.py @@ -16,5 +16,5 @@ class TestToQPixmap(PillowQPixmapTestCase): assert not data.isNull() # Test saving the file - tempfile = str(tmp_path / "temp_{}.png".format(mode)) + tempfile = str(tmp_path / f"temp_{mode}.png") data.save(tempfile) diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index 1e36f093a..78aa3ce72 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -212,10 +212,10 @@ class DdsImageFile(ImageFile.ImageFile): def _open(self): magic, header_size = struct.unpack("= (3, 9): warnings.warn( - "Pillow {} does not support Python {}.{} and does not provide prebuilt " - "Windows binaries. We do not recommend building from source on Windows.".format( - PILLOW_VERSION, sys.version_info.major, sys.version_info.minor - ), + f"Pillow {PILLOW_VERSION} does not support Python " + f"{sys.version_info.major}.{sys.version_info.minor} and does not provide " + "prebuilt Windows binaries. We do not recommend building from source on " + "Windows.", RuntimeWarning, ) @@ -175,7 +175,7 @@ def _find_library_dirs_ldconfig(): # Assuming GLIBC's ldconfig (with option -p) # Alpine Linux uses musl that can't print cache args = ["/sbin/ldconfig", "-p"] - expr = r".*\(%s.*\) => (.*)" % abi_type + expr = fr".*\({abi_type}.*\) => (.*)" env = dict(os.environ) env["LC_ALL"] = "C" env["LANG"] = "C" @@ -308,8 +308,8 @@ class pil_build_ext(build_ext): user_options = ( build_ext.user_options - + [("disable-%s" % x, None, "Disable support for %s" % x) for x in feature] - + [("enable-%s" % x, None, "Enable support for %s" % x) for x in feature] + + [(f"disable-{x}", None, f"Disable support for {x}") for x in feature] + + [(f"enable-{x}", None, f"Enable support for {x}") for x in feature] + [ ("disable-platform-guessing", None, "Disable platform guessing on Linux"), ("debug", None, "Debug logging"), @@ -322,8 +322,8 @@ class pil_build_ext(build_ext): self.add_imaging_libs = "" build_ext.initialize_options(self) for x in self.feature: - setattr(self, "disable_%s" % x, None) - setattr(self, "enable_%s" % x, None) + setattr(self, f"disable_{x}", None) + setattr(self, f"enable_{x}", None) def finalize_options(self): build_ext.finalize_options(self) @@ -340,15 +340,15 @@ class pil_build_ext(build_ext): except TypeError: self.parallel = None for x in self.feature: - if getattr(self, "disable_%s" % x): + if getattr(self, f"disable_{x}"): setattr(self.feature, x, False) self.feature.required.discard(x) _dbg("Disabling %s", x) - if getattr(self, "enable_%s" % x): + if getattr(self, f"enable_{x}"): raise ValueError( - "Conflicting options: --enable-{} and --disable-{}".format(x, x) + f"Conflicting options: --enable-{x} and --disable-{x}" ) - if getattr(self, "enable_%s" % x): + if getattr(self, f"enable_{x}"): _dbg("Requiring %s", x) self.feature.required.add(x) @@ -383,12 +383,12 @@ class pil_build_ext(build_ext): if root is None and pkg_config: if isinstance(lib_name, tuple): for lib_name2 in lib_name: - _dbg("Looking for `%s` using pkg-config." % lib_name2) + _dbg(f"Looking for `{lib_name2}` using pkg-config.") root = pkg_config(lib_name2) if root: break else: - _dbg("Looking for `%s` using pkg-config." % lib_name) + _dbg(f"Looking for `{lib_name}` using pkg-config.") root = pkg_config(lib_name) if isinstance(root, tuple): @@ -733,9 +733,9 @@ class pil_build_ext(build_ext): and sys.version_info < (3, 9) and not (PLATFORM_PYPY or PLATFORM_MINGW) ): - defs.append(("PILLOW_VERSION", '"\\"%s\\""' % PILLOW_VERSION)) + defs.append(("PILLOW_VERSION", f'"\\"{PILLOW_VERSION}\\""')) else: - defs.append(("PILLOW_VERSION", '"%s"' % PILLOW_VERSION)) + defs.append(("PILLOW_VERSION", f'"{PILLOW_VERSION}"')) exts = [(Extension("PIL._imaging", files, libraries=libs, define_macros=defs))] @@ -808,11 +808,11 @@ class pil_build_ext(build_ext): print("-" * 68) print("PIL SETUP SUMMARY") print("-" * 68) - print("version Pillow %s" % PILLOW_VERSION) + print(f"version Pillow {PILLOW_VERSION}") v = sys.version.split("[") - print("platform {} {}".format(sys.platform, v[0].strip())) + print(f"platform {sys.platform} {v[0].strip()}") for v in v[1:]: - print(" [%s" % v.strip()) + print(f" [{v.strip()}") print("-" * 68) options = [ @@ -833,10 +833,10 @@ class pil_build_ext(build_ext): if option[0]: version = "" if len(option) >= 3 and option[2]: - version = " (%s)" % option[2] - print("--- {} support available{}".format(option[1], version)) + version = f" ({option[2]})" + print(f"--- {option[1]} support available{version}") else: - print("*** %s support not available" % option[1]) + print(f"*** {option[1]} support not available") all = 0 print("-" * 68) @@ -900,28 +900,23 @@ try: zip_safe=not (debug_build() or PLATFORM_MINGW), ) except RequiredDependencyException as err: - msg = """ + msg = f""" -The headers or library files could not be found for %s, +The headers or library files could not be found for {str(err)}, a required dependency when compiling Pillow from source. Please see the install instructions at: https://pillow.readthedocs.io/en/latest/installation.html -""" % ( - str(err) - ) +""" sys.stderr.write(msg) raise RequiredDependencyException(msg) except DependencyException as err: - msg = """ + msg = f""" -The headers or library files could not be found for %s, -which was requested by the option flag --enable-%s +The headers or library files could not be found for {str(err)}, +which was requested by the option flag --enable-{str(err)} -""" % ( - str(err), - str(err), - ) +""" sys.stderr.write(msg) raise DependencyException(msg) diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index cb8a08e20..d5d7c0e05 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -250,7 +250,7 @@ class BlpImageFile(ImageFile.ImageFile): decoder = "BLP2" self.mode = "RGBA" if self._blp_alpha_depth else "RGB" else: - raise BLPFormatError("Bad BLP magic %r" % (self.magic)) + raise BLPFormatError(f"Bad BLP magic {repr(self.magic)}") self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))] @@ -336,11 +336,11 @@ class BLP1Decoder(_BLPBaseDecoder): self.set_as_raw(bytes(data)) else: raise BLPFormatError( - "Unsupported BLP encoding %r" % (self._blp_encoding) + f"Unsupported BLP encoding {repr(self._blp_encoding)}" ) else: raise BLPFormatError( - "Unsupported BLP compression %r" % (self._blp_encoding) + f"Unsupported BLP compression {repr(self._blp_encoding)}" ) def _decode_jpeg_stream(self): @@ -400,13 +400,15 @@ class BLP2Decoder(_BLPBaseDecoder): data += d else: raise BLPFormatError( - "Unsupported alpha encoding %r" % (self._blp_alpha_encoding) + f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}" ) else: - raise BLPFormatError("Unknown BLP encoding %r" % (self._blp_encoding)) + raise BLPFormatError(f"Unknown BLP encoding {repr(self._blp_encoding)}") else: - raise BLPFormatError("Unknown BLP compression %r" % (self._blp_compression)) + raise BLPFormatError( + f"Unknown BLP compression {repr(self._blp_compression)}" + ) self.set_as_raw(bytes(data)) diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 1d348b5a3..c1931b791 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -144,7 +144,7 @@ class BmpImageFile(ImageFile.ImageFile): file_info["a_mask"], ) else: - raise OSError("Unsupported BMP header type (%d)" % file_info["header_size"]) + raise OSError(f"Unsupported BMP header type ({file_info['header_size']})") # ------------------ Special case : header is reported 40, which # ---------------------- is shorter than real size for bpp >= 16 @@ -164,7 +164,7 @@ class BmpImageFile(ImageFile.ImageFile): # ---------------------- Check bit depth for unusual unsupported values self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None)) if self.mode is None: - raise OSError("Unsupported BMP pixel depth (%d)" % file_info["bits"]) + raise OSError(f"Unsupported BMP pixel depth ({file_info['bits']})") # ---------------- Process BMP with Bitfields compression (not palette) if file_info["compression"] == self.BITFIELDS: @@ -209,14 +209,14 @@ class BmpImageFile(ImageFile.ImageFile): if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset raw_mode, self.mode = "BGRA", "RGBA" else: - raise OSError("Unsupported BMP compression (%d)" % file_info["compression"]) + raise OSError(f"Unsupported BMP compression ({file_info['compression']})") # --------------- Once the header is processed, process the palette/LUT if self.mode == "P": # Paletted for 1, 4 and 8 bit images # ---------------------------------------------------- 1-bit images if not (0 < file_info["colors"] <= 65536): - raise OSError("Unsupported BMP Palette size (%d)" % file_info["colors"]) + raise OSError(f"Unsupported BMP Palette size ({file_info['colors']})") else: padding = file_info["palette_padding"] palette = read(padding * file_info["colors"]) @@ -305,7 +305,7 @@ def _save(im, fp, filename, bitmap_header=True): try: rawmode, bits, colors = SAVE[im.mode] except KeyError as e: - raise OSError("cannot write mode %s as BMP" % im.mode) from e + raise OSError(f"cannot write mode {im.mode} as BMP") from e info = im.encoderinfo diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 9ba6e0ff8..3837192ab 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -106,10 +106,10 @@ class DdsImageFile(ImageFile.ImageFile): def _open(self): magic, header_size = struct.unpack("= (3, 7): if name == "PILLOW_VERSION": _raise_version_warning() return __version__ - raise AttributeError("module '{}' has no attribute '{}'".format(__name__, name)) + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") else: @@ -96,8 +96,8 @@ try: if __version__ != getattr(core, "PILLOW_VERSION", None): raise ImportError( "The _imaging extension was built for another version of Pillow or PIL:\n" - "Core version: %s\n" - "Pillow version: %s" % (getattr(core, "PILLOW_VERSION", None), __version__) + f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n" + f"Pillow version: {__version__}" ) except ImportError as v: @@ -403,7 +403,7 @@ def init(): for plugin in _plugins: try: logger.debug("Importing %s", plugin) - __import__("PIL.%s" % plugin, globals(), locals(), []) + __import__(f"PIL.{plugin}", globals(), locals(), []) except ImportError as e: logger.debug("Image: failed to import %s: %s", plugin, e) @@ -435,7 +435,7 @@ def _getdecoder(mode, decoder_name, args, extra=()): # get decoder decoder = getattr(core, decoder_name + "_decoder") except AttributeError as e: - raise OSError("decoder %s not available" % decoder_name) from e + raise OSError(f"decoder {decoder_name} not available") from e return decoder(mode, *args + extra) @@ -458,7 +458,7 @@ def _getencoder(mode, encoder_name, args, extra=()): # get encoder encoder = getattr(core, encoder_name + "_encoder") except AttributeError as e: - raise OSError("encoder %s not available" % encoder_name) from e + raise OSError(f"encoder {encoder_name} not available") from e return encoder(mode, *args + extra) @@ -742,7 +742,7 @@ class Image: if s: break if s < 0: - raise RuntimeError("encoder error %d in tobytes" % s) + raise RuntimeError(f"encoder error {s} in tobytes") return b"".join(data) @@ -763,9 +763,9 @@ class Image: data = self.tobytes("xbm") return b"".join( [ - ("#define %s_width %d\n" % (name, self.size[0])).encode("ascii"), - ("#define %s_height %d\n" % (name, self.size[1])).encode("ascii"), - ("static char %s_bits[] = {\n" % name).encode("ascii"), + f"#define {name}_width {self.size[0]}\n".encode("ascii"), + f"#define {name}_height {self.size[1]}\n".encode("ascii"), + f"static char {name}_bits[] = {{\n".encode("ascii"), data, b"};", ] @@ -1861,7 +1861,7 @@ class Image: """ if resample not in (NEAREST, BILINEAR, BICUBIC, LANCZOS, BOX, HAMMING): - message = "Unknown resampling filter ({}).".format(resample) + message = f"Unknown resampling filter ({resample})." filters = [ "{} ({})".format(filter[1], filter[0]) @@ -2129,7 +2129,7 @@ class Image: try: format = EXTENSION[ext] except KeyError as e: - raise ValueError("unknown file extension: {}".format(ext)) from e + raise ValueError(f"unknown file extension: {ext}") from e if format.upper() not in SAVE: init() @@ -2241,7 +2241,7 @@ class Image: try: channel = self.getbands().index(channel) except ValueError as e: - raise ValueError('The image has no channel "{}"'.format(channel)) from e + raise ValueError(f'The image has no channel "{channel}"') from e return self._new(self.im.getband(channel)) @@ -2462,9 +2462,9 @@ class Image: BOX: "Image.BOX", HAMMING: "Image.HAMMING", LANCZOS: "Image.LANCZOS/Image.ANTIALIAS", - }[resample] + " ({}) cannot be used.".format(resample) + }[resample] + f" ({resample}) cannot be used." else: - message = "Unknown resampling filter ({}).".format(resample) + message = f"Unknown resampling filter ({resample})." filters = [ "{} ({})".format(filter[1], filter[0]) @@ -2758,7 +2758,7 @@ def fromarray(obj, mode=None): else: ndmax = 4 if ndim > ndmax: - raise ValueError("Too many dimensions: %d > %d." % (ndim, ndmax)) + raise ValueError(f"Too many dimensions: {ndim} > {ndmax}.") size = 1 if ndim == 1 else shape[1], shape[0] if strides is not None: @@ -2824,14 +2824,14 @@ def _decompression_bomb_check(size): if pixels > 2 * MAX_IMAGE_PIXELS: raise DecompressionBombError( - "Image size (%d pixels) exceeds limit of %d pixels, " - "could be decompression bomb DOS attack." % (pixels, 2 * MAX_IMAGE_PIXELS) + f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " + "pixels, could be decompression bomb DOS attack." ) if pixels > MAX_IMAGE_PIXELS: warnings.warn( - "Image size (%d pixels) exceeds limit of %d pixels, " - "could be decompression bomb DOS attack." % (pixels, MAX_IMAGE_PIXELS), + f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, " + "could be decompression bomb DOS attack.", DecompressionBombWarning, ) @@ -2860,7 +2860,7 @@ def open(fp, mode="r"): """ if mode != "r": - raise ValueError("bad mode %r" % mode) + raise ValueError(f"bad mode {repr(mode)}") elif isinstance(fp, io.StringIO): raise ValueError( "StringIO cannot be used to open an image. " @@ -3241,13 +3241,13 @@ def _apply_env_variables(env=None): try: var = int(var) * units except ValueError: - warnings.warn("{} is not int".format(var_name)) + warnings.warn(f"{var_name} is not int") continue try: setter(var) except ValueError as e: - warnings.warn("{}: {}".format(var_name, e)) + warnings.warn(f"{var_name}: {e}") _apply_env_variables() @@ -3370,8 +3370,8 @@ class Exif(MutableMapping): if len(data) != size: warnings.warn( "Possibly corrupt EXIF MakerNote data. " - "Expecting to read %d bytes but only got %d." - " Skipping tag %s" % (size, len(data), ifd_tag) + f"Expecting to read {size} bytes but only got " + f"{len(data)}. Skipping tag {ifd_tag}" ) continue diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 1c4ce5a08..f854959a7 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -678,8 +678,7 @@ def createProfile(colorSpace, colorTemp=-1): if colorSpace not in ["LAB", "XYZ", "sRGB"]: raise PyCMSError( - "Color space not supported for on-the-fly profile creation (%s)" - % colorSpace + f"Color space not supported for on-the-fly profile creation ({colorSpace})" ) if colorSpace == "LAB": @@ -687,7 +686,7 @@ def createProfile(colorSpace, colorTemp=-1): colorTemp = float(colorTemp) except (TypeError, ValueError) as e: raise PyCMSError( - 'Color temperature must be numeric, "%s" not valid' % colorTemp + f'Color temperature must be numeric, "{colorTemp}" not valid' ) from e try: @@ -732,7 +731,7 @@ def getProfileName(profile): return (profile.profile.profile_description or "") + "\n" if not manufacturer or len(model) > 30: return model + "\n" - return "{} - {}\n".format(model, manufacturer) + return f"{model} - {manufacturer}\n" except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) from v diff --git a/src/PIL/ImageColor.py b/src/PIL/ImageColor.py index 9cf7a9912..909117449 100644 --- a/src/PIL/ImageColor.py +++ b/src/PIL/ImageColor.py @@ -113,7 +113,7 @@ def getrgb(color): m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) if m: return (int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))) - raise ValueError("unknown color specifier: %r" % color) + raise ValueError(f"unknown color specifier: {repr(color)}") def getcolor(color, mode): diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 648101ee3..bb8737d33 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -61,7 +61,7 @@ def raise_oserror(error): except AttributeError: message = ERRORS.get(error) if not message: - message = "decoder error %d" % error + message = f"decoder error {error}" raise OSError(message + " when reading image file") @@ -201,7 +201,7 @@ class ImageFile(Image.Image): # use mmap, if possible import mmap - with open(self.filename, "r") as fp: + with open(self.filename) as fp: self.map = mmap.mmap( fp.fileno(), 0, access=mmap.ACCESS_READ ) @@ -256,7 +256,7 @@ class ImageFile(Image.Image): else: raise OSError( "image file is truncated " - "(%d bytes not processed)" % len(b) + f"({len(b)} bytes not processed)" ) b = b + s @@ -332,7 +332,7 @@ class StubImageFile(ImageFile): def load(self): loader = self._load() if loader is None: - raise OSError("cannot find loader for this %s file" % self.format) + raise OSError(f"cannot find loader for this {self.format} file") image = loader.load(self) assert image is not None # become the other object (!) @@ -524,7 +524,7 @@ def _save(im, fp, tile, bufsize=0): if s: break if s < 0: - raise OSError("encoder error %d when writing image file" % s) from e + raise OSError(f"encoder error {s} when writing image file") from e e.cleanup() else: # slight speedup: compress to real file object @@ -539,7 +539,7 @@ def _save(im, fp, tile, bufsize=0): else: s = e.encode_to_file(fh, bufsize) if s < 0: - raise OSError("encoder error %d when writing image file" % s) + raise OSError(f"encoder error {s} when writing image file") e.cleanup() if hasattr(fp, "flush"): fp.flush() diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index 18c550c84..c00261e47 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -401,9 +401,8 @@ class Color3DLUT(MultibandFilter): raise ValueError( "The table should have either channels * size**3 float items " "or size**3 items of channels-sized tuples with floats. " - "Table should be: {}x{}x{}x{}. Actual length: {}".format( - channels, size[0], size[1], size[2], len(table) - ) + f"Table should be: {channels}x{size[0]}x{size[1]}x{size[2]}. " + f"Actual length: {len(table)}" ) self.table = table @@ -513,12 +512,12 @@ class Color3DLUT(MultibandFilter): def __repr__(self): r = [ - "{} from {}".format(self.__class__.__name__, self.table.__class__.__name__), + f"{self.__class__.__name__} from {self.table.__class__.__name__}", "size={:d}x{:d}x{:d}".format(*self.size), - "channels={:d}".format(self.channels), + f"channels={self.channels:d}", ] if self.mode: - r.append("target_mode={}".format(self.mode)) + r.append(f"target_mode={self.mode}") return "<{}>".format(" ".join(r)) def filter(self, image): diff --git a/src/PIL/ImageMath.py b/src/PIL/ImageMath.py index 9a2d0b78e..7f9c88e14 100644 --- a/src/PIL/ImageMath.py +++ b/src/PIL/ImageMath.py @@ -41,7 +41,7 @@ class _Operand: elif im1.im.mode in ("I", "F"): return im1.im else: - raise ValueError("unsupported mode: %s" % im1.im.mode) + raise ValueError(f"unsupported mode: {im1.im.mode}") else: # argument was a constant if _isconstant(im1) and self.im.mode in ("1", "L", "I"): @@ -58,7 +58,7 @@ class _Operand: try: op = getattr(_imagingmath, op + "_" + im1.mode) except AttributeError as e: - raise TypeError("bad operand type for '%s'" % op) from e + raise TypeError(f"bad operand type for '{op}'") from e _imagingmath.unop(op, out.im.id, im1.im.id) else: # binary operation @@ -86,7 +86,7 @@ class _Operand: try: op = getattr(_imagingmath, op + "_" + im1.mode) except AttributeError as e: - raise TypeError("bad operand type for '%s'" % op) from e + raise TypeError(f"bad operand type for '{op}'") from e _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id) return _Operand(out) diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index 5dba6176f..d0604112f 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -111,7 +111,7 @@ class ImagePalette: self.dirty = 1 return index else: - raise ValueError("unknown color specifier: %r" % color) + raise ValueError(f"unknown color specifier: {repr(color)}") def save(self, fp): """Save palette to text file. @@ -123,12 +123,12 @@ class ImagePalette: if isinstance(fp, str): fp = open(fp, "w") fp.write("# Palette\n") - fp.write("# Mode: %s\n" % self.mode) + fp.write(f"# Mode: {self.mode}\n") for i in range(256): - fp.write("%d" % i) + fp.write(f"{i}") for j in range(i * len(self.mode), (i + 1) * len(self.mode)): try: - fp.write(" %d" % self.palette[j]) + fp.write(f" {self.palette[j]}") except IndexError: fp.write(" 0") fp.write("\n") diff --git a/src/PIL/ImageQt.py b/src/PIL/ImageQt.py index a15f4ab5e..63cc6ae5a 100644 --- a/src/PIL/ImageQt.py +++ b/src/PIL/ImageQt.py @@ -145,7 +145,7 @@ def _toqclass_helper(im): data = im.tobytes("raw", "BGRA") format = QImage.Format_ARGB32 else: - raise ValueError("unsupported image mode %r" % im.mode) + raise ValueError(f"unsupported image mode {repr(im.mode)}") __data = data or align8to32(im.tobytes(), im.size[0], im.mode) return {"data": __data, "im": im, "format": format, "colortable": colortable} diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index 3ffb4d632..1ada8252c 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -123,9 +123,9 @@ class WindowsViewer(Viewer): def get_command(self, file, **options): return ( - 'start "Pillow" /WAIT "%s" ' + f'start "Pillow" /WAIT "{file}" ' "&& ping -n 2 127.0.0.1 >NUL " - '&& del /f "%s"' % (file, file) + f'&& del /f "{file}"' ) @@ -143,9 +143,7 @@ class MacViewer(Viewer): # on darwin open returns immediately resulting in the temp # file removal while app is opening command = "open -a Preview.app" - command = "({} {}; sleep 20; rm -f {})&".format( - command, quote(file), quote(file) - ) + command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&" return command def show_file(self, file, **options): @@ -153,7 +151,7 @@ class MacViewer(Viewer): fd, path = tempfile.mkstemp() with os.fdopen(fd, "w") as f: f.write(file) - with open(path, "r") as f: + with open(path) as f: subprocess.Popen( ["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"], shell=True, @@ -173,14 +171,14 @@ class UnixViewer(Viewer): def get_command(self, file, **options): command = self.get_command_ex(file, **options)[0] - return "({} {}; rm -f {})&".format(command, quote(file), quote(file)) + return f"({command} {quote(file)}; rm -f {quote(file)})&" def show_file(self, file, **options): """Display given file""" fd, path = tempfile.mkstemp() with os.fdopen(fd, "w") as f: f.write(file) - with open(path, "r") as f: + with open(path) as f: command = self.get_command_ex(file, **options)[0] subprocess.Popen( ["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f @@ -216,7 +214,7 @@ class XVViewer(UnixViewer): # imagemagick's display command instead. command = executable = "xv" if title: - command += " -name %s" % quote(title) + command += f" -name {quote(title)}" return command, executable diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index ee707cffb..e8148ad01 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -41,7 +41,7 @@ def _pilbitmap_check(): if _pilbitmap_ok is None: try: im = Image.new("1", (1, 1)) - tkinter.BitmapImage(data="PIL:%d" % im.im.id) + tkinter.BitmapImage(data=f"PIL:{im.im.id}") _pilbitmap_ok = 1 except tkinter.TclError: _pilbitmap_ok = 0 @@ -229,7 +229,7 @@ class BitmapImage: if _pilbitmap_check(): # fast way (requires the pilbitmap booster patch) image.load() - kw["data"] = "PIL:%d" % image.im.id + kw["data"] = f"PIL:{image.im.id}" self.__im = image # must keep a reference else: # slow but safe way diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index f18eedb20..dfd96d2df 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -195,7 +195,7 @@ def SOF(self, marker): self.bits = i8(s[0]) if self.bits != 8: - raise SyntaxError("cannot handle %d-bit layers" % self.bits) + raise SyntaxError(f"cannot handle {self.bits}-bit layers") self.layers = i8(s[5]) if self.layers == 1: @@ -205,7 +205,7 @@ def SOF(self, marker): elif self.layers == 4: self.mode = "CMYK" else: - raise SyntaxError("cannot handle %d-layer images" % self.layers) + raise SyntaxError(f"cannot handle {self.layers}-layer images") if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]: self.info["progressive"] = self.info["progression"] = 1 @@ -518,7 +518,7 @@ def _getmp(self): rawmpentries = mp[0xB002] for entrynum in range(0, quant): unpackedentry = struct.unpack_from( - "{}LLLHH".format(endianness), rawmpentries, entrynum * 16 + f"{endianness}LLLHH", rawmpentries, entrynum * 16 ) labels = ("Attribute", "Size", "DataOffset", "EntryNo1", "EntryNo2") mpentry = dict(zip(labels, unpackedentry)) @@ -613,7 +613,7 @@ def _save(im, fp, filename): try: rawmode = RAWMODE[im.mode] except KeyError as e: - raise OSError("cannot write mode %s as JPEG" % im.mode) from e + raise OSError(f"cannot write mode {im.mode} as JPEG") from e info = im.encoderinfo diff --git a/src/PIL/MspImagePlugin.py b/src/PIL/MspImagePlugin.py index ca9572187..03add47f4 100644 --- a/src/PIL/MspImagePlugin.py +++ b/src/PIL/MspImagePlugin.py @@ -114,7 +114,7 @@ class MspDecoder(ImageFile.PyDecoder): try: self.fd.seek(32) rowmap = struct.unpack_from( - "<%dH" % (self.state.ysize), self.fd.read(self.state.ysize * 2) + f"<{self.state.ysize}H", self.fd.read(self.state.ysize * 2) ) except struct.error as e: raise OSError("Truncated MSP file in row map") from e @@ -143,7 +143,7 @@ class MspDecoder(ImageFile.PyDecoder): idx += runcount except struct.error as e: - raise OSError("Corrupted MSP file in row %d" % x) from e + raise OSError(f"Corrupted MSP file in row {x}") from e self.set_as_raw(img.getvalue(), ("1", 0, 1)) @@ -160,7 +160,7 @@ Image.register_decoder("MSP", MspDecoder) def _save(im, fp, filename): if im.mode != "1": - raise OSError("cannot write mode %s as MSP" % im.mode) + raise OSError(f"cannot write mode {im.mode} as MSP") # create MSP header header = [0] * 16 diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index 3cfcbaf28..3d96b481b 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -71,10 +71,10 @@ class PSDraw: """ if font not in self.isofont: # reencode font - self._fp_write("/PSDraw-{} ISOLatin1Encoding /{} E\n".format(font, font)) + self._fp_write(f"/PSDraw-{font} ISOLatin1Encoding /{font} E\n") self.isofont[font] = 1 # rough - self._fp_write("/F0 %d /PSDraw-%s F\n" % (size, font)) + self._fp_write(f"/F0 {size} /PSDraw-{font} F\n") def line(self, xy0, xy1): """ @@ -82,8 +82,7 @@ class PSDraw: PostScript point coordinates (72 points per inch, (0, 0) is the lower left corner of the page). """ - xy = xy0 + xy1 - self._fp_write("%d %d %d %d Vl\n" % xy) + self._fp_write("%d %d %d %d Vl\n" % (*xy0, *xy1)) def rectangle(self, box): """ @@ -107,8 +106,7 @@ class PSDraw: """ text = "\\(".join(text.split("(")) text = "\\)".join(text.split(")")) - xy = xy + (text,) - self._fp_write("%d %d M (%s) S\n" % xy) + self._fp_write(f"{xy[0]} {xy[1]} M ({text}) S\n") def image(self, box, im, dpi=None): """Draw a PIL image, centered in the given box.""" @@ -132,12 +130,12 @@ class PSDraw: y = ymax dx = (xmax - x) / 2 + box[0] dy = (ymax - y) / 2 + box[1] - self._fp_write("gsave\n{:f} {:f} translate\n".format(dx, dy)) + self._fp_write(f"gsave\n{dx:f} {dy:f} translate\n") if (x, y) != im.size: # EpsImagePlugin._save prints the image at (0,0,xsize,ysize) sx = x / im.size[0] sy = y / im.size[1] - self._fp_write("{:f} {:f} scale\n".format(sx, sy)) + self._fp_write(f"{sx:f} {sy:f} scale\n") EpsImagePlugin._save(im, self.fp, None, 0) self._fp_write("\ngrestore\n") diff --git a/src/PIL/PalmImagePlugin.py b/src/PIL/PalmImagePlugin.py index 9fc55d795..553fe7b77 100644 --- a/src/PIL/PalmImagePlugin.py +++ b/src/PIL/PalmImagePlugin.py @@ -137,7 +137,7 @@ def _save(im, fp, filename): bpp = im.info["bpp"] im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval)) else: - raise OSError("cannot write mode %s as Palm" % im.mode) + raise OSError(f"cannot write mode {im.mode} as Palm") # we ignore the palette here im.mode = "P" @@ -153,7 +153,7 @@ def _save(im, fp, filename): else: - raise OSError("cannot write mode %s as Palm" % im.mode) + raise OSError(f"cannot write mode {im.mode} as Palm") # # make sure image data is available diff --git a/src/PIL/PcxImagePlugin.py b/src/PIL/PcxImagePlugin.py index f7ae3bf70..0306237dc 100644 --- a/src/PIL/PcxImagePlugin.py +++ b/src/PIL/PcxImagePlugin.py @@ -132,7 +132,7 @@ def _save(im, fp, filename): try: version, bits, planes, rawmode = SAVE[im.mode] except KeyError as e: - raise ValueError("Cannot save %s images as PCX" % im.mode) from e + raise ValueError(f"Cannot save {im.mode} images as PCX") from e # bytes per plane stride = (im.size[0] * bits + 7) // 8 diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 47500baf7..9583f704a 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -77,7 +77,7 @@ def _save(im, fp, filename, save_all=False): existing_pdf.start_writing() existing_pdf.write_header() - existing_pdf.write_comment("created by Pillow {} PDF driver".format(__version__)) + existing_pdf.write_comment(f"created by Pillow {__version__} PDF driver") # # pages @@ -129,7 +129,7 @@ def _save(im, fp, filename, save_all=False): bits = 1 elif im.mode == "L": filter = "DCTDecode" - # params = "<< /Predictor 15 /Columns %d >>" % (width-2) + # params = f"<< /Predictor 15 /Columns {width-2} >>" colorspace = PdfParser.PdfName("DeviceGray") procset = "ImageB" # grayscale elif im.mode == "P": @@ -151,7 +151,7 @@ def _save(im, fp, filename, save_all=False): colorspace = PdfParser.PdfName("DeviceCMYK") procset = "ImageC" # color images else: - raise ValueError("cannot save mode %s" % im.mode) + raise ValueError(f"cannot save mode {im.mode}") # # image @@ -173,7 +173,7 @@ def _save(im, fp, filename, save_all=False): elif filter == "RunLengthDecode": ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)]) else: - raise ValueError("unsupported PDF filter (%s)" % filter) + raise ValueError(f"unsupported PDF filter ({filter})") # # Get image characteristics diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 3c343c5e8..975905f96 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -183,8 +183,8 @@ class XrefTable: this_deleted_object_id = deleted_keys.pop(0) check_format_condition( object_id == this_deleted_object_id, - "expected the next deleted object ID to be %s, instead found %s" - % (object_id, this_deleted_object_id), + f"expected the next deleted object ID to be {object_id}, " + f"instead found {this_deleted_object_id}", ) try: next_in_linked_list = deleted_keys[0] @@ -218,7 +218,7 @@ class PdfName: return hash(self.name) def __repr__(self): - return "PdfName(%s)" % repr(self.name) + return f"PdfName({repr(self.name)})" @classmethod def from_pdf_stream(cls, data): @@ -315,7 +315,7 @@ class PdfStream: return zlib.decompress(self.buf, bufsize=int(expected_length)) else: raise NotImplementedError( - "stream filter %s unknown/unsupported" % repr(self.dictionary.Filter) + f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported" ) @@ -423,7 +423,7 @@ class PdfParser: self.f.write(b"%PDF-1.4\n") def write_comment(self, s): - self.f.write(("% {}\n".format(s)).encode("utf-8")) + self.f.write(f"% {s}\n".encode("utf-8")) def write_catalog(self): self.del_root() @@ -966,9 +966,8 @@ class PdfParser: offset, generation = self.xref_table[ref[0]] check_format_condition( generation == ref[1], - "expected to find generation %s for object ID %s in xref table, " - "instead found generation %s at offset %s" - % (ref[1], ref[0], generation, offset), + f"expected to find generation {ref[1]} for object ID {ref[0]} in xref " + f"table, instead found generation {generation} at offset {offset}", ) value = self.get_value( self.buf, diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 9d048b211..9900a5e12 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -159,7 +159,7 @@ class ChunkStream: if not is_cid(cid): if not ImageFile.LOAD_TRUNCATED_IMAGES: - raise SyntaxError("broken PNG file (chunk %s)" % repr(cid)) + raise SyntaxError(f"broken PNG file (chunk {repr(cid)})") return cid, pos, length @@ -196,10 +196,12 @@ class ChunkStream: crc1 = _crc32(data, _crc32(cid)) crc2 = i32(self.fp.read(4)) if crc1 != crc2: - raise SyntaxError("broken PNG file (bad header checksum in %r)" % cid) + raise SyntaxError( + f"broken PNG file (bad header checksum in {repr(cid)})" + ) except struct.error as e: raise SyntaxError( - "broken PNG file (incomplete checksum in %r)" % cid + f"broken PNG file (incomplete checksum in {repr(cid)})" ) from e def crc_skip(self, cid, data): @@ -351,8 +353,8 @@ class PngStream(ChunkStream): self.text_memory += chunklen if self.text_memory > MAX_TEXT_MEMORY: raise ValueError( - "Too much memory used in text chunks: %s>MAX_TEXT_MEMORY" - % self.text_memory + "Too much memory used in text chunks: " + f"{self.text_memory}>MAX_TEXT_MEMORY" ) def save_rewind(self): @@ -381,9 +383,7 @@ class PngStream(ChunkStream): logger.debug("Compression method %s", i8(s[i])) comp_method = i8(s[i]) if comp_method != 0: - raise SyntaxError( - "Unknown compression method %s in iCCP chunk" % comp_method - ) + raise SyntaxError(f"Unknown compression method {comp_method} in iCCP chunk") try: icc_profile = _safe_zlib_decompress(s[i + 2 :]) except ValueError: @@ -530,9 +530,7 @@ class PngStream(ChunkStream): else: comp_method = 0 if comp_method != 0: - raise SyntaxError( - "Unknown compression method %s in zTXt chunk" % comp_method - ) + raise SyntaxError(f"Unknown compression method {comp_method} in zTXt chunk") try: v = _safe_zlib_decompress(v[1:]) except ValueError: @@ -794,7 +792,7 @@ class PngImageFile(ImageFile.ImageFile): return else: if frame != self.__frame + 1: - raise ValueError("cannot seek to frame %d" % frame) + raise ValueError(f"cannot seek to frame {frame}") # ensure previous frame was loaded self.load() @@ -1186,7 +1184,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): else: bits = 8 if bits != 8: - mode = "%s;%d" % (mode, bits) + mode = f"{mode};{bits}" # encoder options im.encoderconfig = ( @@ -1200,7 +1198,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): try: rawmode, mode = _OUTMODES[mode] except KeyError as e: - raise OSError("cannot write mode %s as PNG" % mode) from e + raise OSError(f"cannot write mode {mode} as PNG") from e # # write minimal PNG file diff --git a/src/PIL/PpmImagePlugin.py b/src/PIL/PpmImagePlugin.py index 35a77bafb..abf4d651d 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -104,7 +104,7 @@ class PpmImageFile(ImageFile.ImageFile): # maxgrey if s > 255: if not mode == "L": - raise ValueError("Too many colors for band: %s" % s) + raise ValueError(f"Too many colors for band: {s}") if s < 2 ** 16: self.mode = "I" rawmode = "I;16B" @@ -135,7 +135,7 @@ def _save(im, fp, filename): elif im.mode == "RGBA": rawmode, head = "RGB", b"P6" else: - raise OSError("cannot write mode %s as PPM" % im.mode) + raise OSError(f"cannot write mode {im.mode} as PPM") fp.write(head + ("\n%d %d\n" % im.size).encode("ascii")) if head == b"P6": fp.write(b"255\n") diff --git a/src/PIL/SgiImagePlugin.py b/src/PIL/SgiImagePlugin.py index ec9855e77..612ebe5a8 100644 --- a/src/PIL/SgiImagePlugin.py +++ b/src/PIL/SgiImagePlugin.py @@ -158,9 +158,7 @@ def _save(im, fp, filename): # assert we've got the right number of bands. if len(im.getbands()) != z: raise ValueError( - "incorrect number of bands in SGI write: {} vs {}".format( - z, len(im.getbands()) - ) + f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}" ) # Minimum Byte value diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index 56aac2987..819f2ed0a 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -213,7 +213,7 @@ def loadImageSeries(filelist=None): imglist = [] for img in filelist: if not os.path.exists(img): - print("unable to find %s" % img) + print(f"unable to find {img}") continue try: with Image.open(img) as im: @@ -318,7 +318,7 @@ if __name__ == "__main__": # perform some image operation im = im.transpose(Image.FLIP_LEFT_RIGHT) print( - "saving a flipped version of %s as %s " - % (os.path.basename(filename), outfile) + f"saving a flipped version of {os.path.basename(filename)} " + f"as {outfile} " ) im.save(outfile, SpiderImageFile.format) diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index 566f0ac18..d3f780d4d 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -168,7 +168,7 @@ def _save(im, fp, filename): try: rawmode, bits, colormaptype, imagetype = SAVE[im.mode] except KeyError as e: - raise OSError("cannot write mode %s as TGA" % im.mode) from e + raise OSError(f"cannot write mode {im.mode} as TGA") from e if "rle" in im.encoderinfo: rle = im.encoderinfo["rle"] diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 6a772e48b..453cc8660 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -464,7 +464,7 @@ class ImageFileDirectory_v2(MutableMapping): :param prefix: Override the endianness of the file. """ if ifh[:4] not in PREFIXES: - raise SyntaxError("not a TIFF file (header %r not valid)" % ifh) + raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)") self._prefix = prefix if prefix is not None else ifh[:2] if self._prefix == MM: self._endian = ">" @@ -592,8 +592,8 @@ class ImageFileDirectory_v2(MutableMapping): except ValueError: # We've got a builtin tag with 1 expected entry warnings.warn( - "Metadata Warning, tag %s had too many entries: %s, expected 1" - % (tag, len(values)) + f"Metadata Warning, tag {tag} had too many entries: " + f"{len(values)}, expected 1" ) dest[tag] = values[0] @@ -728,7 +728,7 @@ class ImageFileDirectory_v2(MutableMapping): if len(ret) != size: raise OSError( "Corrupt EXIF data. " - + "Expecting to read %d bytes but only got %d. " % (size, len(ret)) + f"Expecting to read {size} bytes but only got {len(ret)}. " ) return ret @@ -743,18 +743,18 @@ class ImageFileDirectory_v2(MutableMapping): tagname = TiffTags.lookup(tag).name typname = TYPES.get(typ, "unknown") - msg = "tag: %s (%d) - type: %s (%d)" % (tagname, tag, typname, typ) + msg = f"tag: {tagname} ({tag}) - type: {typname} ({typ})" try: unit_size, handler = self._load_dispatch[typ] except KeyError: - logger.debug(msg + " - unsupported type {}".format(typ)) + logger.debug(msg + f" - unsupported type {typ}") continue # ignore unsupported type size = count * unit_size if size > 4: here = fp.tell() (offset,) = self._unpack("L", data) - msg += " Tag Location: {} - Data Location: {}".format(here, offset) + msg += f" Tag Location: {here} - Data Location: {offset}" fp.seek(offset) data = ImageFile._safe_read(fp, size) fp.seek(here) @@ -764,8 +764,8 @@ class ImageFileDirectory_v2(MutableMapping): if len(data) != size: warnings.warn( "Possibly corrupt EXIF data. " - "Expecting to read %d bytes but only got %d." - " Skipping tag %s" % (size, len(data), tag) + f"Expecting to read {size} bytes but only got {len(data)}." + f" Skipping tag {tag}" ) logger.debug(msg) continue @@ -801,13 +801,13 @@ class ImageFileDirectory_v2(MutableMapping): if tag == STRIPOFFSETS: stripoffsets = len(entries) typ = self.tagtype.get(tag) - logger.debug("Tag {}, Type: {}, Value: {}".format(tag, typ, value)) + logger.debug(f"Tag {tag}, Type: {typ}, Value: {value}") values = value if isinstance(value, tuple) else (value,) data = self._write_dispatch[typ](self, *values) tagname = TiffTags.lookup(tag).name typname = TYPES.get(typ, "unknown") - msg = "save: %s (%d) - type: %s (%d)" % (tagname, tag, typname, typ) + msg = f"save: {tagname} ({tag}) - type: {typname} ({typ})" msg += " - value: " + ( "" % len(data) if len(data) >= 16 else str(values) ) @@ -835,9 +835,7 @@ class ImageFileDirectory_v2(MutableMapping): # pass 2: write entries to file for tag, typ, count, value, data in entries: - logger.debug( - "{} {} {} {} {}".format(tag, typ, count, repr(value), repr(data)) - ) + logger.debug(f"{tag} {typ} {count} {repr(value)} {repr(data)}") result += self._pack("HHL4s", tag, typ, count, value) # -- overwrite here for multi-page -- @@ -1002,8 +1000,8 @@ class TiffImageFile(ImageFile.ImageFile): self._n_frames = None logger.debug("*** TiffImageFile._open ***") - logger.debug("- __first: {}".format(self.__first)) - logger.debug("- ifh: {!r}".format(ifh)) # Use !r to avoid str(bytes) + logger.debug(f"- __first: {self.__first}") + logger.debug(f"- ifh: {repr(ifh)}") # Use repr to avoid str(bytes) # and load the first frame self._seek(0) @@ -1035,8 +1033,8 @@ class TiffImageFile(ImageFile.ImageFile): if not self.__next: raise EOFError("no more images in TIFF file") logger.debug( - "Seeking to frame %s, on frame %s, __next %s, location: %s" - % (frame, self.__frame, self.__next, self.fp.tell()) + f"Seeking to frame {frame}, on frame {self.__frame}, " + f"__next {self.__next}, location: {self.fp.tell()}" ) # reset buffered io handle in case fp # was passed to libtiff, invalidating the buffer @@ -1193,18 +1191,18 @@ class TiffImageFile(ImageFile.ImageFile): fillorder = self.tag_v2.get(FILLORDER, 1) logger.debug("*** Summary ***") - logger.debug("- compression: {}".format(self._compression)) - logger.debug("- photometric_interpretation: {}".format(photo)) - logger.debug("- planar_configuration: {}".format(self._planar_configuration)) - logger.debug("- fill_order: {}".format(fillorder)) - logger.debug("- YCbCr subsampling: {}".format(self.tag.get(530))) + logger.debug(f"- compression: {self._compression}") + logger.debug(f"- photometric_interpretation: {photo}") + logger.debug(f"- planar_configuration: {self._planar_configuration}") + logger.debug(f"- fill_order: {fillorder}") + logger.debug(f"- YCbCr subsampling: {self.tag.get(530)}") # size xsize = int(self.tag_v2.get(IMAGEWIDTH)) ysize = int(self.tag_v2.get(IMAGELENGTH)) self._size = xsize, ysize - logger.debug("- size: {}".format(self.size)) + logger.debug(f"- size: {self.size}") sampleFormat = self.tag_v2.get(SAMPLEFORMAT, (1,)) if len(sampleFormat) > 1 and max(sampleFormat) == min(sampleFormat) == 1: @@ -1238,15 +1236,15 @@ class TiffImageFile(ImageFile.ImageFile): bps_tuple, extra_tuple, ) - logger.debug("format key: {}".format(key)) + logger.debug(f"format key: {key}") try: self.mode, rawmode = OPEN_INFO[key] except KeyError as e: logger.debug("- unsupported format") raise SyntaxError("unknown pixel mode") from e - logger.debug("- raw mode: {}".format(rawmode)) - logger.debug("- pil mode: {}".format(self.mode)) + logger.debug(f"- raw mode: {rawmode}") + logger.debug(f"- pil mode: {self.mode}") self.info["compression"] = self._compression @@ -1287,7 +1285,7 @@ class TiffImageFile(ImageFile.ImageFile): if fillorder == 2: # Replace fillorder with fillorder=1 key = key[:3] + (1,) + key[4:] - logger.debug("format key: {}".format(key)) + logger.debug(f"format key: {key}") # this should always work, since all the # fillorder==2 modes have a corresponding # fillorder=1 mode @@ -1411,7 +1409,7 @@ def _save(im, fp, filename): try: rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode] except KeyError as e: - raise OSError("cannot write mode %s as TIFF" % im.mode) from e + raise OSError(f"cannot write mode {im.mode} as TIFF") from e ifd = ImageFileDirectory_v2(prefix=prefix) @@ -1608,7 +1606,7 @@ def _save(im, fp, filename): if s: break if s < 0: - raise OSError("encoder error %d when writing image file" % s) + raise OSError(f"encoder error {s} when writing image file") else: offset = ifd.save(fp) @@ -1774,29 +1772,29 @@ class AppendingTiffWriter: self.f.seek(-2, os.SEEK_CUR) bytesWritten = self.f.write(struct.pack(self.longFmt, value)) if bytesWritten is not None and bytesWritten != 4: - raise RuntimeError("wrote only %u bytes but wanted 4" % bytesWritten) + raise RuntimeError(f"wrote only {bytesWritten} bytes but wanted 4") def rewriteLastShort(self, value): self.f.seek(-2, os.SEEK_CUR) bytesWritten = self.f.write(struct.pack(self.shortFmt, value)) if bytesWritten is not None and bytesWritten != 2: - raise RuntimeError("wrote only %u bytes but wanted 2" % bytesWritten) + raise RuntimeError(f"wrote only {bytesWritten} bytes but wanted 2") def rewriteLastLong(self, value): self.f.seek(-4, os.SEEK_CUR) bytesWritten = self.f.write(struct.pack(self.longFmt, value)) if bytesWritten is not None and bytesWritten != 4: - raise RuntimeError("wrote only %u bytes but wanted 4" % bytesWritten) + raise RuntimeError(f"wrote only {bytesWritten} bytes but wanted 4") def writeShort(self, value): bytesWritten = self.f.write(struct.pack(self.shortFmt, value)) if bytesWritten is not None and bytesWritten != 2: - raise RuntimeError("wrote only %u bytes but wanted 2" % bytesWritten) + raise RuntimeError(f"wrote only {bytesWritten} bytes but wanted 2") def writeLong(self, value): bytesWritten = self.f.write(struct.pack(self.longFmt, value)) if bytesWritten is not None and bytesWritten != 4: - raise RuntimeError("wrote only %u bytes but wanted 4" % bytesWritten) + raise RuntimeError(f"wrote only {bytesWritten} bytes but wanted 4") def close(self): self.finalize() diff --git a/src/PIL/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index ead9722c8..644cfb39b 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -69,15 +69,15 @@ class XbmImageFile(ImageFile.ImageFile): def _save(im, fp, filename): if im.mode != "1": - raise OSError("cannot write mode %s as XBM" % im.mode) + raise OSError(f"cannot write mode {im.mode} as XBM") - fp.write(("#define im_width %d\n" % im.size[0]).encode("ascii")) - fp.write(("#define im_height %d\n" % im.size[1]).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")) hotspot = im.encoderinfo.get("hotspot") if hotspot: - fp.write(("#define im_x_hot %d\n" % hotspot[0]).encode("ascii")) - fp.write(("#define im_y_hot %d\n" % hotspot[1]).encode("ascii")) + fp.write(f"#define im_x_hot {hotspot[0]}\n".encode("ascii")) + fp.write(f"#define im_y_hot {hotspot[1]}\n".encode("ascii")) fp.write(b"static char im_bits[] = {\n") diff --git a/src/PIL/__init__.py b/src/PIL/__init__.py index d225ed134..d4f5ea76a 100644 --- a/src/PIL/__init__.py +++ b/src/PIL/__init__.py @@ -39,7 +39,7 @@ if sys.version_info >= (3, 7): if name == "PILLOW_VERSION": _raise_version_warning() return __version__ - raise AttributeError("module '{}' has no attribute '{}'".format(__name__, name)) + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") else: diff --git a/src/PIL/features.py b/src/PIL/features.py index 66b093350..d2e861372 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -25,7 +25,7 @@ def check_module(feature): :raises ValueError: If the module is not defined in this version of Pillow. """ if not (feature in modules): - raise ValueError("Unknown module %s" % feature) + raise ValueError(f"Unknown module {feature}") module, ver = modules[feature] @@ -78,7 +78,7 @@ def check_codec(feature): :raises ValueError: If the codec is not defined in this version of Pillow. """ if feature not in codecs: - raise ValueError("Unknown codec %s" % feature) + raise ValueError(f"Unknown codec {feature}") codec, lib = codecs[feature] @@ -133,7 +133,7 @@ def check_feature(feature): :raises ValueError: If the feature is not defined in this version of Pillow. """ if feature not in features: - raise ValueError("Unknown feature %s" % feature) + raise ValueError(f"Unknown feature {feature}") module, flag, ver = features[feature] @@ -182,7 +182,7 @@ def check(feature): return check_codec(feature) if feature in features: return check_feature(feature) - warnings.warn("Unknown feature '%s'." % feature, stacklevel=2) + warnings.warn(f"Unknown feature '{feature}'.", stacklevel=2) return False @@ -230,19 +230,17 @@ def pilinfo(out=None, supported_formats=True): Image.init() print("-" * 68, file=out) - print("Pillow {}".format(PIL.__version__), file=out) + print(f"Pillow {PIL.__version__}", file=out) py_version = sys.version.splitlines() - print("Python {}".format(py_version[0].strip()), file=out) + print(f"Python {py_version[0].strip()}", file=out) for py_version in py_version[1:]: - print(" {}".format(py_version.strip()), file=out) + print(f" {py_version.strip()}", file=out) print("-" * 68, file=out) print( - "Python modules loaded from {}".format(os.path.dirname(Image.__file__)), - file=out, + f"Python modules loaded from {os.path.dirname(Image.__file__)}", file=out, ) print( - "Binary modules loaded from {}".format(os.path.dirname(Image.core.__file__)), - file=out, + f"Binary modules loaded from {os.path.dirname(Image.core.__file__)}", file=out, ) print("-" * 68, file=out) @@ -283,9 +281,9 @@ def pilinfo(out=None, supported_formats=True): extensions[i].append(ext) for i in sorted(Image.ID): - line = "{}".format(i) + line = f"{i}" if i in Image.MIME: - line = "{} {}".format(line, Image.MIME[i]) + line = f"{line} {Image.MIME[i]}" print(line, file=out) if i in extensions: diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index 7edc7df5b..ec292b14d 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -417,7 +417,7 @@ def build_dep(name): for patch_file, patch_list in dep.get("patch", {}).items(): patch_file = os.path.join(build_dir, dir, patch_file.format(**prefs)) - with open(patch_file, "r") as f: + with open(patch_file) as f: text = f.read() for patch_from, patch_to in patch_list.items(): text = text.replace(patch_from.format(**prefs), patch_to.format(**prefs))