mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-01 00:17:27 +03:00 
			
		
		
		
	Merge pull request #4794 from hugovk/rm-3.5
This commit is contained in:
		
						commit
						5ce2fac3d6
					
				|  | @ -3,7 +3,7 @@ repos: | ||||||
|     rev: e66be67b9b6811913470f70c28b4d50f94d05b22  # frozen: 20.8b1 |     rev: e66be67b9b6811913470f70c28b4d50f94d05b22  # frozen: 20.8b1 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: black |       - id: black | ||||||
|         args: ["--target-version", "py35"] |         args: ["--target-version", "py36"] | ||||||
|         # Only .py files, until https://github.com/psf/black/issues/402 resolved |         # Only .py files, until https://github.com/psf/black/issues/402 resolved | ||||||
|         files: \.py$ |         files: \.py$ | ||||||
|         types: [] |         types: [] | ||||||
|  |  | ||||||
|  | @ -28,15 +28,17 @@ def timer(func, label, *args): | ||||||
|         func(*args) |         func(*args) | ||||||
|         if time.time() - starttime > 10: |         if time.time() - starttime > 10: | ||||||
|             print( |             print( | ||||||
|                 "%s: breaking at %s iterations, %.6f per iteration" |                 "{}: breaking at {} iterations, {:.6f} per iteration".format( | ||||||
|                 % (label, x + 1, (time.time() - starttime) / (x + 1.0)) |                     label, x + 1, (time.time() - starttime) / (x + 1.0) | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|             break |             break | ||||||
|     if x == iterations - 1: |     if x == iterations - 1: | ||||||
|         endtime = time.time() |         endtime = time.time() | ||||||
|         print( |         print( | ||||||
|             "%s: %.4f s  %.6f per iteration" |             "{}: {:.4f} s  {:.6f} per iteration".format( | ||||||
|             % (label, endtime - starttime, (endtime - starttime) / (x + 1.0)) |                 label, endtime - starttime, (endtime - starttime) / (x + 1.0) | ||||||
|  |             ) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ def _test_leak(min_iterations, max_iterations, fn, *args, **kwargs): | ||||||
|         if i < min_iterations: |         if i < min_iterations: | ||||||
|             mem_limit = mem + 1 |             mem_limit = mem + 1 | ||||||
|             continue |             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 |         assert mem <= mem_limit, msg | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,8 +42,8 @@ def test_dos_total_memory(): | ||||||
|     info = PngImagePlugin.PngInfo() |     info = PngImagePlugin.PngInfo() | ||||||
| 
 | 
 | ||||||
|     for x in range(64): |     for x in range(64): | ||||||
|         info.add_text("t%s" % x, compressed_data, zip=True) |         info.add_text(f"t{x}", compressed_data, zip=True) | ||||||
|         info.add_itxt("i%s" % x, compressed_data, zip=True) |         info.add_itxt(f"i{x}", compressed_data, zip=True) | ||||||
| 
 | 
 | ||||||
|     b = BytesIO() |     b = BytesIO() | ||||||
|     im.save(b, "PNG", pnginfo=info) |     im.save(b, "PNG", pnginfo=info) | ||||||
|  |  | ||||||
|  | @ -9,4 +9,4 @@ def pytest_report_header(config): | ||||||
|             features.pilinfo(out=out, supported_formats=False) |             features.pilinfo(out=out, supported_formats=False) | ||||||
|             return out.getvalue() |             return out.getvalue() | ||||||
|     except Exception as e: |     except Exception as e: | ||||||
|         return "pytest_report_header failed: %s" % e |         return f"pytest_report_header failed: {e}" | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ if __name__ == "__main__": | ||||||
|     # create font data chunk for embedding |     # create font data chunk for embedding | ||||||
|     font = "Tests/images/courB08" |     font = "Tests/images/courB08" | ||||||
|     print("    f._load_pilfont_data(") |     print("    f._load_pilfont_data(") | ||||||
|     print("         # %s" % os.path.basename(font)) |     print(f"         # {os.path.basename(font)}") | ||||||
|     print("         BytesIO(base64.decodestring(b'''") |     print("         BytesIO(base64.decodestring(b'''") | ||||||
|     with open(font + ".pil", "rb") as fp: |     with open(font + ".pil", "rb") as fp: | ||||||
|         print(base64.b64encode(fp.read()).decode()) |         print(base64.b64encode(fp.read()).decode()) | ||||||
|  |  | ||||||
|  | @ -68,37 +68,31 @@ def convert_to_comparable(a, b): | ||||||
| 
 | 
 | ||||||
| def assert_deep_equal(a, b, msg=None): | def assert_deep_equal(a, b, msg=None): | ||||||
|     try: |     try: | ||||||
|         assert len(a) == len(b), msg or "got length {}, expected {}".format( |         assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}" | ||||||
|             len(a), len(b) |  | ||||||
|         ) |  | ||||||
|     except Exception: |     except Exception: | ||||||
|         assert a == b, msg |         assert a == b, msg | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def assert_image(im, mode, size, msg=None): | def assert_image(im, mode, size, msg=None): | ||||||
|     if mode is not None: |     if mode is not None: | ||||||
|         assert im.mode == mode, msg or "got mode {!r}, expected {!r}".format( |         assert im.mode == mode, ( | ||||||
|             im.mode, mode |             msg or f"got mode {repr(im.mode)}, expected {repr(mode)}" | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     if size is not None: |     if size is not None: | ||||||
|         assert im.size == size, msg or "got size {!r}, expected {!r}".format( |         assert im.size == size, ( | ||||||
|             im.size, size |             msg or f"got size {repr(im.size)}, expected {repr(size)}" | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def assert_image_equal(a, b, msg=None): | def assert_image_equal(a, b, msg=None): | ||||||
|     assert a.mode == b.mode, msg or "got mode {!r}, expected {!r}".format( |     assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}" | ||||||
|         a.mode, b.mode |     assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}" | ||||||
|     ) |  | ||||||
|     assert a.size == b.size, msg or "got size {!r}, expected {!r}".format( |  | ||||||
|         a.size, b.size |  | ||||||
|     ) |  | ||||||
|     if a.tobytes() != b.tobytes(): |     if a.tobytes() != b.tobytes(): | ||||||
|         if HAS_UPLOADER: |         if HAS_UPLOADER: | ||||||
|             try: |             try: | ||||||
|                 url = test_image_results.upload(a, b) |                 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: |             except Exception: | ||||||
|                 pass |                 pass | ||||||
| 
 | 
 | ||||||
|  | @ -113,12 +107,8 @@ def assert_image_equal_tofile(a, filename, msg=None, mode=None): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def assert_image_similar(a, b, epsilon, msg=None): | def assert_image_similar(a, b, epsilon, msg=None): | ||||||
|     assert a.mode == b.mode, msg or "got mode {!r}, expected {!r}".format( |     assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}" | ||||||
|         a.mode, b.mode |     assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}" | ||||||
|     ) |  | ||||||
|     assert a.size == b.size, msg or "got size {!r}, expected {!r}".format( |  | ||||||
|         a.size, b.size |  | ||||||
|     ) |  | ||||||
| 
 | 
 | ||||||
|     a, b = convert_to_comparable(a, b) |     a, b = convert_to_comparable(a, b) | ||||||
| 
 | 
 | ||||||
|  | @ -130,13 +120,14 @@ def assert_image_similar(a, b, epsilon, msg=None): | ||||||
|     ave_diff = diff / (a.size[0] * a.size[1]) |     ave_diff = diff / (a.size[0] * a.size[1]) | ||||||
|     try: |     try: | ||||||
|         assert epsilon >= ave_diff, ( |         assert epsilon >= ave_diff, ( | ||||||
|             msg or "" |             (msg or "") | ||||||
|         ) + " average pixel value difference %.4f > epsilon %.4f" % (ave_diff, epsilon) |             + f" average pixel value difference {ave_diff:.4f} > epsilon {epsilon:.4f}" | ||||||
|  |         ) | ||||||
|     except Exception as e: |     except Exception as e: | ||||||
|         if HAS_UPLOADER: |         if HAS_UPLOADER: | ||||||
|             try: |             try: | ||||||
|                 url = test_image_results.upload(a, b) |                 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: |             except Exception: | ||||||
|                 pass |                 pass | ||||||
|         raise e |         raise e | ||||||
|  | @ -167,7 +158,7 @@ def assert_tuple_approx_equal(actuals, targets, threshold, msg): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def skip_unless_feature(feature): | 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) |     return pytest.mark.skipif(not features.check(feature), reason=reason) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -205,7 +196,7 @@ class PillowLeakTestCase: | ||||||
|         for cycle in range(self.iterations): |         for cycle in range(self.iterations): | ||||||
|             core() |             core() | ||||||
|             mem = self._get_mem_usage() - start_mem |             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 |             assert mem < self.mem_limit, msg | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ def test_questionable(): | ||||||
|             with Image.open(f) as im: |             with Image.open(f) as im: | ||||||
|                 im.load() |                 im.load() | ||||||
|             if os.path.basename(f) not in supported: |             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: |         except Exception:  # as msg: | ||||||
|             if os.path.basename(f) in supported: |             if os.path.basename(f) in supported: | ||||||
|                 raise |                 raise | ||||||
|  | @ -85,7 +85,7 @@ def test_good(): | ||||||
|         if name in file_map: |         if name in file_map: | ||||||
|             return os.path.join(base, "html", file_map[name]) |             return os.path.join(base, "html", file_map[name]) | ||||||
|         name = os.path.splitext(name)[0] |         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"): |     for f in get_files("g"): | ||||||
|         try: |         try: | ||||||
|  | @ -108,4 +108,4 @@ def test_good(): | ||||||
|                 os.path.join(base, "g", "pal8rle.bmp"), |                 os.path.join(base, "g", "pal8rle.bmp"), | ||||||
|                 os.path.join(base, "g", "pal4rle.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}" | ||||||
|  |  | ||||||
|  | @ -312,7 +312,7 @@ def test_apng_sequence_errors(): | ||||||
|     ] |     ] | ||||||
|     for f in test_files: |     for f in test_files: | ||||||
|         with pytest.raises(SyntaxError): |         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.seek(im.n_frames - 1) | ||||||
|                 im.load() |                 im.load() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -171,18 +171,18 @@ class TestFileLibTiff(LibTiffTestCase): | ||||||
|                             assert ( |                             assert ( | ||||||
|                                 c_float(val[0][0] / val[0][1]).value |                                 c_float(val[0][0] / val[0][1]).value | ||||||
|                                 == c_float(value[0][0] / value[0][1]).value |                                 == c_float(value[0][0] / value[0][1]).value | ||||||
|                             ), ("%s didn't roundtrip" % tag) |                             ), f"{tag} didn't roundtrip" | ||||||
|                         else: |                         else: | ||||||
|                             assert c_float(val).value == c_float(value).value, ( |                             assert ( | ||||||
|                                 "%s didn't roundtrip" % tag |                                 c_float(val).value == c_float(value).value | ||||||
|                             ) |                             ), f"{tag} didn't roundtrip" | ||||||
|                     else: |                     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 |             # https://github.com/python-pillow/Pillow/issues/1561 | ||||||
|             requested_fields = ["StripByteCounts", "RowsPerStrip", "StripOffsets"] |             requested_fields = ["StripByteCounts", "RowsPerStrip", "StripOffsets"] | ||||||
|             for field in requested_fields: |             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): |     def test_additional_metadata(self, tmp_path): | ||||||
|         # these should not crash. Seriously dummy data, most of it doesn't make |         # these should not crash. Seriously dummy data, most of it doesn't make | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ def test_others(): | ||||||
|         with Image.open(path) as im: |         with Image.open(path) as im: | ||||||
|             im.load() |             im.load() | ||||||
|             assert isinstance(im, SunImagePlugin.SunImageFile) |             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) |             # im.save(target_file) | ||||||
|             with Image.open(target_path) as target: |             with Image.open(target_path) as target: | ||||||
|                 assert_image_equal(im, target) |                 assert_image_equal(im, target) | ||||||
|  |  | ||||||
|  | @ -36,9 +36,7 @@ def test_sanity(tmp_path): | ||||||
| 
 | 
 | ||||||
|                 assert_image_equal(saved_im, original_im) |                 assert_image_equal(saved_im, original_im) | ||||||
| 
 | 
 | ||||||
|         png_paths = glob( |         png_paths = glob(os.path.join(_TGA_DIR_COMMON, f"*x*_{mode.lower()}.png")) | ||||||
|             os.path.join(_TGA_DIR_COMMON, "*x*_{}.png".format(mode.lower())) |  | ||||||
|         ) |  | ||||||
| 
 | 
 | ||||||
|         for png_path in png_paths: |         for png_path in png_paths: | ||||||
|             with Image.open(png_path) as reference_im: |             with Image.open(png_path) as reference_im: | ||||||
|  |  | ||||||
|  | @ -145,16 +145,16 @@ def test_write_metadata(tmp_path): | ||||||
|             assert_deep_equal( |             assert_deep_equal( | ||||||
|                 original[tag], |                 original[tag], | ||||||
|                 value, |                 value, | ||||||
|                 "{} didn't roundtrip, {}, {}".format(tag, original[tag], value), |                 f"{tag} didn't roundtrip, {original[tag]}, {value}", | ||||||
|             ) |             ) | ||||||
|         else: |         else: | ||||||
|             assert original[tag] == value, "{} didn't roundtrip, {}, {}".format( |             assert ( | ||||||
|                 tag, original[tag], value |                 original[tag] == value | ||||||
|             ) |             ), f"{tag} didn't roundtrip, {original[tag]}, {value}" | ||||||
| 
 | 
 | ||||||
|     for tag, value in original.items(): |     for tag, value in original.items(): | ||||||
|         if tag not in ignored: |         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): | def test_change_stripbytecounts_tag_type(tmp_path): | ||||||
|  |  | ||||||
|  | @ -47,11 +47,11 @@ def save_font(request, tmp_path, encoding): | ||||||
|     font.save(tempname) |     font.save(tempname) | ||||||
| 
 | 
 | ||||||
|     with Image.open(tempname.replace(".pil", ".pbm")) as loaded: |     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) |             assert_image_equal(loaded, target) | ||||||
| 
 | 
 | ||||||
