diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 7e2fbf28f..0e0abaf95 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -31,13 +31,13 @@ jobs: language: python dry-run: false - name: Upload New Crash - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() && steps.build.outcome == 'success' with: name: artifacts path: ./out/artifacts - name: Upload Legacy Crash - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: steps.run.outcome == 'success' with: name: crash diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 533ce8cbd..4540fb5af 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,7 +10,7 @@ jobs: name: Lint steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: pre-commit cache uses: actions/cache@v2 @@ -21,7 +21,7 @@ jobs: lint-pre-commit- - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: "3.10" cache: pip diff --git a/.github/workflows/test-docker.yml b/.github/workflows/test-docker.yml index 2762d80c9..f583eae10 100644 --- a/.github/workflows/test-docker.yml +++ b/.github/workflows/test-docker.yml @@ -41,7 +41,7 @@ jobs: name: ${{ matrix.docker }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build system information run: python3 .github/workflows/system-info.py diff --git a/.github/workflows/test-mingw.yml b/.github/workflows/test-mingw.yml index 51bd3a300..7b5cc8a97 100644 --- a/.github/workflows/test-mingw.yml +++ b/.github/workflows/test-mingw.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout Pillow - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up shell run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH diff --git a/.github/workflows/test-valgrind.yml b/.github/workflows/test-valgrind.yml index 4a8966ca8..21a2b469e 100644 --- a/.github/workflows/test-valgrind.yml +++ b/.github/workflows/test-valgrind.yml @@ -28,7 +28,7 @@ jobs: name: ${{ matrix.docker }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build system information run: python3 .github/workflows/system-info.py diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index e2cf44cae..64289cc3a 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -23,17 +23,17 @@ jobs: steps: - name: Checkout Pillow - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Checkout cached dependencies - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: python-pillow/pillow-depends path: winbuild\depends # sets env: pythonLocation - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.architecture }} @@ -156,7 +156,7 @@ jobs: shell: bash - name: Upload errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: errors @@ -182,7 +182,7 @@ jobs: winbuild\\build\\build_pillow.cmd --disable-imagequant bdist_wheel shell: cmd - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: "github.event_name != 'pull_request'" with: name: ${{ steps.wheel.outputs.dist }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 133972881..fef442cfd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,10 +36,10 @@ jobs: name: ${{ matrix.os }} Python ${{ matrix.python-version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} cache: pip @@ -84,7 +84,7 @@ jobs: mkdir -p Tests/errors - name: Upload errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: errors diff --git a/.github/workflows/tidelift.yml b/.github/workflows/tidelift.yml index c2b8b3bda..2e8c9b730 100644 --- a/.github/workflows/tidelift.yml +++ b/.github/workflows/tidelift.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Scan uses: tidelift/alignment-action@main env: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 822fa43ca..b54650565 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: f1d4e742c91dd5179d742b0db9293c4472b765f8 # frozen: 21.12b0 + rev: fc0be6eb1e2a96091e6f64009ee5e9081bf8b6c6 # frozen: 22.1.0 hooks: - id: black args: ["--target-version", "py37"] @@ -19,7 +19,7 @@ repos: - id: yesqa - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: 3592548bbd98528887eeed63486cf6c9bae00b98 # frozen: v1.1.10 + rev: ca52c4245639abd55c970e6bbbca95cab3de22d8 # frozen: v1.1.13 hooks: - id: remove-tabs exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.opt$) diff --git a/Tests/32bit_segfault_check.py b/Tests/32bit_segfault_check.py index e19cdf7a9..2ff7f908f 100755 --- a/Tests/32bit_segfault_check.py +++ b/Tests/32bit_segfault_check.py @@ -4,5 +4,5 @@ import sys from PIL import Image -if sys.maxsize < 2 ** 32: +if sys.maxsize < 2**32: im = Image.new("L", (999999, 999999), 0) diff --git a/Tests/check_large_memory.py b/Tests/check_large_memory.py index c191ffc1e..d98f4a694 100644 --- a/Tests/check_large_memory.py +++ b/Tests/check_large_memory.py @@ -23,7 +23,7 @@ YDIM = 32769 XDIM = 48000 -pytestmark = pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="requires 64-bit system") +pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system") def _write_png(tmp_path, xdim, ydim): diff --git a/Tests/check_large_memory_numpy.py b/Tests/check_large_memory_numpy.py index 70ae6d230..24cb1f722 100644 --- a/Tests/check_large_memory_numpy.py +++ b/Tests/check_large_memory_numpy.py @@ -19,7 +19,7 @@ YDIM = 32769 XDIM = 48000 -pytestmark = pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="requires 64-bit system") +pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system") def _write_png(tmp_path, xdim, ydim): diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py index 6c52d25a4..385192a3c 100644 --- a/Tests/test_core_resources.py +++ b/Tests/test_core_resources.py @@ -110,9 +110,9 @@ class TestCoreMemory: with pytest.raises(ValueError): Image.core.set_blocks_max(-1) - if sys.maxsize < 2 ** 32: + if sys.maxsize < 2**32: with pytest.raises(ValueError): - Image.core.set_blocks_max(2 ** 29) + Image.core.set_blocks_max(2**29) @pytest.mark.skipif(is_pypy(), reason="Images not collected") def test_set_blocks_max_stats(self): diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 2f46ed77e..58447122e 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -196,6 +196,13 @@ def test__accept_false(): assert not output +def test_invalid_file(): + invalid_file = "Tests/images/flower.jpg" + + with pytest.raises(SyntaxError): + DdsImagePlugin.DdsImageFile(invalid_file) + + def test_short_header(): """Check a short header""" with open(TEST_FILE_DXT5, "rb") as f: diff --git a/Tests/test_file_ftex.py b/Tests/test_file_ftex.py index 5447dc740..cae20fa46 100644 --- a/Tests/test_file_ftex.py +++ b/Tests/test_file_ftex.py @@ -16,6 +16,13 @@ def test_load_dxt1(): assert_image_similar(im, target.convert("RGBA"), 15) +def test_invalid_file(): + invalid_file = "Tests/images/flower.jpg" + + with pytest.raises(SyntaxError): + FtexImagePlugin.FtexImageFile(invalid_file) + + def test_constants_deprecation(): for enum, prefix in { FtexImagePlugin.Format: "FORMAT_", diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 53ed2520a..a9337f4fc 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -218,7 +218,7 @@ class TestFileLibTiff(LibTiffTestCase): values = { 2: "test", 3: 1, - 4: 2 ** 20, + 4: 2**20, 5: TiffImagePlugin.IFDRational(100, 1), 12: 1.05, } @@ -1019,7 +1019,7 @@ class TestFileLibTiff(LibTiffTestCase): im = hopper("RGB").resize((256, 256)) out = str(tmp_path / "temp.tif") - TiffImagePlugin.STRIP_SIZE = 2 ** 18 + TiffImagePlugin.STRIP_SIZE = 2**18 try: im.save(out, compression="tiff_adobe_deflate") diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index 2213af5aa..056295516 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -258,7 +258,7 @@ def test_ifd_unsigned_rational(tmp_path): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() - max_long = 2 ** 32 - 1 + max_long = 2**32 - 1 # 4 bytes unsigned long numerator = max_long @@ -290,8 +290,8 @@ def test_ifd_signed_rational(tmp_path): info = TiffImagePlugin.ImageFileDirectory_v2() # pair of 4 byte signed longs - numerator = 2 ** 31 - 1 - denominator = -(2 ** 31) + numerator = 2**31 - 1 + denominator = -(2**31) info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) @@ -302,8 +302,8 @@ def test_ifd_signed_rational(tmp_path): assert numerator == reloaded.tag_v2[37380].numerator assert denominator == reloaded.tag_v2[37380].denominator - numerator = -(2 ** 31) - denominator = 2 ** 31 - 1 + numerator = -(2**31) + denominator = 2**31 - 1 info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) @@ -315,7 +315,7 @@ def test_ifd_signed_rational(tmp_path): assert denominator == reloaded.tag_v2[37380].denominator # out of bounds of 4 byte signed long - numerator = -(2 ** 31) - 1 + numerator = -(2**31) - 1 denominator = 1 info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) @@ -324,7 +324,7 @@ def test_ifd_signed_rational(tmp_path): im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: - assert 2 ** 31 - 1 == reloaded.tag_v2[37380].numerator + assert 2**31 - 1 == reloaded.tag_v2[37380].numerator assert -1 == reloaded.tag_v2[37380].denominator diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 55897f1eb..051119378 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -128,7 +128,7 @@ class TestFileWebp: self._roundtrip(tmp_path, "P", 50.0) - @pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="Requires 64-bit system") + @pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system") def test_write_encoding_error_message(self, tmp_path): temp_file = str(tmp_path / "temp.webp") im = Image.new("RGB", (15000, 15000)) diff --git a/Tests/test_file_xbm.py b/Tests/test_file_xbm.py index 487920a92..9c54c6755 100644 --- a/Tests/test_file_xbm.py +++ b/Tests/test_file_xbm.py @@ -2,7 +2,7 @@ from io import BytesIO import pytest -from PIL import Image +from PIL import Image, XbmImagePlugin from .helper import hopper @@ -63,6 +63,13 @@ def test_open_filename_with_underscore(): assert im.size == (128, 128) +def test_invalid_file(): + invalid_file = "Tests/images/flower.jpg" + + with pytest.raises(SyntaxError): + XbmImagePlugin.XbmImageFile(invalid_file) + + def test_save_wrong_mode(tmp_path): im = hopper() out = str(tmp_path / "temp.xbm") diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 7b3036979..97321143d 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -205,10 +205,10 @@ class TestImageGetPixel(AccessTest): # see https://github.com/python-pillow/Pillow/issues/452 # pixelaccess is using signed int* instead of uint* for mode in ("I;16", "I;16B"): - self.check(mode, 2 ** 15 - 1) - self.check(mode, 2 ** 15) - self.check(mode, 2 ** 15 + 1) - self.check(mode, 2 ** 16 - 1) + self.check(mode, 2**15 - 1) + self.check(mode, 2**15) + self.check(mode, 2**15 + 1) + self.check(mode, 2**16 - 1) def test_p_putpixel_rgb_rgba(self): for color in [(255, 0, 0), (255, 0, 0, 255)]: @@ -386,7 +386,7 @@ class TestImagePutPixelError(AccessTest): def test_putpixel_overflow_error(self, mode): im = hopper(mode) with pytest.raises(OverflowError): - im.putpixel((0, 0), 2 ** 80) + im.putpixel((0, 0), 2**80) def test_putpixel_unrecognized_mode(self): im = hopper("BGR;15") diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py index 7e4bbaaec..3d60e52a2 100644 --- a/Tests/test_image_putdata.py +++ b/Tests/test_image_putdata.py @@ -38,7 +38,7 @@ def test_long_integers(): assert put(0xFFFFFFFF) == (255, 255, 255, 255) assert put(-1) == (255, 255, 255, 255) assert put(-1) == (255, 255, 255, 255) - if sys.maxsize > 2 ** 32: + if sys.maxsize > 2**32: assert put(sys.maxsize) == (255, 255, 255, 255) else: assert put(sys.maxsize) == (255, 255, 255, 127) diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index e0093739c..66a72a90e 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -303,7 +303,7 @@ def test_extended_information(): def assert_truncated_tuple_equal(tup1, tup2, digits=10): # Helper function to reduce precision of tuples of floats # recursively and then check equality. - power = 10 ** digits + power = 10**digits def truncate_tuple(tuple_or_float): return tuple( diff --git a/Tests/test_imageqt.py b/Tests/test_imageqt.py index 930907939..a42240d49 100644 --- a/Tests/test_imageqt.py +++ b/Tests/test_imageqt.py @@ -32,10 +32,10 @@ def test_rgb(): def checkrgb(r, g, b): val = ImageQt.rgb(r, g, b) - val = val % 2 ** 24 # drop the alpha + val = val % 2**24 # drop the alpha assert val >> 16 == r - assert ((val >> 8) % 2 ** 8) == g - assert val % 2 ** 8 == b + assert ((val >> 8) % 2**8) == g + assert val % 2**8 == b checkrgb(0, 0, 0) checkrgb(255, 0, 0) diff --git a/Tests/test_imagestat.py b/Tests/test_imagestat.py index 9474ff6f9..5717fe150 100644 --- a/Tests/test_imagestat.py +++ b/Tests/test_imagestat.py @@ -51,8 +51,8 @@ def test_constant(): st = ImageStat.Stat(im) assert st.extrema[0] == (128, 128) - assert st.sum[0] == 128 ** 3 - assert st.sum2[0] == 128 ** 4 + assert st.sum[0] == 128**3 + assert st.sum2[0] == 128**4 assert st.mean[0] == 128 assert st.median[0] == 128 assert st.rms[0] == 128 diff --git a/Tests/test_map.py b/Tests/test_map.py index 42f3447eb..d816bddaf 100644 --- a/Tests/test_map.py +++ b/Tests/test_map.py @@ -36,7 +36,7 @@ def test_tobytes(): Image.MAX_IMAGE_PIXELS = max_pixels -@pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="Requires 64-bit system") +@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system") def test_ysize(): numpy = pytest.importorskip("numpy", reason="NumPy not installed") diff --git a/Tests/test_pdfparser.py b/Tests/test_pdfparser.py index 2d428e95f..ea9b33dfc 100644 --- a/Tests/test_pdfparser.py +++ b/Tests/test_pdfparser.py @@ -115,6 +115,6 @@ def test_pdf_repr(): assert pdf_repr(True) == b"true" assert pdf_repr(False) == b"false" assert pdf_repr(None) == b"null" - assert pdf_repr(b"a)/b\\(c") == br"(a\)/b\\\(c)" + assert pdf_repr(b"a)/b\\(c") == rb"(a\)/b\\\(c)" assert pdf_repr([123, True, {"a": PdfName(b"b")}]) == b"[ 123 true <<\n/a /b\n>> ]" assert pdf_repr(PdfBinary(b"\x90\x1F\xA0")) == b"<901FA0>" diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index 272409416..29fefba16 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -210,7 +210,9 @@ class DdsImageFile(ImageFile.ImageFile): format_description = "DirectDraw Surface" def _open(self): - magic, header_size = struct.unpack(" (.*)" + expr = rf".*\({abi_type}.*\) => (.*)" env = dict(os.environ) env["LC_ALL"] = "C" env["LANG"] = "C" diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 7a7ad386c..72e40b05f 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -102,7 +102,7 @@ class BmpImageFile(ImageFile.ImageFile): file_info["height"] = ( i32(header_data, 4) if not file_info["y_flip"] - else 2 ** 32 - i32(header_data, 4) + else 2**32 - i32(header_data, 4) ) file_info["planes"] = i16(header_data, 8) file_info["bits"] = i16(header_data, 10) @@ -322,7 +322,7 @@ def _save(im, fp, filename, bitmap_header=True): if bitmap_header: offset = 14 + header + colors * 4 file_size = offset + image - if file_size > 2 ** 32 - 1: + if file_size > 2**32 - 1: raise ValueError("File size is too large for the BMP format") fp.write( b"BM" # file type (magic) diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 260924fca..3a04bdb5d 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -111,7 +111,9 @@ class DdsImageFile(ImageFile.ImageFile): format_description = "DirectDraw Surface" def _open(self): - magic, header_size = struct.unpack("= 6 and i16(prefix, 4) in [0xAF11, 0xAF12] + return ( + len(prefix) >= 6 + and i16(prefix, 4) in [0xAF11, 0xAF12] + and i16(prefix, 14) in [0, 3] # flags + ) ## @@ -44,11 +48,7 @@ class FliImageFile(ImageFile.ImageFile): # HEAD s = self.fp.read(128) - if not ( - _accept(s) - and i16(s, 14) in [0, 3] # flags - and s[20:22] == b"\x00\x00" # reserved - ): + if not (_accept(s) and s[20:22] == b"\x00\x00"): raise SyntaxError("not an FLI/FLC file") # frames diff --git a/src/PIL/FtexImagePlugin.py b/src/PIL/FtexImagePlugin.py index 8629dcf64..55d28e1ff 100644 --- a/src/PIL/FtexImagePlugin.py +++ b/src/PIL/FtexImagePlugin.py @@ -94,7 +94,8 @@ class FtexImageFile(ImageFile.ImageFile): format_description = "Texture File Format (IW2:EOC)" def _open(self): - struct.unpack(" 100: raise SyntaxError("bad palette file") diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 069aff96b..c22bfe0ed 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -167,7 +167,7 @@ class IcnsFile: self.dct = dct = {} self.fobj = fobj sig, filesize = nextheader(fobj) - if sig != MAGIC: + if not _accept(sig): raise SyntaxError("not an icns file") i = HEADERSIZE while i < filesize: diff --git a/src/PIL/ImImagePlugin.py b/src/PIL/ImImagePlugin.py index 1dfc808c4..f7e690b35 100644 --- a/src/PIL/ImImagePlugin.py +++ b/src/PIL/ImImagePlugin.py @@ -100,7 +100,7 @@ for i in range(2, 33): # -------------------------------------------------------------------- # Read IM directory -split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$") +split = re.compile(rb"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$") def number(s): diff --git a/src/PIL/Image.py b/src/PIL/Image.py index c9265b5ab..4b8d2c750 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -1492,11 +1492,12 @@ class Image: def histogram(self, mask=None, extrema=None): """ - Returns a histogram for the image. The histogram is returned as - a list of pixel counts, one for each pixel value in the source - image. If the image has more than one band, the histograms for - all bands are concatenated (for example, the histogram for an - "RGB" image contains 768 values). + Returns a histogram for the image. The histogram is returned as a + list of pixel counts, one for each pixel value in the source + image. Counts are grouped into 256 bins for each band, even if + the image has more than 8 bits per band. If the image has more + than one band, the histograms for all bands are concatenated (for + example, the histogram for an "RGB" image contains 768 values). A bilevel image (mode "1") is treated as a greyscale ("L") image by this method. diff --git a/src/PIL/ImageStat.py b/src/PIL/ImageStat.py index 50bafc972..ef4a1d633 100644 --- a/src/PIL/ImageStat.py +++ b/src/PIL/ImageStat.py @@ -91,7 +91,7 @@ class Stat: for i in range(0, len(self.h), 256): sum2 = 0.0 for j in range(256): - sum2 += (j ** 2) * float(self.h[i + j]) + sum2 += (j**2) * float(self.h[i + j]) v.append(sum2) return v diff --git a/src/PIL/ImtImagePlugin.py b/src/PIL/ImtImagePlugin.py index 21ffd7475..5790acdaf 100644 --- a/src/PIL/ImtImagePlugin.py +++ b/src/PIL/ImtImagePlugin.py @@ -22,7 +22,7 @@ from . import Image, ImageFile # # -------------------------------------------------------------------- -field = re.compile(br"([a-z]*) ([^ \r\n]*)") +field = re.compile(rb"([a-z]*) ([^ \r\n]*)") ## diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index cc7980278..4f4ee8f55 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -132,7 +132,7 @@ def _res_to_dpi(num, denom, exp): calculated as (num / denom) * 10^exp and stored in dots per meter, to floating-point dots per inch.""" if denom != 0: - return (254 * num * (10 ** exp)) / (10000 * denom) + return (254 * num * (10**exp)) / (10000 * denom) def _parse_jp2_header(fp): diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 6ac9c7a7c..9aa0fd6fa 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -576,42 +576,42 @@ class PdfParser: self.xref_table[reference.object_id] = (offset, 0) return reference - delimiter = br"[][()<>{}/%]" - delimiter_or_ws = br"[][()<>{}/%\000\011\012\014\015\040]" - whitespace = br"[\000\011\012\014\015\040]" - whitespace_or_hex = br"[\000\011\012\014\015\0400-9a-fA-F]" + delimiter = rb"[][()<>{}/%]" + delimiter_or_ws = rb"[][()<>{}/%\000\011\012\014\015\040]" + whitespace = rb"[\000\011\012\014\015\040]" + whitespace_or_hex = rb"[\000\011\012\014\015\0400-9a-fA-F]" whitespace_optional = whitespace + b"*" whitespace_mandatory = whitespace + b"+" # No "\012" aka "\n" or "\015" aka "\r": - whitespace_optional_no_nl = br"[\000\011\014\040]*" - newline_only = br"[\r\n]+" + whitespace_optional_no_nl = rb"[\000\011\014\040]*" + newline_only = rb"[\r\n]+" newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl re_trailer_end = re.compile( whitespace_mandatory - + br"trailer" + + rb"trailer" + whitespace_optional - + br"\<\<(.*\>\>)" + + rb"\<\<(.*\>\>)" + newline - + br"startxref" + + rb"startxref" + newline - + br"([0-9]+)" + + rb"([0-9]+)" + newline - + br"%%EOF" + + rb"%%EOF" + whitespace_optional - + br"$", + + rb"$", re.DOTALL, ) re_trailer_prev = re.compile( whitespace_optional - + br"trailer" + + rb"trailer" + whitespace_optional - + br"\<\<(.*?\>\>)" + + rb"\<\<(.*?\>\>)" + newline - + br"startxref" + + rb"startxref" + newline - + br"([0-9]+)" + + rb"([0-9]+)" + newline - + br"%%EOF" + + rb"%%EOF" + whitespace_optional, re.DOTALL, ) @@ -655,12 +655,12 @@ class PdfParser: re_whitespace_optional = re.compile(whitespace_optional) re_name = re.compile( whitespace_optional - + br"/([!-$&'*-.0-;=?-Z\\^-z|~]+)(?=" + + rb"/([!-$&'*-.0-;=?-Z\\^-z|~]+)(?=" + delimiter_or_ws - + br")" + + rb")" ) - re_dict_start = re.compile(whitespace_optional + br"\<\<") - re_dict_end = re.compile(whitespace_optional + br"\>\>" + whitespace_optional) + re_dict_start = re.compile(whitespace_optional + rb"\<\<") + re_dict_end = re.compile(whitespace_optional + rb"\>\>" + whitespace_optional) @classmethod def interpret_trailer(cls, trailer_data): @@ -689,7 +689,7 @@ class PdfParser: ) return trailer - re_hashes_in_name = re.compile(br"([^#]*)(#([0-9a-fA-F]{2}))?") + re_hashes_in_name = re.compile(rb"([^#]*)(#([0-9a-fA-F]{2}))?") @classmethod def interpret_name(cls, raw, as_text=False): @@ -704,53 +704,53 @@ class PdfParser: else: return bytes(name) - re_null = re.compile(whitespace_optional + br"null(?=" + delimiter_or_ws + br")") - re_true = re.compile(whitespace_optional + br"true(?=" + delimiter_or_ws + br")") - re_false = re.compile(whitespace_optional + br"false(?=" + delimiter_or_ws + br")") + re_null = re.compile(whitespace_optional + rb"null(?=" + delimiter_or_ws + rb")") + re_true = re.compile(whitespace_optional + rb"true(?=" + delimiter_or_ws + rb")") + re_false = re.compile(whitespace_optional + rb"false(?=" + delimiter_or_ws + rb")") re_int = re.compile( - whitespace_optional + br"([-+]?[0-9]+)(?=" + delimiter_or_ws + br")" + whitespace_optional + rb"([-+]?[0-9]+)(?=" + delimiter_or_ws + rb")" ) re_real = re.compile( whitespace_optional - + br"([-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+))(?=" + + rb"([-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+))(?=" + delimiter_or_ws - + br")" + + rb")" ) - re_array_start = re.compile(whitespace_optional + br"\[") - re_array_end = re.compile(whitespace_optional + br"]") + re_array_start = re.compile(whitespace_optional + rb"\[") + re_array_end = re.compile(whitespace_optional + rb"]") re_string_hex = re.compile( - whitespace_optional + br"\<(" + whitespace_or_hex + br"*)\>" + whitespace_optional + rb"\<(" + whitespace_or_hex + rb"*)\>" ) - re_string_lit = re.compile(whitespace_optional + br"\(") + re_string_lit = re.compile(whitespace_optional + rb"\(") re_indirect_reference = re.compile( whitespace_optional - + br"([-+]?[0-9]+)" + + rb"([-+]?[0-9]+)" + whitespace_mandatory - + br"([-+]?[0-9]+)" + + rb"([-+]?[0-9]+)" + whitespace_mandatory - + br"R(?=" + + rb"R(?=" + delimiter_or_ws - + br")" + + rb")" ) re_indirect_def_start = re.compile( whitespace_optional - + br"([-+]?[0-9]+)" + + rb"([-+]?[0-9]+)" + whitespace_mandatory - + br"([-+]?[0-9]+)" + + rb"([-+]?[0-9]+)" + whitespace_mandatory - + br"obj(?=" + + rb"obj(?=" + delimiter_or_ws - + br")" + + rb")" ) re_indirect_def_end = re.compile( - whitespace_optional + br"endobj(?=" + delimiter_or_ws + br")" + whitespace_optional + rb"endobj(?=" + delimiter_or_ws + rb")" ) re_comment = re.compile( - br"(" + whitespace_optional + br"%[^\r\n]*" + newline + br")*" + rb"(" + whitespace_optional + rb"%[^\r\n]*" + newline + rb")*" ) - re_stream_start = re.compile(whitespace_optional + br"stream\r?\n") + re_stream_start = re.compile(whitespace_optional + rb"stream\r?\n") re_stream_end = re.compile( - whitespace_optional + br"endstream(?=" + delimiter_or_ws + br")" + whitespace_optional + rb"endstream(?=" + delimiter_or_ws + rb")" ) @classmethod @@ -876,7 +876,7 @@ class PdfParser: raise PdfFormatError("unrecognized object: " + repr(data[offset : offset + 32])) re_lit_str_token = re.compile( - br"(\\[nrtbf()\\])|(\\[0-9]{1,3})|(\\(\r\n|\r|\n))|(\r\n|\r|\n)|(\()|(\))" + rb"(\\[nrtbf()\\])|(\\[0-9]{1,3})|(\\(\r\n|\r|\n))|(\r\n|\r|\n)|(\()|(\))" ) escaped_chars = { b"n": b"\n", @@ -922,16 +922,16 @@ class PdfParser: offset = m.end() raise PdfFormatError("unfinished literal string") - re_xref_section_start = re.compile(whitespace_optional + br"xref" + newline) + re_xref_section_start = re.compile(whitespace_optional + rb"xref" + newline) re_xref_subsection_start = re.compile( whitespace_optional - + br"([0-9]+)" + + rb"([0-9]+)" + whitespace_mandatory - + br"([0-9]+)" + + rb"([0-9]+)" + whitespace_optional + newline_only ) - re_xref_entry = re.compile(br"([0-9]{10}) ([0-9]{5}) ([fn])( \r| \n|\r\n)") + re_xref_entry = re.compile(rb"([0-9]{10}) ([0-9]{5}) ([fn])( \r| \n|\r\n)") def read_xref_table(self, xref_section_offset): subsection_found = False diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index cd0a3e0e0..53525e22e 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -48,7 +48,7 @@ from ._binary import o32be as o32 logger = logging.getLogger(__name__) -is_cid = re.compile(br"\w\w\w\w").match +is_cid = re.compile(rb"\w\w\w\w").match _MAGIC = b"\211PNG\r\n\032\n" diff --git a/src/PIL/PpmImagePlugin.py b/src/PIL/PpmImagePlugin.py index 412376982..9a5cac7d0 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -120,7 +120,7 @@ class PpmImageFile(ImageFile.ImageFile): if maxval > 255: if not mode == "L": raise ValueError(f"Too many colors for band: {maxval}") - if maxval < 2 ** 16: + if maxval < 2**16: self.mode = "I" rawmode = "I;16B" else: @@ -310,7 +310,7 @@ def _save(im, fp, filename): elif im.mode == "L": rawmode, head = "L", b"P5" elif im.mode == "I": - if im.getextrema()[1] < 2 ** 16: + if im.getextrema()[1] < 2**16: rawmode, head = "I;16B", b"P5" else: rawmode, head = "I;32B", b"P5" diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 35ff1c1bb..1d9a4881b 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -493,7 +493,7 @@ class ImageFileDirectory_v2(MutableMapping): endianness. :param prefix: Override the endianness of the file. """ - if ifh[:4] not in PREFIXES: + if not _accept(ifh): raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)") self._prefix = prefix if prefix is not None else ifh[:2] if self._prefix == MM: @@ -577,9 +577,9 @@ class ImageFileDirectory_v2(MutableMapping): else TiffTags.SIGNED_RATIONAL ) elif all(isinstance(v, int) for v in values): - if all(0 <= v < 2 ** 16 for v in values): + if all(0 <= v < 2**16 for v in values): self.tagtype[tag] = TiffTags.SHORT - elif all(-(2 ** 15) < v < 2 ** 15 for v in values): + elif all(-(2**15) < v < 2**15 for v in values): self.tagtype[tag] = TiffTags.SIGNED_SHORT else: self.tagtype[tag] = ( @@ -734,7 +734,7 @@ class ImageFileDirectory_v2(MutableMapping): @_register_writer(5) def write_rational(self, *values): return b"".join( - self._pack("2L", *_limit_rational(frac, 2 ** 32 - 1)) for frac in values + self._pack("2L", *_limit_rational(frac, 2**32 - 1)) for frac in values ) @_register_loader(7, 1) @@ -757,7 +757,7 @@ class ImageFileDirectory_v2(MutableMapping): @_register_writer(10) def write_signed_rational(self, *values): return b"".join( - self._pack("2l", *_limit_signed_rational(frac, 2 ** 31 - 1, -(2 ** 31))) + self._pack("2l", *_limit_signed_rational(frac, 2**31 - 1, -(2**31))) for frac in values ) @@ -1670,7 +1670,7 @@ def _save(im, fp, filename): strip_byte_counts = 1 if stride == 0 else stride * rows_per_strip strips_per_image = (im.size[1] + rows_per_strip - 1) // rows_per_strip ifd[ROWSPERSTRIP] = rows_per_strip - if strip_byte_counts >= 2 ** 16: + if strip_byte_counts >= 2**16: ifd.tagtype[STRIPBYTECOUNTS] = TiffTags.LONG ifd[STRIPBYTECOUNTS] = (strip_byte_counts,) * (strips_per_image - 1) + ( stride * im.size[1] - strip_byte_counts * (strips_per_image - 1), diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index c32cc52f8..2f54cdebb 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -21,7 +21,6 @@ from . import Image, ImageFile from ._binary import i16le as word -from ._binary import i32le as dword from ._binary import si16le as short from ._binary import si32le as _long @@ -112,7 +111,7 @@ class WmfStubImageFile(ImageFile.StubImageFile): if s[22:26] != b"\x01\x00\t\x00": raise SyntaxError("Unsupported WMF file format") - elif dword(s) == 1 and s[40:44] == b" EMF": + elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF": # enhanced metafile # get bounding box diff --git a/src/PIL/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index 644cfb39b..15379ce80 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -25,7 +25,7 @@ from . import Image, ImageFile # XBM header xbm_head = re.compile( - br"\s*#define[ \t]+.*_width[ \t]+(?P[0-9]+)[\r\n]+" + rb"\s*#define[ \t]+.*_width[ \t]+(?P[0-9]+)[\r\n]+" b"#define[ \t]+.*_height[ \t]+(?P[0-9]+)[\r\n]+" b"(?P" b"#define[ \t]+[^_]*_x_hot[ \t]+(?P[0-9]+)[\r\n]+" @@ -52,18 +52,19 @@ class XbmImageFile(ImageFile.ImageFile): m = xbm_head.match(self.fp.read(512)) - if m: + if not m: + raise SyntaxError("not a XBM file") - xsize = int(m.group("width")) - ysize = int(m.group("height")) + xsize = int(m.group("width")) + ysize = int(m.group("height")) - if m.group("hotspot"): - self.info["hotspot"] = (int(m.group("xhot")), int(m.group("yhot"))) + if m.group("hotspot"): + self.info["hotspot"] = (int(m.group("xhot")), int(m.group("yhot"))) - self.mode = "1" - self._size = xsize, ysize + self.mode = "1" + self._size = xsize, ysize - self.tile = [("xbm", (0, 0) + self.size, m.end(), None)] + self.tile = [("xbm", (0, 0) + self.size, m.end(), None)] def _save(im, fp, filename): diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index 3ff1aeca0..31a3fbab7 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -464,7 +464,7 @@ def build_dep_all(): if dep_name in disabled: continue script = build_dep(dep_name) - lines.append(fr'cmd.exe /c "{{build_dir}}\{script}"') + lines.append(rf'cmd.exe /c "{{build_dir}}\{script}"') lines.append("if errorlevel 1 echo Build failed! && exit /B 1") lines.append("@echo All Pillow dependencies built successfully!") write_script("build_dep_all.cmd", lines)