Merge branch 'main' into plainPPM

This commit is contained in:
Andrew Murray 2022-03-06 13:38:19 +11:00 committed by GitHub
commit d20f39d02e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 179 additions and 142 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }}

View File

@ -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

View File

@ -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:

View File

@ -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$)

View File

@ -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)

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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:

View File

@ -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_",

View File

@ -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")

View File

@ -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

View File

@ -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))

View File

@ -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")

View File

@ -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")

View File

@ -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)

View File

@ -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(

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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>"

View File

@ -210,7 +210,9 @@ class DdsImageFile(ImageFile.ImageFile):
format_description = "DirectDraw Surface"
def _open(self):
magic, header_size = struct.unpack("<II", self.fp.read(8))
if not _accept(self.fp.read(4)):
raise SyntaxError("not a DDS file")
(header_size,) = struct.unpack("<I", self.fp.read(4))
if header_size != 124:
raise OSError(f"Unsupported header size {repr(header_size)}")
header_bytes = self.fp.read(header_size - 4)

View File

@ -14,6 +14,16 @@ for a region of an image.
statistics. You can also pass in a previously calculated histogram.
:param image: A PIL image, or a precalculated histogram.
.. note::
For a PIL image, calculations rely on the
:py:meth:`~PIL.Image.Image.histogram` method. The pixel counts are
grouped into 256 bins, even if the image has more than 8 bits per
channel. So ``I`` and ``F`` mode images have a maximum ``mean``,
``median`` and ``rms`` of 255, and cannot have an ``extrema`` maximum
of more than 255.
:param mask: An optional mask.
.. py:attribute:: extrema

View File

@ -167,7 +167,7 @@ def _find_library_dirs_ldconfig():
# Assuming GLIBC's ldconfig (with option -p)
# Alpine Linux uses musl that can't print cache
args = ["/sbin/ldconfig", "-p"]
expr = fr".*\({abi_type}.*\) => (.*)"
expr = rf".*\({abi_type}.*\) => (.*)"
env = dict(os.environ)
env["LC_ALL"] = "C"
env["LANG"] = "C"

View File

@ -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)

View File

@ -111,7 +111,9 @@ class DdsImageFile(ImageFile.ImageFile):
format_description = "DirectDraw Surface"
def _open(self):
magic, header_size = struct.unpack("<II", self.fp.read(8))
if not _accept(self.fp.read(4)):
raise SyntaxError("not a DDS file")
(header_size,) = struct.unpack("<I", self.fp.read(4))
if header_size != 124:
raise OSError(f"Unsupported header size {repr(header_size)}")
header_bytes = self.fp.read(header_size - 4)

View File

@ -26,7 +26,11 @@ from ._binary import o8
def _accept(prefix):
return len(prefix) >= 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

View File

@ -94,7 +94,8 @@ class FtexImageFile(ImageFile.ImageFile):
format_description = "Texture File Format (IW2:EOC)"
def _open(self):
struct.unpack("<I", self.fp.read(4)) # magic
if not _accept(self.fp.read(4)):
raise SyntaxError("not an FTEX file")
struct.unpack("<i", self.fp.read(4)) # version
self._size = struct.unpack("<2i", self.fp.read(8))
mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8))

View File

@ -43,9 +43,9 @@ class GbrImageFile(ImageFile.ImageFile):
def _open(self):
header_size = i32(self.fp.read(4))
version = i32(self.fp.read(4))
if header_size < 20:
raise SyntaxError("not a GIMP brush")
version = i32(self.fp.read(4))
if version not in (1, 2):
raise SyntaxError(f"Unsupported GIMP brush version: {version}")

View File

@ -38,7 +38,7 @@ class GimpPaletteFile:
break
# skip fields and comment lines
if re.match(br"\w+:|#", s):
if re.match(rb"\w+:|#", s):
continue
if len(s) > 100:
raise SyntaxError("bad palette file")

View File

@ -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:

View File

@ -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):

View File

@ -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.

View File

@ -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

View File

@ -22,7 +22,7 @@ from . import Image, ImageFile
#
# --------------------------------------------------------------------
field = re.compile(br"([a-z]*) ([^ \r\n]*)")
field = re.compile(rb"([a-z]*) ([^ \r\n]*)")
##

View File

@ -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):

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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),

View File

@ -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

View File

@ -25,7 +25,7 @@ from . import Image, ImageFile
# XBM header
xbm_head = re.compile(
br"\s*#define[ \t]+.*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
rb"\s*#define[ \t]+.*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
b"#define[ \t]+.*_height[ \t]+(?P<height>[0-9]+)[\r\n]+"
b"(?P<hotspot>"
b"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[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):

View File

@ -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)