|     with open(tempname, "rb") as f_loaded: |     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() |             assert f_loaded.read() == f_target.read() | ||||||
|     return tempname |     return tempname | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -128,16 +128,13 @@ class TestImageGetPixel(AccessTest): | ||||||
|         im.putpixel((0, 0), c) |         im.putpixel((0, 0), c) | ||||||
|         assert ( |         assert ( | ||||||
|             im.getpixel((0, 0)) == c |             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 |         # check putpixel negative index | ||||||
|         im.putpixel((-1, -1), c) |         im.putpixel((-1, -1), c) | ||||||
|         assert ( |         assert ( | ||||||
|             im.getpixel((-1, -1)) == c |             im.getpixel((-1, -1)) == c | ||||||
|         ), "put/getpixel roundtrip negative index failed for mode %s, color %s" % ( |         ), f"put/getpixel roundtrip negative index failed for mode {mode}, color {c}" | ||||||
|             mode, |  | ||||||
|             c, |  | ||||||
|         ) |  | ||||||
| 
 | 
 | ||||||
|         # Check 0 |         # Check 0 | ||||||
|         im = Image.new(mode, (0, 0), None) |         im = Image.new(mode, (0, 0), None) | ||||||
|  | @ -155,11 +152,11 @@ class TestImageGetPixel(AccessTest): | ||||||
|         im = Image.new(mode, (1, 1), c) |         im = Image.new(mode, (1, 1), c) | ||||||
|         assert ( |         assert ( | ||||||
|             im.getpixel((0, 0)) == c |             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 |         # check initial color negative index | ||||||
|         assert ( |         assert ( | ||||||
|             im.getpixel((-1, -1)) == c |             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 |         # Check 0 | ||||||
|         im = Image.new(mode, (0, 0), c) |         im = Image.new(mode, (0, 0), c) | ||||||
|  |  | ||||||
|  | @ -162,8 +162,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): | 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.mode == b.mode, f"got mode {repr(a.mode)}, expected {repr(b.mode)}" | ||||||
|     assert a.size == b.size, "got size %r, expected %r" % (a.size, b.size) |     assert a.size == b.size, f"got size {repr(a.size)}, expected {repr(b.size)}" | ||||||
| 
 | 
 | ||||||
|     a, b = convert_to_comparable(a, b) |     a, b = convert_to_comparable(a, b) | ||||||
| 
 | 
 | ||||||
|  | @ -176,16 +176,15 @@ def assert_compare_images(a, b, max_average_diff, max_diff=255): | ||||||
|             a.size[0] * a.size[1] |             a.size[0] * a.size[1] | ||||||
|         ) |         ) | ||||||
|         msg = ( |         msg = ( | ||||||
|             "average pixel value difference {:.4f} > expected {:.4f} " |             f"average pixel value difference {average_diff:.4f} > " | ||||||
|             "for '{}' band".format(average_diff, max_average_diff, band) |             f"expected {max_average_diff:.4f} for '{band}' band" | ||||||
|         ) |         ) | ||||||
|         assert max_average_diff >= average_diff, msg |         assert max_average_diff >= average_diff, msg | ||||||
| 
 | 
 | ||||||
|         last_diff = [i for i, num in enumerate(ch_hist) if num > 0][-1] |         last_diff = [i for i, num in enumerate(ch_hist) if num > 0][-1] | ||||||
|         assert ( |         assert max_diff >= last_diff, ( | ||||||
|             max_diff >= last_diff |             f"max pixel value difference {last_diff} > expected {max_diff} " | ||||||
|         ), "max pixel value difference {} > expected {} for '{}' band".format( |             f"for '{band}' band" | ||||||
|             last_diff, max_diff, band |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -82,15 +82,16 @@ class TestImagingCoreResampleAccuracy: | ||||||
|         for y in range(case.size[1]): |         for y in range(case.size[1]): | ||||||
|             for x in range(case.size[0]): |             for x in range(case.size[0]): | ||||||
|                 if c_px[x, y] != s_px[x, y]: |                 if c_px[x, y] != s_px[x, y]: | ||||||
|                     message = "\nHave: \n{}\n\nExpected: \n{}".format( |                     message = ( | ||||||
|                         self.serialize_image(case), self.serialize_image(sample) |                         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 |                     assert s_px[x, y] == c_px[x, y], message | ||||||
| 
 | 
 | ||||||
|     def serialize_image(self, image): |     def serialize_image(self, image): | ||||||
|         s_px = image.load() |         s_px = image.load() | ||||||
|         return "\n".join( |         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]) |             for y in range(image.size[1]) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  | @ -230,7 +231,7 @@ class TestCoreResampleConsistency: | ||||||
|         for x in range(channel.size[0]): |         for x in range(channel.size[0]): | ||||||
|             for y in range(channel.size[1]): |             for y in range(channel.size[1]): | ||||||
|                 if px[x, y] != color: |                 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 |                     assert px[x, y] == color, message | ||||||
| 
 | 
 | ||||||
|     def test_8u(self): |     def test_8u(self): | ||||||
|  | @ -269,10 +270,9 @@ class TestCoreResampleAlphaCorrect: | ||||||
|         px = i.load() |         px = i.load() | ||||||
|         for y in range(i.size[1]): |         for y in range(i.size[1]): | ||||||
|             used_colors = {px[x, y][0] for x in range(i.size[0])} |             used_colors = {px[x, y][0] for x in range(i.size[0])} | ||||||
|             assert 256 == len( |             assert 256 == len(used_colors), ( | ||||||
|                 used_colors |                 "All colors should be present in resized image. " | ||||||
|             ), "All colors should present in resized image. Only {} on {} line.".format( |                 f"Only {len(used_colors)} on {y} line." | ||||||
|                 len(used_colors), y |  | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|     @pytest.mark.xfail(reason="Current implementation isn't precise enough") |     @pytest.mark.xfail(reason="Current implementation isn't precise enough") | ||||||
|  | @ -308,8 +308,9 @@ class TestCoreResampleAlphaCorrect: | ||||||
|         for y in range(i.size[1]): |         for y in range(i.size[1]): | ||||||
|             for x in range(i.size[0]): |             for x in range(i.size[0]): | ||||||
|                 if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel: |                 if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel: | ||||||
|                     message = "pixel at ({}, {}) is differ:\n{}\n{}".format( |                     message = ( | ||||||
|                         x, y, px[x, y], clean_pixel |                         f"pixel at ({x}, {y}) is different:\n" | ||||||
|  |                         f"{px[x, y]}\n{clean_pixel}" | ||||||
|                     ) |                     ) | ||||||
|                     assert px[x, y][:3] == clean_pixel, message |                     assert px[x, y][:3] == clean_pixel, message | ||||||
| 
 | 
 | ||||||
|  | @ -504,7 +505,7 @@ class TestCoreResampleBox: | ||||||
|         ]: |         ]: | ||||||
|             res = im.resize(size, Image.LANCZOS, box) |             res = im.resize(size, Image.LANCZOS, box) | ||||||
|             assert res.size == size |             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): |     def test_no_passthrough(self): | ||||||
|         # When resize is required |         # When resize is required | ||||||
|  | @ -520,9 +521,7 @@ class TestCoreResampleBox: | ||||||
|             assert res.size == size |             assert res.size == size | ||||||
|             with pytest.raises(AssertionError, match=r"difference \d"): |             with pytest.raises(AssertionError, match=r"difference \d"): | ||||||
|                 # check that the difference at least that much |                 # check that the difference at least that much | ||||||
|                 assert_image_similar( |                 assert_image_similar(res, im.crop(box), 20, f">>> {size} {box}") | ||||||
|                     res, im.crop(box), 20, ">>> {} {}".format(size, box) |  | ||||||
|                 ) |  | ||||||
| 
 | 
 | ||||||
|     def test_skip_horizontal(self): |     def test_skip_horizontal(self): | ||||||
|         # Can skip resize for one dimension |         # Can skip resize for one dimension | ||||||
|  | @ -542,7 +541,7 @@ class TestCoreResampleBox: | ||||||
|                     res, |                     res, | ||||||
|                     im.crop(box).resize(size, flt), |                     im.crop(box).resize(size, flt), | ||||||
|                     0.4, |                     0.4, | ||||||
|                     ">>> {} {} {}".format(size, box, flt), |                     f">>> {size} {box} {flt}", | ||||||
|                 ) |                 ) | ||||||
| 
 | 
 | ||||||
|     def test_skip_vertical(self): |     def test_skip_vertical(self): | ||||||
|  | @ -563,5 +562,5 @@ class TestCoreResampleBox: | ||||||
|                     res, |                     res, | ||||||
|                     im.crop(box).resize(size, flt), |                     im.crop(box).resize(size, flt), | ||||||
|                     0.4, |                     0.4, | ||||||
|                     ">>> {} {} {}".format(size, box, flt), |                     f">>> {size} {box} {flt}", | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|  | @ -182,7 +182,7 @@ def helper_chord(mode, bbox, start, end): | ||||||
|     # Arrange |     # Arrange | ||||||
|     im = Image.new(mode, (W, H)) |     im = Image.new(mode, (W, H)) | ||||||
|     draw = ImageDraw.Draw(im) |     draw = ImageDraw.Draw(im) | ||||||
|     expected = "Tests/images/imagedraw_chord_{}.png".format(mode) |     expected = f"Tests/images/imagedraw_chord_{mode}.png" | ||||||
| 
 | 
 | ||||||
|     # Act |     # Act | ||||||
|     draw.chord(bbox, start, end, fill="red", outline="yellow") |     draw.chord(bbox, start, end, fill="red", outline="yellow") | ||||||
|  | @ -244,7 +244,7 @@ def helper_ellipse(mode, bbox): | ||||||
|     # Arrange |     # Arrange | ||||||
|     im = Image.new(mode, (W, H)) |     im = Image.new(mode, (W, H)) | ||||||
|     draw = ImageDraw.Draw(im) |     draw = ImageDraw.Draw(im) | ||||||
|     expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) |     expected = f"Tests/images/imagedraw_ellipse_{mode}.png" | ||||||
| 
 | 
 | ||||||
|     # Act |     # Act | ||||||
|     draw.ellipse(bbox, fill="green", outline="blue") |     draw.ellipse(bbox, fill="green", outline="blue") | ||||||
|  | @ -514,7 +514,7 @@ def test_polygon_kite(): | ||||||
|         # Arrange |         # Arrange | ||||||
|         im = Image.new(mode, (W, H)) |         im = Image.new(mode, (W, H)) | ||||||
|         draw = ImageDraw.Draw(im) |         draw = ImageDraw.Draw(im) | ||||||
|         expected = "Tests/images/imagedraw_polygon_kite_{}.png".format(mode) |         expected = f"Tests/images/imagedraw_polygon_kite_{mode}.png" | ||||||
| 
 | 
 | ||||||
|         # Act |         # Act | ||||||
|         draw.polygon(KITE_POINTS, fill="blue", outline="yellow") |         draw.polygon(KITE_POINTS, fill="blue", outline="yellow") | ||||||
|  | @ -1091,7 +1091,5 @@ def test_same_color_outline(): | ||||||
|                 draw_method(*args) |                 draw_method(*args) | ||||||
| 
 | 
 | ||||||
|                 # Assert |                 # Assert | ||||||
|                 expected = "Tests/images/imagedraw_outline_{}_{}.png".format( |                 expected = f"Tests/images/imagedraw_outline_{operation}_{mode}.png" | ||||||
|                     operation, mode |  | ||||||
|                 ) |  | ||||||
|                 assert_image_similar_tofile(im, expected, 1) |                 assert_image_similar_tofile(im, expected, 1) | ||||||
|  |  | ||||||
|  | @ -55,7 +55,7 @@ def helper_ellipse(mode, bbox): | ||||||
|     draw = ImageDraw2.Draw(im) |     draw = ImageDraw2.Draw(im) | ||||||
|     pen = ImageDraw2.Pen("blue", width=2) |     pen = ImageDraw2.Pen("blue", width=2) | ||||||
|     brush = ImageDraw2.Brush("green") |     brush = ImageDraw2.Brush("green") | ||||||
|     expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) |     expected = f"Tests/images/imagedraw_ellipse_{mode}.png" | ||||||
| 
 | 
 | ||||||
|     # Act |     # Act | ||||||
|     draw.ellipse(bbox, pen, brush) |     draw.ellipse(bbox, pen, brush) | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ def _check_alpha(im, original, op, amount): | ||||||
|     assert_image_equal( |     assert_image_equal( | ||||||
|         im.getchannel("A"), |         im.getchannel("A"), | ||||||
|         original.getchannel("A"), |         original.getchannel("A"), | ||||||
|         "Diff on {}: {}".format(op, amount), |         f"Diff on {op}: {amount}", | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ from PIL import Image, ImageMath | ||||||
| 
 | 
 | ||||||
| def pixel(im): | def pixel(im): | ||||||
|     if hasattr(im, "im"): |     if hasattr(im, "im"): | ||||||
|         return "{} {!r}".format(im.mode, im.getpixel((0, 0))) |         return "{} {}".format(im.mode, repr(im.getpixel((0, 0)))) | ||||||
|     else: |     else: | ||||||
|         if isinstance(im, int): |         if isinstance(im, int): | ||||||
|             return int(im)  # hack to deal with booleans |             return int(im)  # hack to deal with booleans | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ def create_lut(): | ||||||
|     for op in ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge"): |     for op in ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge"): | ||||||
|         lb = ImageMorph.LutBuilder(op_name=op) |         lb = ImageMorph.LutBuilder(op_name=op) | ||||||
|         lut = lb.build_lut() |         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) |             f.write(lut) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -76,7 +76,7 @@ def test_lut(): | ||||||
|         assert lb.get_lut() is None |         assert lb.get_lut() is None | ||||||
| 
 | 
 | ||||||
|         lut = lb.build_lut() |         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()) |             assert lut == bytearray(f.read()) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ def setup_module(): | ||||||
|         tk.Frame() |         tk.Frame() | ||||||
|         # root = tk.Tk() |         # root = tk.Tk() | ||||||
|     except tk.TclError as v: |     except tk.TclError as v: | ||||||
|         pytest.skip("TCL Error: %s" % v) |         pytest.skip(f"TCL Error: {v}") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_kw(): | def test_kw(): | ||||||
|  |  | ||||||
|  | @ -15,9 +15,9 @@ def verify(im1): | ||||||
|             xy = x, y |             xy = x, y | ||||||
|             p1 = pix1[xy] |             p1 = pix1[xy] | ||||||
|             p2 = pix2[xy] |             p2 = pix2[xy] | ||||||
|             assert p1 == p2, "got {!r} from mode {} at {}, expected {!r}".format( |             assert ( | ||||||
|                 p1, im1.mode, xy, p2 |                 p1 == p2 | ||||||
|             ) |             ), f"got {repr(p1)} from mode {im1.mode} at {xy}, expected {repr(p2)}" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_basic(tmp_path): | def test_basic(tmp_path): | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ def test_sanity(tmp_path): | ||||||
|             continue |             continue | ||||||
| 
 | 
 | ||||||
|         # Test saving the file |         # Test saving the file | ||||||
|         tempfile = str(tmp_path / "temp_{}.png".format(mode)) |         tempfile = str(tmp_path / f"temp_{mode}.png") | ||||||
|         data.save(tempfile) |         data.save(tempfile) | ||||||
| 
 | 
 | ||||||
|         # Check that it actually worked. |         # Check that it actually worked. | ||||||
|  |  | ||||||
|  | @ -16,5 +16,5 @@ class TestToQPixmap(PillowQPixmapTestCase): | ||||||
|             assert not data.isNull() |             assert not data.isNull() | ||||||
| 
 | 
 | ||||||
|             # Test saving the file |             # Test saving the file | ||||||
|             tempfile = str(tmp_path / "temp_{}.png".format(mode)) |             tempfile = str(tmp_path / f"temp_{mode}.png") | ||||||
|             data.save(tempfile) |             data.save(tempfile) | ||||||
|  |  | ||||||
|  | @ -14,7 +14,6 @@ def test_is_path(): | ||||||
|     assert it_is |     assert it_is | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.mark.skipif(not _util.py36, reason="os.path support for Paths added in 3.6") |  | ||||||
| def test_path_obj_is_path(): | def test_path_obj_is_path(): | ||||||
|     # Arrange |     # Arrange | ||||||
|     from pathlib import Path |     from pathlib import Path | ||||||
|  |  | ||||||
|  | @ -212,10 +212,10 @@ class DdsImageFile(ImageFile.ImageFile): | ||||||
|     def _open(self): |     def _open(self): | ||||||
|         magic, header_size = struct.unpack("<II", self.fp.read(8)) |         magic, header_size = struct.unpack("<II", self.fp.read(8)) | ||||||
|         if header_size != 124: |         if header_size != 124: | ||||||
|             raise OSError("Unsupported header size %r" % (header_size)) |             raise OSError(f"Unsupported header size {repr(header_size)}") | ||||||
|         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("Incomplete header: %s bytes" % len(header_bytes)) |             raise OSError(f"Incomplete header: {len(header_bytes)} bytes") | ||||||
|         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)) | ||||||
|  | @ -235,7 +235,7 @@ class DdsImageFile(ImageFile.ImageFile): | ||||||
|         elif fourcc == b"DXT5": |         elif fourcc == b"DXT5": | ||||||
|             self.decoder = "DXT5" |             self.decoder = "DXT5" | ||||||
|         else: |         else: | ||||||
|             raise NotImplementedError("Unimplemented pixel format %r" % fourcc) |             raise NotImplementedError(f"Unimplemented pixel format {fourcc}") | ||||||
| 
 | 
 | ||||||
|         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))] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -124,7 +124,7 @@ Identify Image Files | ||||||
|     for infile in sys.argv[1:]: |     for infile in sys.argv[1:]: | ||||||
|         try: |         try: | ||||||
|             with Image.open(infile) as im: |             with Image.open(infile) as im: | ||||||
|                 print(infile, im.format, "%dx%d" % im.size, im.mode) |                 print(infile, im.format, f"{im.size}x{im.mode}") | ||||||
|         except OSError: |         except OSError: | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ Example: Vary the sharpness of an image | ||||||
| 
 | 
 | ||||||
|     for i in range(8): |     for i in range(8): | ||||||
|         factor = i / 4.0 |         factor = i / 4.0 | ||||||
|         enhancer.enhance(factor).show("Sharpness %f" % factor) |         enhancer.enhance(factor).show(f"Sharpness {factor:f}") | ||||||
| 
 | 
 | ||||||
| Also see the :file:`enhancer.py` demo program in the :file:`Scripts/` | Also see the :file:`enhancer.py` demo program in the :file:`Scripts/` | ||||||
| directory. | directory. | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ Extracting frames from an animation | ||||||
|     with Image.open("animation.fli") as im: |     with Image.open("animation.fli") as im: | ||||||
|         index = 1 |         index = 1 | ||||||
|         for frame in ImageSequence.Iterator(im): |         for frame in ImageSequence.Iterator(im): | ||||||
|             frame.save("frame%d.png" % index) |             frame.save(f"frame{index}.png") | ||||||
|             index += 1 |             index += 1 | ||||||
| 
 | 
 | ||||||
| The :py:class:`~PIL.ImageSequence.Iterator` class | The :py:class:`~PIL.ImageSequence.Iterator` class | ||||||
|  |  | ||||||
							
								
								
									
										67
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -21,7 +21,7 @@ from setuptools.command.build_ext import build_ext | ||||||
| 
 | 
 | ||||||
| def get_version(): | def get_version(): | ||||||
|     version_file = "src/PIL/_version.py" |     version_file = "src/PIL/_version.py" | ||||||
|     with open(version_file, "r") as f: |     with open(version_file) as f: | ||||||
|         exec(compile(f.read(), version_file, "exec")) |         exec(compile(f.read(), version_file, "exec")) | ||||||
|     return locals()["__version__"] |     return locals()["__version__"] | ||||||
| 
 | 
 | ||||||
|  | @ -39,10 +39,10 @@ ZLIB_ROOT = None | ||||||
| 
 | 
 | ||||||
| if sys.platform == "win32" and sys.version_info >= (3, 9): | if sys.platform == "win32" and sys.version_info >= (3, 9): | ||||||
|     warnings.warn( |     warnings.warn( | ||||||
|         "Pillow {} does not support Python {}.{} and does not provide prebuilt " |         f"Pillow {PILLOW_VERSION} does not support Python " | ||||||
|         "Windows binaries. We do not recommend building from source on Windows.".format( |         f"{sys.version_info.major}.{sys.version_info.minor} and does not provide " | ||||||
|             PILLOW_VERSION, sys.version_info.major, sys.version_info.minor |         "prebuilt Windows binaries. We do not recommend building from source on " | ||||||
|         ), |         "Windows.", | ||||||
|         RuntimeWarning, |         RuntimeWarning, | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  | @ -174,7 +174,7 @@ def _find_library_dirs_ldconfig(): | ||||||
|         # Assuming GLIBC's ldconfig (with option -p) |         # Assuming GLIBC's ldconfig (with option -p) | ||||||
|         # Alpine Linux uses musl that can't print cache |         # Alpine Linux uses musl that can't print cache | ||||||
|         args = ["/sbin/ldconfig", "-p"] |         args = ["/sbin/ldconfig", "-p"] | ||||||
|         expr = r".*\(%s.*\) => (.*)" % abi_type |         expr = fr".*\({abi_type}.*\) => (.*)" | ||||||
|         env = dict(os.environ) |         env = dict(os.environ) | ||||||
|         env["LC_ALL"] = "C" |         env["LC_ALL"] = "C" | ||||||
|         env["LANG"] = "C" |         env["LANG"] = "C" | ||||||
|  | @ -302,8 +302,8 @@ class pil_build_ext(build_ext): | ||||||
| 
 | 
 | ||||||
|     user_options = ( |     user_options = ( | ||||||
|         build_ext.user_options |         build_ext.user_options | ||||||
|         + [("disable-%s" % x, None, "Disable support for %s" % x) for x in feature] |         + [(f"disable-{x}", None, f"Disable support for {x}") for x in feature] | ||||||
|         + [("enable-%s" % x, None, "Enable support for %s" % 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"), |             ("disable-platform-guessing", None, "Disable platform guessing on Linux"), | ||||||
|             ("debug", None, "Debug logging"), |             ("debug", None, "Debug logging"), | ||||||
|  | @ -316,8 +316,8 @@ class pil_build_ext(build_ext): | ||||||
|         self.add_imaging_libs = "" |         self.add_imaging_libs = "" | ||||||
|         build_ext.initialize_options(self) |         build_ext.initialize_options(self) | ||||||
|         for x in self.feature: |         for x in self.feature: | ||||||
|             setattr(self, "disable_%s" % x, None) |             setattr(self, f"disable_{x}", None) | ||||||
|             setattr(self, "enable_%s" % x, None) |             setattr(self, f"enable_{x}", None) | ||||||
| 
 | 
 | ||||||
|     def finalize_options(self): |     def finalize_options(self): | ||||||
|         build_ext.finalize_options(self) |         build_ext.finalize_options(self) | ||||||
|  | @ -334,15 +334,15 @@ class pil_build_ext(build_ext): | ||||||
|             except TypeError: |             except TypeError: | ||||||
|                 self.parallel = None |                 self.parallel = None | ||||||
|         for x in self.feature: |         for x in self.feature: | ||||||
|             if getattr(self, "disable_%s" % x): |             if getattr(self, f"disable_{x}"): | ||||||
|                 setattr(self.feature, x, False) |                 setattr(self.feature, x, False) | ||||||
|                 self.feature.required.discard(x) |                 self.feature.required.discard(x) | ||||||
|                 _dbg("Disabling %s", x) |                 _dbg("Disabling %s", x) | ||||||
|                 if getattr(self, "enable_%s" % x): |                 if getattr(self, f"enable_{x}"): | ||||||
|                     raise ValueError( |                     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) |                 _dbg("Requiring %s", x) | ||||||
|                 self.feature.required.add(x) |                 self.feature.required.add(x) | ||||||
| 
 | 
 | ||||||
|  | @ -393,12 +393,12 @@ class pil_build_ext(build_ext): | ||||||
|             if root is None and pkg_config: |             if root is None and pkg_config: | ||||||
|                 if isinstance(lib_name, tuple): |                 if isinstance(lib_name, tuple): | ||||||
|                     for lib_name2 in lib_name: |                     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) |                         root = pkg_config(lib_name2) | ||||||
|                         if root: |                         if root: | ||||||
|                             break |                             break | ||||||
|                 else: |                 else: | ||||||
|                     _dbg("Looking for `%s` using pkg-config." % lib_name) |                     _dbg(f"Looking for `{lib_name}` using pkg-config.") | ||||||
|                     root = pkg_config(lib_name) |                     root = pkg_config(lib_name) | ||||||
| 
 | 
 | ||||||
|             if isinstance(root, tuple): |             if isinstance(root, tuple): | ||||||
|  | @ -740,9 +740,9 @@ class pil_build_ext(build_ext): | ||||||
|             and sys.version_info < (3, 9) |             and sys.version_info < (3, 9) | ||||||
|             and not (PLATFORM_PYPY or PLATFORM_MINGW) |             and not (PLATFORM_PYPY or PLATFORM_MINGW) | ||||||
|         ): |         ): | ||||||
|             defs.append(("PILLOW_VERSION", '"\\"%s\\""' % PILLOW_VERSION)) |             defs.append(("PILLOW_VERSION", f'"\\"{PILLOW_VERSION}\\""')) | ||||||
|         else: |         else: | ||||||
|             defs.append(("PILLOW_VERSION", '"%s"' % PILLOW_VERSION)) |             defs.append(("PILLOW_VERSION", f'"{PILLOW_VERSION}"')) | ||||||
| 
 | 
 | ||||||
|         self._update_extension("PIL._imaging", libs, defs) |         self._update_extension("PIL._imaging", libs, defs) | ||||||
| 
 | 
 | ||||||
|  | @ -792,11 +792,11 @@ class pil_build_ext(build_ext): | ||||||
|         print("-" * 68) |         print("-" * 68) | ||||||
|         print("PIL SETUP SUMMARY") |         print("PIL SETUP SUMMARY") | ||||||
|         print("-" * 68) |         print("-" * 68) | ||||||
|         print("version      Pillow %s" % PILLOW_VERSION) |         print(f"version      Pillow {PILLOW_VERSION}") | ||||||
|         v = sys.version.split("[") |         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:]: |         for v in v[1:]: | ||||||
|             print("             [%s" % v.strip()) |             print(f"             [{v.strip()}") | ||||||
|         print("-" * 68) |         print("-" * 68) | ||||||
| 
 | 
 | ||||||
|         options = [ |         options = [ | ||||||
|  | @ -817,10 +817,10 @@ class pil_build_ext(build_ext): | ||||||
|             if option[0]: |             if option[0]: | ||||||
|                 version = "" |                 version = "" | ||||||
|                 if len(option) >= 3 and option[2]: |                 if len(option) >= 3 and option[2]: | ||||||
|                     version = " (%s)" % option[2] |                     version = f" ({option[2]})" | ||||||
|                 print("--- {} support available{}".format(option[1], version)) |                 print(f"--- {option[1]} support available{version}") | ||||||
|             else: |             else: | ||||||
|                 print("*** %s support not available" % option[1]) |                 print(f"*** {option[1]} support not available") | ||||||
|                 all = 0 |                 all = 0 | ||||||
| 
 | 
 | ||||||
|         print("-" * 68) |         print("-" * 68) | ||||||
|  | @ -903,28 +903,23 @@ try: | ||||||
|         zip_safe=not (debug_build() or PLATFORM_MINGW), |         zip_safe=not (debug_build() or PLATFORM_MINGW), | ||||||
|     ) |     ) | ||||||
| except RequiredDependencyException as err: | 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. | a required dependency when compiling Pillow from source. | ||||||
| 
 | 
 | ||||||
| Please see the install instructions at: | Please see the install instructions at: | ||||||
|    https://pillow.readthedocs.io/en/latest/installation.html |    https://pillow.readthedocs.io/en/latest/installation.html | ||||||
| 
 | 
 | ||||||
| """ % ( | """ | ||||||
|         str(err) |  | ||||||
|     ) |  | ||||||
|     sys.stderr.write(msg) |     sys.stderr.write(msg) | ||||||
|     raise RequiredDependencyException(msg) |     raise RequiredDependencyException(msg) | ||||||
| except DependencyException as err: | except DependencyException 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)}, | ||||||
| which was requested by the option flag --enable-%s | which was requested by the option flag --enable-{str(err)} | ||||||
| 
 | 
 | ||||||
| """ % ( | """ | ||||||
|         str(err), |  | ||||||
|         str(err), |  | ||||||
|     ) |  | ||||||
|     sys.stderr.write(msg) |     sys.stderr.write(msg) | ||||||
|     raise DependencyException(msg) |     raise DependencyException(msg) | ||||||
|  |  | ||||||
|  | @ -250,7 +250,7 @@ class BlpImageFile(ImageFile.ImageFile): | ||||||
|             decoder = "BLP2" |             decoder = "BLP2" | ||||||
|             self.mode = "RGBA" if self._blp_alpha_depth else "RGB" |             self.mode = "RGBA" if self._blp_alpha_depth else "RGB" | ||||||
|         else: |         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))] |         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)) |                 self.set_as_raw(bytes(data)) | ||||||
|             else: |             else: | ||||||
|                 raise BLPFormatError( |                 raise BLPFormatError( | ||||||
|                     "Unsupported BLP encoding %r" % (self._blp_encoding) |                     f"Unsupported BLP encoding {repr(self._blp_encoding)}" | ||||||
|                 ) |                 ) | ||||||
|         else: |         else: | ||||||
|             raise BLPFormatError( |             raise BLPFormatError( | ||||||
|                 "Unsupported BLP compression %r" % (self._blp_encoding) |                 f"Unsupported BLP compression {repr(self._blp_encoding)}" | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|     def _decode_jpeg_stream(self): |     def _decode_jpeg_stream(self): | ||||||
|  | @ -400,13 +400,15 @@ class BLP2Decoder(_BLPBaseDecoder): | ||||||
|                             data += d |                             data += d | ||||||
|                 else: |                 else: | ||||||
|                     raise BLPFormatError( |                     raise BLPFormatError( | ||||||
|                         "Unsupported alpha encoding %r" % (self._blp_alpha_encoding) |                         f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}" | ||||||
|                     ) |                     ) | ||||||
|             else: |             else: | ||||||
|                 raise BLPFormatError("Unknown BLP encoding %r" % (self._blp_encoding)) |                 raise BLPFormatError(f"Unknown BLP encoding {repr(self._blp_encoding)}") | ||||||
| 
 | 
 | ||||||
|         else: |         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)) |         self.set_as_raw(bytes(data)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -149,7 +149,7 @@ class BmpImageFile(ImageFile.ImageFile): | ||||||
|                     file_info["a_mask"], |                     file_info["a_mask"], | ||||||
|                 ) |                 ) | ||||||
|         else: |         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 |         # ------------------ Special case : header is reported 40, which | ||||||
|         # ---------------------- is shorter than real size for bpp >= 16 |         # ---------------------- is shorter than real size for bpp >= 16 | ||||||
|  | @ -169,7 +169,7 @@ 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("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) |         # ---------------- Process BMP with Bitfields compression (not palette) | ||||||
|         if file_info["compression"] == self.BITFIELDS: |         if file_info["compression"] == self.BITFIELDS: | ||||||
|  | @ -214,14 +214,14 @@ class BmpImageFile(ImageFile.ImageFile): | ||||||
|             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" | ||||||
|         else: |         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 |         # --------------- 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("Unsupported BMP Palette size (%d)" % file_info["colors"]) |                 raise OSError(f"Unsupported BMP Palette size ({file_info['colors']})") | ||||||
|             else: |             else: | ||||||
|                 padding = file_info["palette_padding"] |                 padding = file_info["palette_padding"] | ||||||
|                 palette = read(padding * file_info["colors"]) |                 palette = read(padding * file_info["colors"]) | ||||||
|  | @ -310,7 +310,7 @@ 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("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 |     info = im.encoderinfo | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -106,10 +106,10 @@ class DdsImageFile(ImageFile.ImageFile): | ||||||
|     def _open(self): |     def _open(self): | ||||||
|         magic, header_size = struct.unpack("<II", self.fp.read(8)) |         magic, header_size = struct.unpack("<II", self.fp.read(8)) | ||||||
|         if header_size != 124: |         if header_size != 124: | ||||||
|             raise OSError("Unsupported header size %r" % (header_size)) |             raise OSError(f"Unsupported header size {repr(header_size)}") | ||||||
|         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("Incomplete header: %s bytes" % len(header_bytes)) |             raise OSError(f"Incomplete header: {len(header_bytes)} bytes") | ||||||
|         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)) | ||||||
|  | @ -159,10 +159,10 @@ class DdsImageFile(ImageFile.ImageFile): | ||||||
|                     n = 7 |                     n = 7 | ||||||
|                 else: |                 else: | ||||||
|                     raise NotImplementedError( |                     raise NotImplementedError( | ||||||
|                         "Unimplemented DXGI format %d" % (dxgi_format) |                         f"Unimplemented DXGI format {dxgi_format}" | ||||||
|                     ) |                     ) | ||||||
|             else: |             else: | ||||||
|                 raise NotImplementedError("Unimplemented pixel format %r" % (fourcc)) |                 raise NotImplementedError(f"Unimplemented pixel format {repr(fourcc)}") | ||||||
| 
 | 
 | ||||||
|             self.tile = [("bcn", (0, 0) + self.size, data_start, (n))] |             self.tile = [("bcn", (0, 0) + self.size, data_start, (n))] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -118,10 +118,10 @@ def Ghostscript(tile, size, fp, scale=1): | ||||||
|         "-dNOPAUSE",  # don't pause between pages |         "-dNOPAUSE",  # don't pause between pages | ||||||
|         "-dSAFER",  # safe mode |         "-dSAFER",  # safe mode | ||||||
|         "-sDEVICE=ppmraw",  # ppm driver |         "-sDEVICE=ppmraw",  # ppm driver | ||||||
|         "-sOutputFile=%s" % outfile,  # output file |         f"-sOutputFile={outfile}",  # output file | ||||||
|         # adjust for image origin |         # adjust for image origin | ||||||
|         "-c", |         "-c", | ||||||
|         "%d %d translate" % (-bbox[0], -bbox[1]), |         f"{-bbox[0]} {-bbox[1]} translate", | ||||||
|         "-f", |         "-f", | ||||||
|         infile,  # input file |         infile,  # input file | ||||||
|         # showpage (see https://bugs.ghostscript.com/show_bug.cgi?id=698272) |         # showpage (see https://bugs.ghostscript.com/show_bug.cgi?id=698272) | ||||||
|  | @ -386,10 +386,10 @@ def _save(im, fp, filename, eps=1): | ||||||
|         # image header |         # image header | ||||||
|         fp.write("gsave\n") |         fp.write("gsave\n") | ||||||
|         fp.write("10 dict begin\n") |         fp.write("10 dict begin\n") | ||||||
|         fp.write("/buf %d string def\n" % (im.size[0] * operator[1])) |         fp.write(f"/buf {im.size[0] * operator[1]} string def\n") | ||||||
|         fp.write("%d %d scale\n" % im.size) |         fp.write("%d %d scale\n" % im.size) | ||||||
|         fp.write("%d %d 8\n" % im.size)  # <= bits |         fp.write("%d %d 8\n" % im.size)  # <= bits | ||||||
|         fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1])) |         fp.write(f"[{im.size[0]} 0 0 -{im.size[1]} 0 {im.size[1]}]\n") | ||||||
|         fp.write("{ currentfile buf readhexstring pop } bind\n") |         fp.write("{ currentfile buf readhexstring pop } bind\n") | ||||||
|         fp.write(operator[2] + "\n") |         fp.write(operator[2] + "\n") | ||||||
|         if hasattr(fp, "flush"): |         if hasattr(fp, "flush"): | ||||||
|  |  | ||||||
|  | @ -133,7 +133,7 @@ class FliImageFile(ImageFile.ImageFile): | ||||||
|             self.load() |             self.load() | ||||||
| 
 | 
 | ||||||
|         if frame != self.__frame + 1: |         if frame != self.__frame + 1: | ||||||
|             raise ValueError("cannot seek to frame %d" % frame) |             raise ValueError(f"cannot seek to frame {frame}") | ||||||
|         self.__frame = frame |         self.__frame = frame | ||||||
| 
 | 
 | ||||||
|         # move to next frame |         # move to next frame | ||||||
|  |  | ||||||
|  | @ -101,7 +101,7 @@ class FontFile: | ||||||
|         # font metrics |         # font metrics | ||||||
|         with open(os.path.splitext(filename)[0] + ".pil", "wb") as fp: |         with open(os.path.splitext(filename)[0] + ".pil", "wb") as fp: | ||||||
|             fp.write(b"PILfont\n") |             fp.write(b"PILfont\n") | ||||||
|             fp.write((";;;;;;%d;\n" % self.ysize).encode("ascii"))  # HACK!!! |             fp.write(f";;;;;;{self.ysize};\n".encode("ascii"))  # HACK!!! | ||||||
|             fp.write(b"DATA\n") |             fp.write(b"DATA\n") | ||||||
|             for id in range(256): |             for id in range(256): | ||||||
|                 m = self.metrics[id] |                 m = self.metrics[id] | ||||||
|  |  | ||||||
|  | @ -73,7 +73,7 @@ class FpxImageFile(ImageFile.ImageFile): | ||||||
|         # get the Image Contents Property Set |         # get the Image Contents Property Set | ||||||
| 
 | 
 | ||||||
|         prop = self.ole.getproperties( |         prop = self.ole.getproperties( | ||||||
|             ["Data Object Store %06d" % index, "\005Image Contents"] |             [f"Data Object Store {index:06d}", "\005Image Contents"] | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         # size (highest resolution) |         # size (highest resolution) | ||||||
|  | @ -121,8 +121,8 @@ class FpxImageFile(ImageFile.ImageFile): | ||||||
|         # setup tile descriptors for a given subimage |         # setup tile descriptors for a given subimage | ||||||
| 
 | 
 | ||||||
|         stream = [ |         stream = [ | ||||||
|             "Data Object Store %06d" % index, |             f"Data Object Store {index:06d}", | ||||||
|             "Resolution %04d" % subimage, |             f"Resolution {subimage:04d}", | ||||||
|             "Subimage 0000 Header", |             "Subimage 0000 Header", | ||||||
|         ] |         ] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -89,7 +89,7 @@ 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("Invalid texture compression format: %r" % (format)) |             raise ValueError(f"Invalid texture compression format: {repr(format)}") | ||||||
| 
 | 
 | ||||||
|         self.fp.close() |         self.fp.close() | ||||||
|         self.fp = BytesIO(data) |         self.fp = BytesIO(data) | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ class GbrImageFile(ImageFile.ImageFile): | ||||||
|         if header_size < 20: |         if header_size < 20: | ||||||
|             raise SyntaxError("not a GIMP brush") |             raise SyntaxError("not a GIMP brush") | ||||||
|         if version not in (1, 2): |         if version not in (1, 2): | ||||||
|             raise SyntaxError("Unsupported GIMP brush version: %s" % version) |             raise SyntaxError(f"Unsupported GIMP brush version: {version}") | ||||||
| 
 | 
 | ||||||
|         width = i32(self.fp.read(4)) |         width = i32(self.fp.read(4)) | ||||||
|         height = i32(self.fp.read(4)) |         height = i32(self.fp.read(4)) | ||||||
|  | @ -55,7 +55,7 @@ class GbrImageFile(ImageFile.ImageFile): | ||||||
|         if width <= 0 or height <= 0: |         if width <= 0 or height <= 0: | ||||||
|             raise SyntaxError("not a GIMP brush") |             raise SyntaxError("not a GIMP brush") | ||||||
|         if color_depth not in (1, 4): |         if color_depth not in (1, 4): | ||||||
|             raise SyntaxError("Unsupported GIMP brush color depth: %s" % color_depth) |             raise SyntaxError(f"Unsupported GIMP brush color depth: {color_depth}") | ||||||
| 
 | 
 | ||||||
|         if version == 1: |         if version == 1: | ||||||
|             comment_length = header_size - 20 |             comment_length = header_size - 20 | ||||||
|  |  | ||||||
|  | @ -154,7 +154,7 @@ class GifImageFile(ImageFile.ImageFile): | ||||||
|                 self.load() |                 self.load() | ||||||
| 
 | 
 | ||||||
|         if frame != self.__frame + 1: |         if frame != self.__frame + 1: | ||||||
|             raise ValueError("cannot seek to frame %d" % frame) |             raise ValueError(f"cannot seek to frame {frame}") | ||||||
|         self.__frame = frame |         self.__frame = frame | ||||||
| 
 | 
 | ||||||
|         self.tile = [] |         self.tile = [] | ||||||
|  |  | ||||||
|  | @ -83,7 +83,7 @@ def read_32(fobj, start_length, size): | ||||||
|                 if bytesleft <= 0: |                 if bytesleft <= 0: | ||||||
|                     break |                     break | ||||||
|             if bytesleft != 0: |             if bytesleft != 0: | ||||||
|                 raise SyntaxError("Error reading channel [%r left]" % bytesleft) |                 raise SyntaxError(f"Error reading channel [{repr(bytesleft)} left]") | ||||||
|             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} | ||||||
|  | @ -321,7 +321,7 @@ def _save(im, fp, filename): | ||||||
|         last_w = None |         last_w = None | ||||||
|         second_path = None |         second_path = None | ||||||
|         for w in [16, 32, 128, 256, 512]: |         for w in [16, 32, 128, 256, 512]: | ||||||
|             prefix = "icon_{}x{}".format(w, w) |             prefix = f"icon_{w}x{w}" | ||||||
| 
 | 
 | ||||||
|             first_path = os.path.join(iconset, prefix + ".png") |             first_path = os.path.join(iconset, prefix + ".png") | ||||||
|             if last_w == w: |             if last_w == w: | ||||||
|  |  | ||||||
|  | @ -86,16 +86,16 @@ OPEN = { | ||||||
| 
 | 
 | ||||||
| # ifunc95 extensions | # ifunc95 extensions | ||||||
| for i in ["8", "8S", "16", "16S", "32", "32F"]: | for i in ["8", "8S", "16", "16S", "32", "32F"]: | ||||||
|     OPEN["L %s image" % i] = ("F", "F;%s" % i) |     OPEN[f"L {i} image"] = ("F", f"F;{i}") | ||||||
|     OPEN["L*%s image" % i] = ("F", "F;%s" % i) |     OPEN[f"L*{i} image"] = ("F", f"F;{i}") | ||||||
| for i in ["16", "16L", "16B"]: | for i in ["16", "16L", "16B"]: | ||||||
|     OPEN["L %s image" % i] = ("I;%s" % i, "I;%s" % i) |     OPEN[f"L {i} image"] = (f"I;{i}", f"I;{i}") | ||||||
|     OPEN["L*%s image" % i] = ("I;%s" % i, "I;%s" % i) |     OPEN[f"L*{i} image"] = (f"I;{i}", f"I;{i}") | ||||||
| for i in ["32S"]: | for i in ["32S"]: | ||||||
|     OPEN["L %s image" % i] = ("I", "I;%s" % i) |     OPEN[f"L {i} image"] = ("I", f"I;{i}") | ||||||
|     OPEN["L*%s image" % i] = ("I", "I;%s" % i) |     OPEN[f"L*{i} image"] = ("I", f"I;{i}") | ||||||
| for i in range(2, 33): | for i in range(2, 33): | ||||||
|     OPEN["L*%s image" % i] = ("F", "F;%s" % i) |     OPEN[f"L*{i} image"] = ("F", f"F;{i}") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # -------------------------------------------------------------------- | # -------------------------------------------------------------------- | ||||||
|  | @ -342,11 +342,11 @@ 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("Cannot save %s images as IM" % im.mode) from e |         raise ValueError(f"Cannot save {im.mode} images as IM") from e | ||||||
| 
 | 
 | ||||||
|     frames = im.encoderinfo.get("frames", 1) |     frames = im.encoderinfo.get("frames", 1) | ||||||
| 
 | 
 | ||||||
|     fp.write(("Image type: %s image\r\n" % image_type).encode("ascii")) |     fp.write(f"Image type: {image_type} image\r\n".encode("ascii")) | ||||||
|     if filename: |     if filename: | ||||||
|         # Each line must be 100 characters or less, |         # Each line must be 100 characters or less, | ||||||
|         # or: SyntaxError("not an IM file") |         # or: SyntaxError("not an IM file") | ||||||
|  | @ -355,9 +355,9 @@ def _save(im, fp, filename): | ||||||
|         name, ext = os.path.splitext(os.path.basename(filename)) |         name, ext = os.path.splitext(os.path.basename(filename)) | ||||||
|         name = "".join([name[: 92 - len(ext)], ext]) |         name = "".join([name[: 92 - len(ext)], ext]) | ||||||
| 
 | 
 | ||||||
|         fp.write(("Name: %s\r\n" % name).encode("ascii")) |         fp.write(f"Name: {name}\r\n".encode("ascii")) | ||||||
|     fp.write(("Image size (x*y): %d*%d\r\n" % im.size).encode("ascii")) |     fp.write(("Image size (x*y): %d*%d\r\n" % im.size).encode("ascii")) | ||||||
|     fp.write(("File size (no of images): %d\r\n" % frames).encode("ascii")) |     fp.write(f"File size (no of images): {frames}\r\n".encode("ascii")) | ||||||
|     if im.mode in ["P", "PA"]: |     if im.mode in ["P", "PA"]: | ||||||
|         fp.write(b"Lut: 1\r\n") |         fp.write(b"Lut: 1\r\n") | ||||||
|     fp.write(b"\000" * (511 - fp.tell()) + b"\032") |     fp.write(b"\000" * (511 - fp.tell()) + b"\032") | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ if sys.version_info >= (3, 7): | ||||||
|         if name == "PILLOW_VERSION": |         if name == "PILLOW_VERSION": | ||||||
|             _raise_version_warning() |             _raise_version_warning() | ||||||
|             return __version__ |             return __version__ | ||||||
|         raise AttributeError("module '{}' has no attribute '{}'".format(__name__, name)) |         raise AttributeError(f"module '{__name__}' has no attribute '{name}'") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| else: | else: | ||||||
|  | @ -96,8 +96,8 @@ try: | ||||||
|     if __version__ != getattr(core, "PILLOW_VERSION", None): |     if __version__ != getattr(core, "PILLOW_VERSION", None): | ||||||
|         raise ImportError( |         raise ImportError( | ||||||
|             "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" | ||||||
|             "Core version: %s\n" |             f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n" | ||||||
|             "Pillow version: %s" % (getattr(core, "PILLOW_VERSION", None), __version__) |             f"Pillow version: {__version__}" | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| except ImportError as v: | except ImportError as v: | ||||||
|  | @ -403,7 +403,7 @@ def init(): | ||||||
|     for plugin in _plugins: |     for plugin in _plugins: | ||||||
|         try: |         try: | ||||||
|             logger.debug("Importing %s", plugin) |             logger.debug("Importing %s", plugin) | ||||||
|             __import__("PIL.%s" % plugin, globals(), locals(), []) |             __import__(f"PIL.{plugin}", globals(), locals(), []) | ||||||
|         except ImportError as e: |         except ImportError as e: | ||||||
|             logger.debug("Image: failed to import %s: %s", plugin, e) |             logger.debug("Image: failed to import %s: %s", plugin, e) | ||||||
| 
 | 
 | ||||||
|  | @ -435,7 +435,7 @@ 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("decoder %s not available" % decoder_name) from e |         raise OSError(f"decoder {decoder_name} not available") from e | ||||||
|     return decoder(mode, *args + extra) |     return decoder(mode, *args + extra) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -458,7 +458,7 @@ 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("encoder %s not available" % encoder_name) from e |         raise OSError(f"encoder {encoder_name} not available") from e | ||||||
|     return encoder(mode, *args + extra) |     return encoder(mode, *args + extra) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -743,7 +743,7 @@ class Image: | ||||||
|             if s: |             if s: | ||||||
|                 break |                 break | ||||||
|         if s < 0: |         if s < 0: | ||||||
|             raise RuntimeError("encoder error %d in tobytes" % s) |             raise RuntimeError(f"encoder error {s} in tobytes") | ||||||
| 
 | 
 | ||||||
|         return b"".join(data) |         return b"".join(data) | ||||||
| 
 | 
 | ||||||
|  | @ -764,9 +764,9 @@ class Image: | ||||||
|         data = self.tobytes("xbm") |         data = self.tobytes("xbm") | ||||||
|         return b"".join( |         return b"".join( | ||||||
|             [ |             [ | ||||||
|                 ("#define %s_width %d\n" % (name, self.size[0])).encode("ascii"), |                 f"#define {name}_width {self.size[0]}\n".encode("ascii"), | ||||||
|                 ("#define %s_height %d\n" % (name, self.size[1])).encode("ascii"), |                 f"#define {name}_height {self.size[1]}\n".encode("ascii"), | ||||||
|                 ("static char %s_bits[] = {\n" % name).encode("ascii"), |                 f"static char {name}_bits[] = {{\n".encode("ascii"), | ||||||
|                 data, |                 data, | ||||||
|                 b"};", |                 b"};", | ||||||
|             ] |             ] | ||||||
|  | @ -1862,7 +1862,7 @@ class Image: | ||||||
|         """ |         """ | ||||||
| 
 | 
 | ||||||
|         if resample not in (NEAREST, BILINEAR, BICUBIC, LANCZOS, BOX, HAMMING): |         if resample not in (NEAREST, BILINEAR, BICUBIC, LANCZOS, BOX, HAMMING): | ||||||
|             message = "Unknown resampling filter ({}).".format(resample) |             message = f"Unknown resampling filter ({resample})." | ||||||
| 
 | 
 | ||||||
|             filters = [ |             filters = [ | ||||||
|                 "{} ({})".format(filter[1], filter[0]) |                 "{} ({})".format(filter[1], filter[0]) | ||||||
|  | @ -2130,7 +2130,7 @@ class Image: | ||||||
|             try: |             try: | ||||||
|                 format = EXTENSION[ext] |                 format = EXTENSION[ext] | ||||||
|             except KeyError as e: |             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: |         if format.upper() not in SAVE: | ||||||
|             init() |             init() | ||||||
|  | @ -2242,7 +2242,7 @@ class Image: | ||||||
|             try: |             try: | ||||||
|                 channel = self.getbands().index(channel) |                 channel = self.getbands().index(channel) | ||||||
|             except ValueError as e: |             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)) |         return self._new(self.im.getband(channel)) | ||||||
| 
 | 
 | ||||||
|  | @ -2463,9 +2463,9 @@ class Image: | ||||||
|                     BOX: "Image.BOX", |                     BOX: "Image.BOX", | ||||||
|                     HAMMING: "Image.HAMMING", |                     HAMMING: "Image.HAMMING", | ||||||
|                     LANCZOS: "Image.LANCZOS/Image.ANTIALIAS", |                     LANCZOS: "Image.LANCZOS/Image.ANTIALIAS", | ||||||
|                 }[resample] + " ({}) cannot be used.".format(resample) |                 }[resample] + f" ({resample}) cannot be used." | ||||||
|             else: |             else: | ||||||
|                 message = "Unknown resampling filter ({}).".format(resample) |                 message = f"Unknown resampling filter ({resample})." | ||||||
| 
 | 
 | ||||||
|             filters = [ |             filters = [ | ||||||
|                 "{} ({})".format(filter[1], filter[0]) |                 "{} ({})".format(filter[1], filter[0]) | ||||||
|  | @ -2759,7 +2759,7 @@ def fromarray(obj, mode=None): | ||||||
|     else: |     else: | ||||||
|         ndmax = 4 |         ndmax = 4 | ||||||
|     if ndim > ndmax: |     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] |     size = 1 if ndim == 1 else shape[1], shape[0] | ||||||
|     if strides is not None: |     if strides is not None: | ||||||
|  | @ -2825,14 +2825,14 @@ def _decompression_bomb_check(size): | ||||||
| 
 | 
 | ||||||
|     if pixels > 2 * MAX_IMAGE_PIXELS: |     if pixels > 2 * MAX_IMAGE_PIXELS: | ||||||
|         raise DecompressionBombError( |         raise DecompressionBombError( | ||||||
|             "Image size (%d pixels) exceeds limit of %d pixels, " |             f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " | ||||||
|             "could be decompression bomb DOS attack." % (pixels, 2 * MAX_IMAGE_PIXELS) |             "pixels, could be decompression bomb DOS attack." | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     if pixels > MAX_IMAGE_PIXELS: |     if pixels > MAX_IMAGE_PIXELS: | ||||||
|         warnings.warn( |         warnings.warn( | ||||||
|             "Image size (%d pixels) exceeds limit of %d pixels, " |             f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, " | ||||||
|             "could be decompression bomb DOS attack." % (pixels, MAX_IMAGE_PIXELS), |             "could be decompression bomb DOS attack.", | ||||||
|             DecompressionBombWarning, |             DecompressionBombWarning, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  | @ -2861,7 +2861,7 @@ def open(fp, mode="r"): | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     if mode != "r": |     if mode != "r": | ||||||
|         raise ValueError("bad mode %r" % mode) |         raise ValueError(f"bad mode {repr(mode)}") | ||||||
|     elif isinstance(fp, io.StringIO): |     elif isinstance(fp, io.StringIO): | ||||||
|         raise ValueError( |         raise ValueError( | ||||||
|             "StringIO cannot be used to open an image. " |             "StringIO cannot be used to open an image. " | ||||||
|  | @ -3242,13 +3242,13 @@ def _apply_env_variables(env=None): | ||||||
|         try: |         try: | ||||||
|             var = int(var) * units |             var = int(var) * units | ||||||
|         except ValueError: |         except ValueError: | ||||||
|             warnings.warn("{} is not int".format(var_name)) |             warnings.warn(f"{var_name} is not int") | ||||||
|             continue |             continue | ||||||
| 
 | 
 | ||||||
|         try: |         try: | ||||||
|             setter(var) |             setter(var) | ||||||
|         except ValueError as e: |         except ValueError as e: | ||||||
|             warnings.warn("{}: {}".format(var_name, e)) |             warnings.warn(f"{var_name}: {e}") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| _apply_env_variables() | _apply_env_variables() | ||||||
|  | @ -3371,8 +3371,8 @@ class Exif(MutableMapping): | ||||||
|                         if len(data) != size: |                         if len(data) != size: | ||||||
|                             warnings.warn( |                             warnings.warn( | ||||||
|                                 "Possibly corrupt EXIF MakerNote data.  " |                                 "Possibly corrupt EXIF MakerNote data.  " | ||||||
|                                 "Expecting to read %d bytes but only got %d." |                                 f"Expecting to read {size} bytes but only got " | ||||||
|                                 " Skipping tag %s" % (size, len(data), ifd_tag) |                                 f"{len(data)}. Skipping tag {ifd_tag}" | ||||||
|                             ) |                             ) | ||||||
|                             continue |                             continue | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -680,8 +680,7 @@ def createProfile(colorSpace, colorTemp=-1): | ||||||
| 
 | 
 | ||||||
|     if colorSpace not in ["LAB", "XYZ", "sRGB"]: |     if colorSpace not in ["LAB", "XYZ", "sRGB"]: | ||||||
|         raise PyCMSError( |         raise PyCMSError( | ||||||
|             "Color space not supported for on-the-fly profile creation (%s)" |             f"Color space not supported for on-the-fly profile creation ({colorSpace})" | ||||||
|             % colorSpace |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     if colorSpace == "LAB": |     if colorSpace == "LAB": | ||||||
|  | @ -689,7 +688,7 @@ def createProfile(colorSpace, colorTemp=-1): | ||||||
|             colorTemp = float(colorTemp) |             colorTemp = float(colorTemp) | ||||||
|         except (TypeError, ValueError) as e: |         except (TypeError, ValueError) as e: | ||||||
|             raise PyCMSError( |             raise PyCMSError( | ||||||
|                 'Color temperature must be numeric, "%s" not valid' % colorTemp |                 f'Color temperature must be numeric, "{colorTemp}" not valid' | ||||||
|             ) from e |             ) from e | ||||||
| 
 | 
 | ||||||
|     try: |     try: | ||||||
|  | @ -734,7 +733,7 @@ def getProfileName(profile): | ||||||
|             return (profile.profile.profile_description or "") + "\n" |             return (profile.profile.profile_description or "") + "\n" | ||||||
|         if not manufacturer or len(model) > 30: |         if not manufacturer or len(model) > 30: | ||||||
|             return model + "\n" |             return model + "\n" | ||||||
|         return "{} - {}\n".format(model, manufacturer) |         return f"{model} - {manufacturer}\n" | ||||||
| 
 | 
 | ||||||
|     except (AttributeError, OSError, TypeError, ValueError) as v: |     except (AttributeError, OSError, TypeError, ValueError) as v: | ||||||
|         raise PyCMSError(v) from v |         raise PyCMSError(v) from v | ||||||
|  |  | ||||||
|  | @ -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) |     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("unknown color specifier: %r" % color) |     raise ValueError(f"unknown color specifier: {repr(color)}") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def getcolor(color, mode): | def getcolor(color, mode): | ||||||
|  |  | ||||||
|  | @ -276,7 +276,7 @@ class ImageDraw: | ||||||
|         stroke_width=0, |         stroke_width=0, | ||||||
|         stroke_fill=None, |         stroke_fill=None, | ||||||
|         *args, |         *args, | ||||||
|         **kwargs |         **kwargs, | ||||||
|     ): |     ): | ||||||
|         if self._multiline_check(text): |         if self._multiline_check(text): | ||||||
|             return self.multiline_text( |             return self.multiline_text( | ||||||
|  |  | ||||||
|  | @ -63,7 +63,7 @@ def raise_oserror(error): | ||||||
|     except AttributeError: |     except AttributeError: | ||||||
|         message = ERRORS.get(error) |         message = ERRORS.get(error) | ||||||
|     if not message: |     if not message: | ||||||
|         message = "decoder error %d" % error |         message = f"decoder error {error}" | ||||||
|     raise OSError(message + " when reading image file") |     raise OSError(message + " when reading image file") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -203,7 +203,7 @@ class ImageFile(Image.Image): | ||||||
|                         # use mmap, if possible |                         # use mmap, if possible | ||||||
|                         import mmap |                         import mmap | ||||||
| 
 | 
 | ||||||
|                         with open(self.filename, "r") as fp: |                         with open(self.filename) as fp: | ||||||
|                             self.map = mmap.mmap( |                             self.map = mmap.mmap( | ||||||
|                                 fp.fileno(), 0, access=mmap.ACCESS_READ |                                 fp.fileno(), 0, access=mmap.ACCESS_READ | ||||||
|                             ) |                             ) | ||||||
|  | @ -258,7 +258,7 @@ class ImageFile(Image.Image): | ||||||
|                                 else: |                                 else: | ||||||
|                                     raise OSError( |                                     raise OSError( | ||||||
|                                         "image file is truncated " |                                         "image file is truncated " | ||||||
|                                         "(%d bytes not processed)" % len(b) |                                         f"({len(b)} bytes not processed)" | ||||||
|                                     ) |                                     ) | ||||||
| 
 | 
 | ||||||
|                             b = b + s |                             b = b + s | ||||||
|  | @ -334,7 +334,7 @@ class StubImageFile(ImageFile): | ||||||
|     def load(self): |     def load(self): | ||||||
|         loader = self._load() |         loader = self._load() | ||||||
|         if loader is None: |         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) |         image = loader.load(self) | ||||||
|         assert image is not None |         assert image is not None | ||||||
|         # become the other object (!) |         # become the other object (!) | ||||||
|  | @ -526,7 +526,7 @@ def _save(im, fp, tile, bufsize=0): | ||||||
|                     if s: |                     if s: | ||||||
|                         break |                         break | ||||||
|             if s < 0: |             if s < 0: | ||||||
|                 raise OSError("encoder error %d when writing image file" % s) from exc |                 raise OSError(f"encoder error {s} when writing image file") from exc | ||||||
|             e.cleanup() |             e.cleanup() | ||||||
|     else: |     else: | ||||||
|         # slight speedup: compress to real file object |         # slight speedup: compress to real file object | ||||||
|  | @ -541,7 +541,7 @@ def _save(im, fp, tile, bufsize=0): | ||||||
|             else: |             else: | ||||||
|                 s = e.encode_to_file(fh, bufsize) |                 s = e.encode_to_file(fh, bufsize) | ||||||
|             if s < 0: |             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() |             e.cleanup() | ||||||
|     if hasattr(fp, "flush"): |     if hasattr(fp, "flush"): | ||||||
|         fp.flush() |         fp.flush() | ||||||
|  |  | ||||||
|  | @ -401,9 +401,8 @@ class Color3DLUT(MultibandFilter): | ||||||
|             raise ValueError( |             raise ValueError( | ||||||
|                 "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. " | ||||||
|                 "Table should be: {}x{}x{}x{}. Actual length: {}".format( |                 f"Table should be: {channels}x{size[0]}x{size[1]}x{size[2]}. " | ||||||
|                     channels, size[0], size[1], size[2], len(table) |                 f"Actual length: {len(table)}" | ||||||
|                 ) |  | ||||||
|             ) |             ) | ||||||
|         self.table = table |         self.table = table | ||||||
| 
 | 
 | ||||||
|  | @ -513,12 +512,12 @@ class Color3DLUT(MultibandFilter): | ||||||
| 
 | 
 | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         r = [ |         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), |             "size={:d}x{:d}x{:d}".format(*self.size), | ||||||
|             "channels={:d}".format(self.channels), |             f"channels={self.channels:d}", | ||||||
|         ] |         ] | ||||||
|         if self.mode: |         if self.mode: | ||||||
|             r.append("target_mode={}".format(self.mode)) |             r.append(f"target_mode={self.mode}") | ||||||
|         return "<{}>".format(" ".join(r)) |         return "<{}>".format(" ".join(r)) | ||||||
| 
 | 
 | ||||||
|     def filter(self, image): |     def filter(self, image): | ||||||
|  |  | ||||||
|  | @ -415,7 +415,7 @@ class FreeTypeFont: | ||||||
|         language=None, |         language=None, | ||||||
|         stroke_width=0, |         stroke_width=0, | ||||||
|         *args, |         *args, | ||||||
|         **kwargs |         **kwargs, | ||||||
|     ): |     ): | ||||||
|         """ |         """ | ||||||
|         Create a bitmap for the text. |         Create a bitmap for the text. | ||||||
|  |  | ||||||
|  | @ -41,7 +41,7 @@ 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("unsupported mode: %s" % im1.im.mode) |                 raise ValueError(f"unsupported mode: {im1.im.mode}") | ||||||
|         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"): | ||||||
|  | @ -58,7 +58,7 @@ 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("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) |             _imagingmath.unop(op, out.im.id, im1.im.id) | ||||||
|         else: |         else: | ||||||
|             # binary operation |             # binary operation | ||||||
|  | @ -86,7 +86,7 @@ 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("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) |             _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id) | ||||||
|         return _Operand(out) |         return _Operand(out) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ class ImagePalette: | ||||||
|                 self.dirty = 1 |                 self.dirty = 1 | ||||||
|                 return index |                 return index | ||||||
|         else: |         else: | ||||||
|             raise ValueError("unknown color specifier: %r" % color) |             raise ValueError(f"unknown color specifier: {repr(color)}") | ||||||
| 
 | 
 | ||||||
|     def save(self, fp): |     def save(self, fp): | ||||||
|         """Save palette to text file. |         """Save palette to text file. | ||||||
|  | @ -123,12 +123,12 @@ class ImagePalette: | ||||||
|         if isinstance(fp, str): |         if isinstance(fp, str): | ||||||
|             fp = open(fp, "w") |             fp = open(fp, "w") | ||||||
|         fp.write("# Palette\n") |         fp.write("# Palette\n") | ||||||
|         fp.write("# Mode: %s\n" % self.mode) |         fp.write(f"# Mode: {self.mode}\n") | ||||||
|         for i in range(256): |         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)): |             for j in range(i * len(self.mode), (i + 1) * len(self.mode)): | ||||||
|                 try: |                 try: | ||||||
|                     fp.write(" %d" % self.palette[j]) |                     fp.write(f" {self.palette[j]}") | ||||||
|                 except IndexError: |                 except IndexError: | ||||||
|                     fp.write(" 0") |                     fp.write(" 0") | ||||||
|             fp.write("\n") |             fp.write("\n") | ||||||
|  |  | ||||||
|  | @ -145,7 +145,7 @@ def _toqclass_helper(im): | ||||||
|         data = im.tobytes("raw", "BGRA") |         data = im.tobytes("raw", "BGRA") | ||||||
|         format = QImage.Format_ARGB32 |         format = QImage.Format_ARGB32 | ||||||
|     else: |     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) |     __data = data or align8to32(im.tobytes(), im.size[0], im.mode) | ||||||
|     return {"data": __data, "im": im, "format": format, "colortable": colortable} |     return {"data": __data, "im": im, "format": format, "colortable": colortable} | ||||||
|  |  | ||||||
|  | @ -123,9 +123,9 @@ class WindowsViewer(Viewer): | ||||||
| 
 | 
 | ||||||
|     def get_command(self, file, **options): |     def get_command(self, file, **options): | ||||||
|         return ( |         return ( | ||||||
|             'start "Pillow" /WAIT "%s" ' |             f'start "Pillow" /WAIT "{file}" ' | ||||||
|             "&& ping -n 2 127.0.0.1 >NUL " |             "&& 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 |         # on darwin open returns immediately resulting in the temp | ||||||
|         # file removal while app is opening |         # file removal while app is opening | ||||||
|         command = "open -a Preview.app" |         command = "open -a Preview.app" | ||||||
|         command = "({} {}; sleep 20; rm -f {})&".format( |         command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&" | ||||||
|             command, quote(file), quote(file) |  | ||||||
|         ) |  | ||||||
|         return command |         return command | ||||||
| 
 | 
 | ||||||
|     def show_file(self, file, **options): |     def show_file(self, file, **options): | ||||||
|  | @ -153,7 +151,7 @@ class MacViewer(Viewer): | ||||||
|         fd, path = tempfile.mkstemp() |         fd, path = tempfile.mkstemp() | ||||||
|         with os.fdopen(fd, "w") as f: |         with os.fdopen(fd, "w") as f: | ||||||
|             f.write(file) |             f.write(file) | ||||||
|         with open(path, "r") as f: |         with open(path) as f: | ||||||
|             subprocess.Popen( |             subprocess.Popen( | ||||||
|                 ["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"], |                 ["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"], | ||||||
|                 shell=True, |                 shell=True, | ||||||
|  | @ -173,14 +171,14 @@ class UnixViewer(Viewer): | ||||||
| 
 | 
 | ||||||
|     def get_command(self, file, **options): |     def get_command(self, file, **options): | ||||||
|         command = self.get_command_ex(file, **options)[0] |         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): |     def show_file(self, file, **options): | ||||||
|         """Display given file""" |         """Display given file""" | ||||||
|         fd, path = tempfile.mkstemp() |         fd, path = tempfile.mkstemp() | ||||||
|         with os.fdopen(fd, "w") as f: |         with os.fdopen(fd, "w") as f: | ||||||
|             f.write(file) |             f.write(file) | ||||||
|         with open(path, "r") as f: |         with open(path) as f: | ||||||
|             command = self.get_command_ex(file, **options)[0] |             command = self.get_command_ex(file, **options)[0] | ||||||
|             subprocess.Popen( |             subprocess.Popen( | ||||||
|                 ["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f |                 ["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f | ||||||
|  | @ -216,7 +214,7 @@ class XVViewer(UnixViewer): | ||||||
|         # imagemagick's display command instead. |         # imagemagick's display command instead. | ||||||
|         command = executable = "xv" |         command = executable = "xv" | ||||||
|         if title: |         if title: | ||||||
|             command += " -name %s" % quote(title) |             command += f" -name {quote(title)}" | ||||||
|         return command, executable |         return command, executable | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,7 +41,7 @@ def _pilbitmap_check(): | ||||||
|     if _pilbitmap_ok is None: |     if _pilbitmap_ok is None: | ||||||
|         try: |         try: | ||||||
|             im = Image.new("1", (1, 1)) |             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 |             _pilbitmap_ok = 1 | ||||||
|         except tkinter.TclError: |         except tkinter.TclError: | ||||||
|             _pilbitmap_ok = 0 |             _pilbitmap_ok = 0 | ||||||
|  | @ -229,7 +229,7 @@ class BitmapImage: | ||||||
|         if _pilbitmap_check(): |         if _pilbitmap_check(): | ||||||
|             # fast way (requires the pilbitmap booster patch) |             # fast way (requires the pilbitmap booster patch) | ||||||
|             image.load() |             image.load() | ||||||
|             kw["data"] = "PIL:%d" % image.im.id |             kw["data"] = f"PIL:{image.im.id}" | ||||||
|             self.__im = image  # must keep a reference |             self.__im = image  # must keep a reference | ||||||
|         else: |         else: | ||||||
|             # slow but safe way |             # slow but safe way | ||||||
|  |  | ||||||
|  | @ -198,7 +198,7 @@ def SOF(self, marker): | ||||||
| 
 | 
 | ||||||
|     self.bits = i8(s[0]) |     self.bits = i8(s[0]) | ||||||
|     if self.bits != 8: |     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]) |     self.layers = i8(s[5]) | ||||||
|     if self.layers == 1: |     if self.layers == 1: | ||||||
|  | @ -208,7 +208,7 @@ def SOF(self, marker): | ||||||
|     elif self.layers == 4: |     elif self.layers == 4: | ||||||
|         self.mode = "CMYK" |         self.mode = "CMYK" | ||||||
|     else: |     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]: |     if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]: | ||||||
|         self.info["progressive"] = self.info["progression"] = 1 |         self.info["progressive"] = self.info["progression"] = 1 | ||||||
|  | @ -521,7 +521,7 @@ def _getmp(self): | ||||||
|         rawmpentries = mp[0xB002] |         rawmpentries = mp[0xB002] | ||||||
|         for entrynum in range(0, quant): |         for entrynum in range(0, quant): | ||||||
|             unpackedentry = struct.unpack_from( |             unpackedentry = struct.unpack_from( | ||||||
|                 "{}LLLHH".format(endianness), rawmpentries, entrynum * 16 |                 f"{endianness}LLLHH", rawmpentries, entrynum * 16 | ||||||
|             ) |             ) | ||||||
|             labels = ("Attribute", "Size", "DataOffset", "EntryNo1", "EntryNo2") |             labels = ("Attribute", "Size", "DataOffset", "EntryNo1", "EntryNo2") | ||||||
|             mpentry = dict(zip(labels, unpackedentry)) |             mpentry = dict(zip(labels, unpackedentry)) | ||||||
|  | @ -616,7 +616,7 @@ def _save(im, fp, filename): | ||||||
|     try: |     try: | ||||||
|         rawmode = RAWMODE[im.mode] |         rawmode = RAWMODE[im.mode] | ||||||
|     except KeyError as e: |     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 |     info = im.encoderinfo | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -116,7 +116,7 @@ class MspDecoder(ImageFile.PyDecoder): | ||||||
|         try: |         try: | ||||||
|             self.fd.seek(32) |             self.fd.seek(32) | ||||||
|             rowmap = struct.unpack_from( |             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: |         except struct.error as e: | ||||||
|             raise OSError("Truncated MSP file in row map") from e |             raise OSError("Truncated MSP file in row map") from e | ||||||
|  | @ -145,7 +145,7 @@ class MspDecoder(ImageFile.PyDecoder): | ||||||
|                         idx += runcount |                         idx += runcount | ||||||
| 
 | 
 | ||||||
|             except struct.error as e: |             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)) |         self.set_as_raw(img.getvalue(), ("1", 0, 1)) | ||||||
| 
 | 
 | ||||||
|  | @ -162,7 +162,7 @@ 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("cannot write mode %s as MSP" % im.mode) |         raise OSError(f"cannot write mode {im.mode} as MSP") | ||||||
| 
 | 
 | ||||||
|     # create MSP header |     # create MSP header | ||||||
|     header = [0] * 16 |     header = [0] * 16 | ||||||
|  |  | ||||||
|  | @ -71,10 +71,10 @@ class PSDraw: | ||||||
|         """ |         """ | ||||||
|         if font not in self.isofont: |         if font not in self.isofont: | ||||||
|             # reencode font |             # 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 |             self.isofont[font] = 1 | ||||||
|         # rough |         # 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): |     def line(self, xy0, xy1): | ||||||
|         """ |         """ | ||||||
|  | @ -82,8 +82,7 @@ class PSDraw: | ||||||
|         PostScript point coordinates (72 points per inch, (0, 0) is the lower |         PostScript point coordinates (72 points per inch, (0, 0) is the lower | ||||||
|         left corner of the page). |         left corner of the page). | ||||||
|         """ |         """ | ||||||
|         xy = xy0 + xy1 |         self._fp_write("%d %d %d %d Vl\n" % (*xy0, *xy1)) | ||||||
|         self._fp_write("%d %d %d %d Vl\n" % xy) |  | ||||||
| 
 | 
 | ||||||
|     def rectangle(self, box): |     def rectangle(self, box): | ||||||
|         """ |         """ | ||||||
|  | @ -107,8 +106,7 @@ class PSDraw: | ||||||
|         """ |         """ | ||||||
|         text = "\\(".join(text.split("(")) |         text = "\\(".join(text.split("(")) | ||||||
|         text = "\\)".join(text.split(")")) |         text = "\\)".join(text.split(")")) | ||||||
|         xy = xy + (text,) |         self._fp_write(f"{xy[0]} {xy[1]} M ({text}) S\n") | ||||||
|         self._fp_write("%d %d M (%s) S\n" % xy) |  | ||||||
| 
 | 
 | ||||||
|     def image(self, box, im, dpi=None): |     def image(self, box, im, dpi=None): | ||||||
|         """Draw a PIL image, centered in the given box.""" |         """Draw a PIL image, centered in the given box.""" | ||||||
|  | @ -132,12 +130,12 @@ class PSDraw: | ||||||
|             y = ymax |             y = ymax | ||||||
|         dx = (xmax - x) / 2 + box[0] |         dx = (xmax - x) / 2 + box[0] | ||||||
|         dy = (ymax - y) / 2 + box[1] |         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: |         if (x, y) != im.size: | ||||||
|             # EpsImagePlugin._save prints the image at (0,0,xsize,ysize) |             # EpsImagePlugin._save prints the image at (0,0,xsize,ysize) | ||||||
|             sx = x / im.size[0] |             sx = x / im.size[0] | ||||||
|             sy = y / im.size[1] |             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) |         EpsImagePlugin._save(im, self.fp, None, 0) | ||||||
|         self._fp_write("\ngrestore\n") |         self._fp_write("\ngrestore\n") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -138,7 +138,7 @@ 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("cannot write mode %s as Palm" % im.mode) |             raise OSError(f"cannot write mode {im.mode} as Palm") | ||||||
| 
 | 
 | ||||||
|         # we ignore the palette here |         # we ignore the palette here | ||||||
|         im.mode = "P" |         im.mode = "P" | ||||||
|  | @ -154,7 +154,7 @@ def _save(im, fp, filename): | ||||||
| 
 | 
 | ||||||
|     else: |     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 |     # make sure image data is available | ||||||
|  |  | ||||||
|  | @ -135,7 +135,7 @@ 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("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 |     # bytes per plane | ||||||
|     stride = (im.size[0] * bits + 7) // 8 |     stride = (im.size[0] * bits + 7) // 8 | ||||||
|  |  | ||||||
|  | @ -77,7 +77,7 @@ def _save(im, fp, filename, save_all=False): | ||||||
| 
 | 
 | ||||||
|     existing_pdf.start_writing() |     existing_pdf.start_writing() | ||||||
|     existing_pdf.write_header() |     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 |     # pages | ||||||
|  | @ -130,7 +130,7 @@ def _save(im, fp, filename, save_all=False): | ||||||
|                 bits = 1 |                 bits = 1 | ||||||
|             elif im.mode == "L": |             elif im.mode == "L": | ||||||
|                 filter = "DCTDecode" |                 filter = "DCTDecode" | ||||||
|                 # params = "<< /Predictor 15 /Columns %d >>" % (width-2) |                 # params = f"<< /Predictor 15 /Columns {width-2} >>" | ||||||
|                 colorspace = PdfParser.PdfName("DeviceGray") |                 colorspace = PdfParser.PdfName("DeviceGray") | ||||||
|                 procset = "ImageB"  # grayscale |                 procset = "ImageB"  # grayscale | ||||||
|             elif im.mode == "P": |             elif im.mode == "P": | ||||||
|  | @ -153,7 +153,7 @@ 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("cannot save mode %s" % im.mode) |                 raise ValueError(f"cannot save mode {im.mode}") | ||||||
| 
 | 
 | ||||||
|             # |             # | ||||||
|             # image |             # image | ||||||
|  | @ -175,7 +175,7 @@ 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("unsupported PDF filter (%s)" % filter) |                 raise ValueError(f"unsupported PDF filter ({filter})") | ||||||
| 
 | 
 | ||||||
|             # |             # | ||||||
|             # Get image characteristics |             # Get image characteristics | ||||||
|  |  | ||||||
|  | @ -183,8 +183,8 @@ class XrefTable: | ||||||
|                     this_deleted_object_id = deleted_keys.pop(0) |                     this_deleted_object_id = deleted_keys.pop(0) | ||||||
|                     check_format_condition( |                     check_format_condition( | ||||||
|                         object_id == this_deleted_object_id, |                         object_id == this_deleted_object_id, | ||||||
|                         "expected the next deleted object ID to be %s, instead found %s" |                         f"expected the next deleted object ID to be {object_id}, " | ||||||
|                         % (object_id, this_deleted_object_id), |                         f"instead found {this_deleted_object_id}", | ||||||
|                     ) |                     ) | ||||||
|                     try: |                     try: | ||||||
|                         next_in_linked_list = deleted_keys[0] |                         next_in_linked_list = deleted_keys[0] | ||||||
|  | @ -218,7 +218,7 @@ class PdfName: | ||||||
|         return hash(self.name) |         return hash(self.name) | ||||||
| 
 | 
 | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return "PdfName(%s)" % repr(self.name) |         return f"PdfName({repr(self.name)})" | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def from_pdf_stream(cls, data): |     def from_pdf_stream(cls, data): | ||||||
|  | @ -315,7 +315,7 @@ class PdfStream: | ||||||
|             return zlib.decompress(self.buf, bufsize=int(expected_length)) |             return zlib.decompress(self.buf, bufsize=int(expected_length)) | ||||||
|         else: |         else: | ||||||
|             raise NotImplementedError( |             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") |         self.f.write(b"%PDF-1.4\n") | ||||||
| 
 | 
 | ||||||
|     def write_comment(self, s): |     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): |     def write_catalog(self): | ||||||
|         self.del_root() |         self.del_root() | ||||||
|  | @ -966,9 +966,8 @@ class PdfParser: | ||||||
|         offset, generation = self.xref_table[ref[0]] |         offset, generation = self.xref_table[ref[0]] | ||||||
|         check_format_condition( |         check_format_condition( | ||||||
|             generation == ref[1], |             generation == ref[1], | ||||||
|             "expected to find generation %s for object ID %s in xref table, " |             f"expected to find generation {ref[1]} for object ID {ref[0]} in xref " | ||||||
|             "instead found generation %s at offset %s" |             f"table, instead found generation {generation} at offset {offset}", | ||||||
|             % (ref[1], ref[0], generation, offset), |  | ||||||
|         ) |         ) | ||||||
|         value = self.get_value( |         value = self.get_value( | ||||||
|             self.buf, |             self.buf, | ||||||
|  |  | ||||||
|  | @ -164,7 +164,7 @@ 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("broken PNG file (chunk %s)" % repr(cid)) |                 raise SyntaxError(f"broken PNG file (chunk {repr(cid)})") | ||||||
| 
 | 
 | ||||||
|         return cid, pos, length |         return cid, pos, length | ||||||
| 
 | 
 | ||||||
|  | @ -201,10 +201,12 @@ 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("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: |         except struct.error as e: | ||||||
|             raise SyntaxError( |             raise SyntaxError( | ||||||
|                 "broken PNG file (incomplete checksum in %r)" % cid |                 f"broken PNG file (incomplete checksum in {repr(cid)})" | ||||||
|             ) from e |             ) from e | ||||||
| 
 | 
 | ||||||
|     def crc_skip(self, cid, data): |     def crc_skip(self, cid, data): | ||||||
|  | @ -356,8 +358,8 @@ class PngStream(ChunkStream): | ||||||
|         self.text_memory += chunklen |         self.text_memory += chunklen | ||||||
|         if self.text_memory > MAX_TEXT_MEMORY: |         if self.text_memory > MAX_TEXT_MEMORY: | ||||||
|             raise ValueError( |             raise ValueError( | ||||||
|                 "Too much memory used in text chunks: %s>MAX_TEXT_MEMORY" |                 "Too much memory used in text chunks: " | ||||||
|                 % self.text_memory |                 f"{self.text_memory}>MAX_TEXT_MEMORY" | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|     def save_rewind(self): |     def save_rewind(self): | ||||||
|  | @ -386,9 +388,7 @@ class PngStream(ChunkStream): | ||||||
|         logger.debug("Compression method %s", i8(s[i])) |         logger.debug("Compression method %s", i8(s[i])) | ||||||
|         comp_method = i8(s[i]) |         comp_method = i8(s[i]) | ||||||
|         if comp_method != 0: |         if comp_method != 0: | ||||||
|             raise SyntaxError( |             raise SyntaxError(f"Unknown compression method {comp_method} in iCCP chunk") | ||||||
|                 "Unknown compression method %s in iCCP chunk" % comp_method |  | ||||||
|             ) |  | ||||||
|         try: |         try: | ||||||
|             icc_profile = _safe_zlib_decompress(s[i + 2 :]) |             icc_profile = _safe_zlib_decompress(s[i + 2 :]) | ||||||
|         except ValueError: |         except ValueError: | ||||||
|  | @ -536,9 +536,7 @@ class PngStream(ChunkStream): | ||||||
|         else: |         else: | ||||||
|             comp_method = 0 |             comp_method = 0 | ||||||
|         if comp_method != 0: |         if comp_method != 0: | ||||||
|             raise SyntaxError( |             raise SyntaxError(f"Unknown compression method {comp_method} in zTXt chunk") | ||||||
|                 "Unknown compression method %s in zTXt chunk" % comp_method |  | ||||||
|             ) |  | ||||||
|         try: |         try: | ||||||
|             v = _safe_zlib_decompress(v[1:]) |             v = _safe_zlib_decompress(v[1:]) | ||||||
|         except ValueError: |         except ValueError: | ||||||
|  | @ -800,7 +798,7 @@ class PngImageFile(ImageFile.ImageFile): | ||||||
|             return |             return | ||||||
|         else: |         else: | ||||||
|             if frame != self.__frame + 1: |             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 |         # ensure previous frame was loaded | ||||||
|         self.load() |         self.load() | ||||||
|  | @ -1197,7 +1195,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): | ||||||
|         else: |         else: | ||||||
|             bits = 8 |             bits = 8 | ||||||
|         if bits != 8: |         if bits != 8: | ||||||
|             mode = "%s;%d" % (mode, bits) |             mode = f"{mode};{bits}" | ||||||
| 
 | 
 | ||||||
|     # encoder options |     # encoder options | ||||||
|     im.encoderconfig = ( |     im.encoderconfig = ( | ||||||
|  | @ -1211,7 +1209,7 @@ 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("cannot write mode %s as PNG" % mode) from e |         raise OSError(f"cannot write mode {mode} as PNG") from e | ||||||
| 
 | 
 | ||||||
|     # |     # | ||||||
|     # write minimal PNG file |     # write minimal PNG file | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ class PpmImageFile(ImageFile.ImageFile): | ||||||
|                 # maxgrey |                 # maxgrey | ||||||
|                 if s > 255: |                 if s > 255: | ||||||
|                     if not mode == "L": |                     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: |                     if s < 2 ** 16: | ||||||
|                         self.mode = "I" |                         self.mode = "I" | ||||||
|                         rawmode = "I;16B" |                         rawmode = "I;16B" | ||||||
|  | @ -135,7 +135,7 @@ def _save(im, fp, filename): | ||||||
|     elif im.mode == "RGBA": |     elif im.mode == "RGBA": | ||||||
|         rawmode, head = "RGB", b"P6" |         rawmode, head = "RGB", b"P6" | ||||||
|     else: |     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")) |     fp.write(head + ("\n%d %d\n" % im.size).encode("ascii")) | ||||||
|     if head == b"P6": |     if head == b"P6": | ||||||
|         fp.write(b"255\n") |         fp.write(b"255\n") | ||||||
|  |  | ||||||
|  | @ -160,9 +160,7 @@ 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( |         raise ValueError( | ||||||
|             "incorrect number of bands in SGI write: {} vs {}".format( |             f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}" | ||||||
|                 z, len(im.getbands()) |  | ||||||
|             ) |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     # Minimum Byte value |     # Minimum Byte value | ||||||
|  |  | ||||||
|  | @ -213,7 +213,7 @@ def loadImageSeries(filelist=None): | ||||||
|     imglist = [] |     imglist = [] | ||||||
|     for img in filelist: |     for img in filelist: | ||||||
|         if not os.path.exists(img): |         if not os.path.exists(img): | ||||||
|             print("unable to find %s" % img) |             print(f"unable to find {img}") | ||||||
|             continue |             continue | ||||||
|         try: |         try: | ||||||
|             with Image.open(img) as im: |             with Image.open(img) as im: | ||||||
|  | @ -318,7 +318,7 @@ if __name__ == "__main__": | ||||||
|             # perform some image operation |             # perform some image operation | ||||||
|             im = im.transpose(Image.FLIP_LEFT_RIGHT) |             im = im.transpose(Image.FLIP_LEFT_RIGHT) | ||||||
|             print( |             print( | ||||||
|                 "saving a flipped version of %s as %s " |                 f"saving a flipped version of {os.path.basename(filename)} " | ||||||
|                 % (os.path.basename(filename), outfile) |                 f"as {outfile} " | ||||||
|             ) |             ) | ||||||
|             im.save(outfile, SpiderImageFile.format) |             im.save(outfile, SpiderImageFile.format) | ||||||
|  |  | ||||||
|  | @ -171,7 +171,7 @@ 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("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: |     if "rle" in im.encoderinfo: | ||||||
|         rle = im.encoderinfo["rle"] |         rle = im.encoderinfo["rle"] | ||||||
|  |  | ||||||
|  | @ -466,7 +466,7 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
|         :param prefix: Override the endianness of the file. |         :param prefix: Override the endianness of the file. | ||||||
|         """ |         """ | ||||||
|         if ifh[:4] not in PREFIXES: |         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] |         self._prefix = prefix if prefix is not None else ifh[:2] | ||||||
|         if self._prefix == MM: |         if self._prefix == MM: | ||||||
|             self._endian = ">" |             self._endian = ">" | ||||||
|  | @ -596,8 +596,8 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
|             except ValueError: |             except ValueError: | ||||||
|                 # We've got a builtin tag with 1 expected entry |                 # We've got a builtin tag with 1 expected entry | ||||||
|                 warnings.warn( |                 warnings.warn( | ||||||
|                     "Metadata Warning, tag %s had too many entries: %s, expected 1" |                     f"Metadata Warning, tag {tag} had too many entries: " | ||||||
|                     % (tag, len(values)) |                     f"{len(values)}, expected 1" | ||||||
|                 ) |                 ) | ||||||
|                 dest[tag] = values[0] |                 dest[tag] = values[0] | ||||||
| 
 | 
 | ||||||
|  | @ -732,7 +732,7 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
|         if len(ret) != size: |         if len(ret) != size: | ||||||
|             raise OSError( |             raise OSError( | ||||||
|                 "Corrupt EXIF data.  " |                 "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 |         return ret | ||||||
| 
 | 
 | ||||||
|  | @ -747,18 +747,18 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
| 
 | 
 | ||||||
|                 tagname = TiffTags.lookup(tag).name |                 tagname = TiffTags.lookup(tag).name | ||||||
|                 typname = TYPES.get(typ, "unknown") |                 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: |                 try: | ||||||
|                     unit_size, handler = self._load_dispatch[typ] |                     unit_size, handler = self._load_dispatch[typ] | ||||||
|                 except KeyError: |                 except KeyError: | ||||||
|                     logger.debug(msg + " - unsupported type {}".format(typ)) |                     logger.debug(msg + f" - unsupported type {typ}") | ||||||
|                     continue  # ignore unsupported type |                     continue  # ignore unsupported type | ||||||
|                 size = count * unit_size |                 size = count * unit_size | ||||||
|                 if size > 4: |                 if size > 4: | ||||||
|                     here = fp.tell() |                     here = fp.tell() | ||||||
|                     (offset,) = self._unpack("L", data) |                     (offset,) = self._unpack("L", data) | ||||||
|                     msg += " Tag Location: {} - Data Location: {}".format(here, offset) |                     msg += f" Tag Location: {here} - Data Location: {offset}" | ||||||
|                     fp.seek(offset) |                     fp.seek(offset) | ||||||
|                     data = ImageFile._safe_read(fp, size) |                     data = ImageFile._safe_read(fp, size) | ||||||
|                     fp.seek(here) |                     fp.seek(here) | ||||||
|  | @ -768,8 +768,8 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
|                 if len(data) != size: |                 if len(data) != size: | ||||||
|                     warnings.warn( |                     warnings.warn( | ||||||
|                         "Possibly corrupt EXIF data.  " |                         "Possibly corrupt EXIF data.  " | ||||||
|                         "Expecting to read %d bytes but only got %d." |                         f"Expecting to read {size} bytes but only got {len(data)}." | ||||||
|                         " Skipping tag %s" % (size, len(data), tag) |                         f" Skipping tag {tag}" | ||||||
|                     ) |                     ) | ||||||
|                     logger.debug(msg) |                     logger.debug(msg) | ||||||
|                     continue |                     continue | ||||||
|  | @ -805,7 +805,7 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
|             if tag == STRIPOFFSETS: |             if tag == STRIPOFFSETS: | ||||||
|                 stripoffsets = len(entries) |                 stripoffsets = len(entries) | ||||||
|             typ = self.tagtype.get(tag) |             typ = self.tagtype.get(tag) | ||||||
|             logger.debug("Tag {}, Type: {}, Value: {}".format(tag, typ, value)) |             logger.debug(f"Tag {tag}, Type: {typ}, Value: {value}") | ||||||
|             is_ifd = typ == TiffTags.LONG and isinstance(value, dict) |             is_ifd = typ == TiffTags.LONG and isinstance(value, dict) | ||||||
|             if is_ifd: |             if is_ifd: | ||||||
|                 if self._endian == "<": |                 if self._endian == "<": | ||||||
|  | @ -822,7 +822,7 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
| 
 | 
 | ||||||
|             tagname = TiffTags.lookup(tag).name |             tagname = TiffTags.lookup(tag).name | ||||||
|             typname = "ifd" if is_ifd else TYPES.get(typ, "unknown") |             typname = "ifd" if is_ifd else 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: " + ( |             msg += " - value: " + ( | ||||||
|                 "<table: %d bytes>" % len(data) if len(data) >= 16 else str(values) |                 "<table: %d bytes>" % len(data) if len(data) >= 16 else str(values) | ||||||
|             ) |             ) | ||||||
|  | @ -852,9 +852,7 @@ class ImageFileDirectory_v2(MutableMapping): | ||||||
| 
 | 
 | ||||||
|         # pass 2: write entries to file |         # pass 2: write entries to file | ||||||
|         for tag, typ, count, value, data in entries: |         for tag, typ, count, value, data in entries: | ||||||
|             logger.debug( |             logger.debug(f"{tag} {typ} {count} {repr(value)} {repr(data)}") | ||||||
|                 "{} {} {} {} {}".format(tag, typ, count, repr(value), repr(data)) |  | ||||||
|             ) |  | ||||||
|             result += self._pack("HHL4s", tag, typ, count, value) |             result += self._pack("HHL4s", tag, typ, count, value) | ||||||
| 
 | 
 | ||||||
|         # -- overwrite here for multi-page -- |         # -- overwrite here for multi-page -- | ||||||
|  | @ -1023,8 +1021,8 @@ class TiffImageFile(ImageFile.ImageFile): | ||||||
|         self._n_frames = None |         self._n_frames = None | ||||||
| 
 | 
 | ||||||
|         logger.debug("*** TiffImageFile._open ***") |         logger.debug("*** TiffImageFile._open ***") | ||||||
|         logger.debug("- __first: {}".format(self.__first)) |         logger.debug(f"- __first: {self.__first}") | ||||||
|         logger.debug("- ifh: {!r}".format(ifh))  # Use !r to avoid str(bytes) |         logger.debug(f"- ifh: {repr(ifh)}")  # Use repr to avoid str(bytes) | ||||||
| 
 | 
 | ||||||
|         # and load the first frame |         # and load the first frame | ||||||
|         self._seek(0) |         self._seek(0) | ||||||
|  | @ -1056,8 +1054,8 @@ class TiffImageFile(ImageFile.ImageFile): | ||||||
|             if not self.__next: |             if not self.__next: | ||||||
|                 raise EOFError("no more images in TIFF file") |                 raise EOFError("no more images in TIFF file") | ||||||
|             logger.debug( |             logger.debug( | ||||||
|                 "Seeking to frame %s, on frame %s, __next %s, location: %s" |                 f"Seeking to frame {frame}, on frame {self.__frame}, " | ||||||
|                 % (frame, self.__frame, self.__next, self.fp.tell()) |                 f"__next {self.__next}, location: {self.fp.tell()}" | ||||||
|             ) |             ) | ||||||
|             # reset buffered io handle in case fp |             # reset buffered io handle in case fp | ||||||
|             # was passed to libtiff, invalidating the buffer |             # was passed to libtiff, invalidating the buffer | ||||||
|  | @ -1214,18 +1212,18 @@ class TiffImageFile(ImageFile.ImageFile): | ||||||
|         fillorder = self.tag_v2.get(FILLORDER, 1) |         fillorder = self.tag_v2.get(FILLORDER, 1) | ||||||
| 
 | 
 | ||||||
|         logger.debug("*** Summary ***") |         logger.debug("*** Summary ***") | ||||||
|         logger.debug("- compression: {}".format(self._compression)) |         logger.debug(f"- compression: {self._compression}") | ||||||
|         logger.debug("- photometric_interpretation: {}".format(photo)) |         logger.debug(f"- photometric_interpretation: {photo}") | ||||||
|         logger.debug("- planar_configuration: {}".format(self._planar_configuration)) |         logger.debug(f"- planar_configuration: {self._planar_configuration}") | ||||||
|         logger.debug("- fill_order: {}".format(fillorder)) |         logger.debug(f"- fill_order: {fillorder}") | ||||||
|         logger.debug("- YCbCr subsampling: {}".format(self.tag.get(530))) |         logger.debug(f"- YCbCr subsampling: {self.tag.get(530)}") | ||||||
| 
 | 
 | ||||||
|         # size |         # size | ||||||
|         xsize = int(self.tag_v2.get(IMAGEWIDTH)) |         xsize = int(self.tag_v2.get(IMAGEWIDTH)) | ||||||
|         ysize = int(self.tag_v2.get(IMAGELENGTH)) |         ysize = int(self.tag_v2.get(IMAGELENGTH)) | ||||||
|         self._size = xsize, ysize |         self._size = xsize, ysize | ||||||
| 
 | 
 | ||||||
|         logger.debug("- size: {}".format(self.size)) |         logger.debug(f"- size: {self.size}") | ||||||
| 
 | 
 | ||||||
|         sampleFormat = self.tag_v2.get(SAMPLEFORMAT, (1,)) |         sampleFormat = self.tag_v2.get(SAMPLEFORMAT, (1,)) | ||||||
|         if len(sampleFormat) > 1 and max(sampleFormat) == min(sampleFormat) == 1: |         if len(sampleFormat) > 1 and max(sampleFormat) == min(sampleFormat) == 1: | ||||||
|  | @ -1259,15 +1257,15 @@ class TiffImageFile(ImageFile.ImageFile): | ||||||
|             bps_tuple, |             bps_tuple, | ||||||
|             extra_tuple, |             extra_tuple, | ||||||
|         ) |         ) | ||||||
|         logger.debug("format key: {}".format(key)) |         logger.debug(f"format key: {key}") | ||||||
|         try: |         try: | ||||||
|             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 |             raise SyntaxError("unknown pixel mode") from e | ||||||
| 
 | 
 | ||||||
|         logger.debug("- raw mode: {}".format(rawmode)) |         logger.debug(f"- raw mode: {rawmode}") | ||||||
|         logger.debug("- pil mode: {}".format(self.mode)) |         logger.debug(f"- pil mode: {self.mode}") | ||||||
| 
 | 
 | ||||||
|         self.info["compression"] = self._compression |         self.info["compression"] = self._compression | ||||||
| 
 | 
 | ||||||
|  | @ -1308,7 +1306,7 @@ class TiffImageFile(ImageFile.ImageFile): | ||||||
|             if fillorder == 2: |             if fillorder == 2: | ||||||
|                 # Replace fillorder with fillorder=1 |                 # Replace fillorder with fillorder=1 | ||||||
|                 key = key[:3] + (1,) + key[4:] |                 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 |                 # this should always work, since all the | ||||||
|                 # fillorder==2 modes have a corresponding |                 # fillorder==2 modes have a corresponding | ||||||
|                 # fillorder=1 mode |                 # fillorder=1 mode | ||||||
|  | @ -1432,7 +1430,7 @@ 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("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) |     ifd = ImageFileDirectory_v2(prefix=prefix) | ||||||
| 
 | 
 | ||||||
|  | @ -1629,7 +1627,7 @@ def _save(im, fp, filename): | ||||||
|             if s: |             if s: | ||||||
|                 break |                 break | ||||||
|         if s < 0: |         if s < 0: | ||||||
|             raise OSError("encoder error %d when writing image file" % s) |             raise OSError(f"encoder error {s} when writing image file") | ||||||
| 
 | 
 | ||||||
|     else: |     else: | ||||||
|         offset = ifd.save(fp) |         offset = ifd.save(fp) | ||||||
|  | @ -1795,29 +1793,29 @@ class AppendingTiffWriter: | ||||||
|         self.f.seek(-2, os.SEEK_CUR) |         self.f.seek(-2, os.SEEK_CUR) | ||||||
|         bytesWritten = self.f.write(struct.pack(self.longFmt, value)) |         bytesWritten = self.f.write(struct.pack(self.longFmt, value)) | ||||||
|         if bytesWritten is not None and bytesWritten != 4: |         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): |     def rewriteLastShort(self, value): | ||||||
|         self.f.seek(-2, os.SEEK_CUR) |         self.f.seek(-2, os.SEEK_CUR) | ||||||
|         bytesWritten = self.f.write(struct.pack(self.shortFmt, value)) |         bytesWritten = self.f.write(struct.pack(self.shortFmt, value)) | ||||||
|         if bytesWritten is not None and bytesWritten != 2: |         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): |     def rewriteLastLong(self, value): | ||||||
|         self.f.seek(-4, os.SEEK_CUR) |         self.f.seek(-4, os.SEEK_CUR) | ||||||
|         bytesWritten = self.f.write(struct.pack(self.longFmt, value)) |         bytesWritten = self.f.write(struct.pack(self.longFmt, value)) | ||||||
|         if bytesWritten is not None and bytesWritten != 4: |         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): |     def writeShort(self, value): | ||||||
|         bytesWritten = self.f.write(struct.pack(self.shortFmt, value)) |         bytesWritten = self.f.write(struct.pack(self.shortFmt, value)) | ||||||
|         if bytesWritten is not None and bytesWritten != 2: |         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): |     def writeLong(self, value): | ||||||
|         bytesWritten = self.f.write(struct.pack(self.longFmt, value)) |         bytesWritten = self.f.write(struct.pack(self.longFmt, value)) | ||||||
|         if bytesWritten is not None and bytesWritten != 4: |         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): |     def close(self): | ||||||
|         self.finalize() |         self.finalize() | ||||||
|  |  | ||||||
|  | @ -69,15 +69,15 @@ class XbmImageFile(ImageFile.ImageFile): | ||||||
| def _save(im, fp, filename): | def _save(im, fp, filename): | ||||||
| 
 | 
 | ||||||
|     if im.mode != "1": |     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(f"#define im_width {im.size[0]}\n".encode("ascii")) | ||||||
|     fp.write(("#define im_height %d\n" % im.size[1]).encode("ascii")) |     fp.write(f"#define im_height {im.size[1]}\n".encode("ascii")) | ||||||
| 
 | 
 | ||||||
|     hotspot = im.encoderinfo.get("hotspot") |     hotspot = im.encoderinfo.get("hotspot") | ||||||
|     if hotspot: |     if hotspot: | ||||||
|         fp.write(("#define im_x_hot %d\n" % hotspot[0]).encode("ascii")) |         fp.write(f"#define im_x_hot {hotspot[0]}\n".encode("ascii")) | ||||||
|         fp.write(("#define im_y_hot %d\n" % hotspot[1]).encode("ascii")) |         fp.write(f"#define im_y_hot {hotspot[1]}\n".encode("ascii")) | ||||||
| 
 | 
 | ||||||
|     fp.write(b"static char im_bits[] = {\n") |     fp.write(b"static char im_bits[] = {\n") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ if sys.version_info >= (3, 7): | ||||||
|         if name == "PILLOW_VERSION": |         if name == "PILLOW_VERSION": | ||||||
|             _raise_version_warning() |             _raise_version_warning() | ||||||
|             return __version__ |             return __version__ | ||||||
|         raise AttributeError("module '{}' has no attribute '{}'".format(__name__, name)) |         raise AttributeError(f"module '{__name__}' has no attribute '{name}'") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| else: | else: | ||||||
|  |  | ||||||
|  | @ -1,20 +1,9 @@ | ||||||
| import os | import os | ||||||
| import sys | from pathlib import Path | ||||||
| 
 |  | ||||||
| py36 = sys.version_info[0:2] >= (3, 6) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if py36: | def isPath(f): | ||||||
|     from pathlib import Path |     return isinstance(f, (bytes, str, Path)) | ||||||
| 
 |  | ||||||
|     def isPath(f): |  | ||||||
|         return isinstance(f, (bytes, str, Path)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| else: |  | ||||||
| 
 |  | ||||||
|     def isPath(f): |  | ||||||
|         return isinstance(f, (bytes, str)) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Checks if an object is a string, and that it points to a directory. | # Checks if an object is a string, and that it points to a directory. | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ 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("Unknown module %s" % feature) |         raise ValueError(f"Unknown module {feature}") | ||||||
| 
 | 
 | ||||||
|     module, ver = modules[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. |     :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("Unknown codec %s" % feature) |         raise ValueError(f"Unknown codec {feature}") | ||||||
| 
 | 
 | ||||||
|     codec, lib = codecs[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. |     :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("Unknown feature %s" % feature) |         raise ValueError(f"Unknown feature {feature}") | ||||||
| 
 | 
 | ||||||
|     module, flag, ver = features[feature] |     module, flag, ver = features[feature] | ||||||
| 
 | 
 | ||||||
|  | @ -182,7 +182,7 @@ def check(feature): | ||||||
|         return check_codec(feature) |         return check_codec(feature) | ||||||
|     if feature in features: |     if feature in features: | ||||||
|         return check_feature(feature) |         return check_feature(feature) | ||||||
|     warnings.warn("Unknown feature '%s'." % feature, stacklevel=2) |     warnings.warn(f"Unknown feature '{feature}'.", stacklevel=2) | ||||||
|     return False |     return False | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -230,18 +230,18 @@ def pilinfo(out=None, supported_formats=True): | ||||||
|     Image.init() |     Image.init() | ||||||
| 
 | 
 | ||||||
|     print("-" * 68, file=out) |     print("-" * 68, file=out) | ||||||
|     print("Pillow {}".format(PIL.__version__), file=out) |     print(f"Pillow {PIL.__version__}", file=out) | ||||||
|     py_version = sys.version.splitlines() |     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:]: |     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("-" * 68, file=out) | ||||||
|     print( |     print( | ||||||
|         "Python modules loaded from {}".format(os.path.dirname(Image.__file__)), |         f"Python modules loaded from {os.path.dirname(Image.__file__)}", | ||||||
|         file=out, |         file=out, | ||||||
|     ) |     ) | ||||||
|     print( |     print( | ||||||
|         "Binary modules loaded from {}".format(os.path.dirname(Image.core.__file__)), |         f"Binary modules loaded from {os.path.dirname(Image.core.__file__)}", | ||||||
|         file=out, |         file=out, | ||||||
|     ) |     ) | ||||||
|     print("-" * 68, file=out) |     print("-" * 68, file=out) | ||||||
|  | @ -283,9 +283,9 @@ def pilinfo(out=None, supported_formats=True): | ||||||
|             extensions[i].append(ext) |             extensions[i].append(ext) | ||||||
| 
 | 
 | ||||||
|         for i in sorted(Image.ID): |         for i in sorted(Image.ID): | ||||||
|             line = "{}".format(i) |             line = f"{i}" | ||||||
|             if i in Image.MIME: |             if i in Image.MIME: | ||||||
|                 line = "{} {}".format(line, Image.MIME[i]) |                 line = f"{line} {Image.MIME[i]}" | ||||||
|             print(line, file=out) |             print(line, file=out) | ||||||
| 
 | 
 | ||||||
|             if i in extensions: |             if i in extensions: | ||||||
|  |  | ||||||
|  | @ -417,7 +417,7 @@ def build_dep(name): | ||||||
| 
 | 
 | ||||||
|     for patch_file, patch_list in dep.get("patch", {}).items(): |     for patch_file, patch_list in dep.get("patch", {}).items(): | ||||||
|         patch_file = os.path.join(sources_dir, dir, patch_file.format(**prefs)) |         patch_file = os.path.join(sources_dir, dir, patch_file.format(**prefs)) | ||||||
|         with open(patch_file, "r") as f: |         with open(patch_file) as f: | ||||||
|             text = f.read() |             text = f.read() | ||||||
|         for patch_from, patch_to in patch_list.items(): |         for patch_from, patch_to in patch_list.items(): | ||||||
|             patch_from = patch_from.format(**prefs) |             patch_from = patch_from.format(**prefs) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user