Skip to content

Commit

Permalink
Merge branch 'main' into test_lists_and_tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed May 6, 2023
2 parents 886ed7a + e3990f6 commit 3de4735
Show file tree
Hide file tree
Showing 46 changed files with 369 additions and 162 deletions.
4 changes: 2 additions & 2 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ install:
- 7z x pillow-test-images.zip -oc:\
- mv c:\pillow-depends-main c:\pillow-depends
- xcopy /S /Y c:\test-images-main\* c:\pillow\tests\images
- 7z x ..\pillow-depends\nasm-2.15.05-win64.zip -oc:\
- 7z x ..\pillow-depends\nasm-2.16.01-win64.zip -oc:\
- choco install ghostscript --version=10.0.0.20230317
- path c:\nasm-2.15.05;C:\Program Files\gs\gs10.00.0\bin;%PATH%
- path c:\nasm-2.16.01;C:\Program Files\gs\gs10.00.0\bin;%PATH%
- cd c:\pillow\winbuild\
- ps: |
c:\python38\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/test-cygwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
uses: actions/checkout@v3

- name: Install Cygwin
uses: cygwin/cygwin-install-action@v3
uses: cygwin/cygwin-install-action@v4
with:
platform: x86_64
packages: >
Expand Down Expand Up @@ -84,6 +84,10 @@ jobs:
restore-keys: |
${{ runner.os }}-cygwin-pip3.${{ matrix.python-minor-version }}-
- name: Select Python version
run: |
ln -sf c:/cygwin/bin/python3.${{ matrix.python-minor-version }} c:/cygwin/bin/python3
- name: Build system information
run: |
dash.exe -c "python3 .github/workflows/system-info.py"
Expand All @@ -95,7 +99,7 @@ jobs:
- name: Install a different NumPy
shell: dash.exe -l "{0}"
run: |
python3 -m pip install -U 'numpy!=1.21.*'
python3 -m pip install -U numpy
- name: Build
shell: bash.exe -eo pipefail -o igncr "{0}"
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/test-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ jobs:
centos-stream-8-amd64,
centos-stream-9-amd64,
debian-11-bullseye-x86,
fedora-36-amd64,
fedora-37-amd64,
fedora-38-amd64,
gentoo,
ubuntu-18.04-bionic-amd64,
ubuntu-20.04-focal-amd64,
ubuntu-22.04-jammy-amd64,
]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-mingw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
pushd depends && ./install_extra_test_images.sh && popd
- name: Build Pillow
run: CFLAGS="-coverage" python3 -m pip install --global-option="build_ext" .
run: SETUPTOOLS_USE_DISTUTILS="stdlib" CFLAGS="-coverage" python3 -m pip install --global-option="build_ext" .

- name: Test Pillow
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ jobs:
- name: Install dependencies
id: install
run: |
7z x winbuild\depends\nasm-2.15.05-win64.zip "-o$env:RUNNER_WORKSPACE\"
echo "$env:RUNNER_WORKSPACE\nasm-2.15.05" >> $env:GITHUB_PATH
7z x winbuild\depends\nasm-2.16.01-win64.zip "-o$env:RUNNER_WORKSPACE\"
echo "$env:RUNNER_WORKSPACE\nasm-2.16.01" >> $env:GITHUB_PATH
choco install ghostscript --version=10.0.0.20230317
echo "C:\Program Files\gs\gs10.00.0\bin" >> $env:GITHUB_PATH
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ repos:
- id: sphinx-lint

- repo: https://github.com/tox-dev/tox-ini-fmt
rev: 1.0.0
rev: 1.3.0
hooks:
- id: tox-ini-fmt

Expand Down
2 changes: 2 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
version: 2

formats: all

build:
os: ubuntu-22.04
tools:
Expand Down
24 changes: 24 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ Changelog (Pillow)
10.0.0 (unreleased)
-------------------

- Support reading signed 8-bit TIFF images #7111
[radarhere]

- Added width argument to ImageDraw regular_polygon #7132
[radarhere]

- Support I mode for ImageFilter.BuiltinFilter #7108
[radarhere]

- Raise error from stderr of Linux ImageGrab.grabclipboard() command #7112
[radarhere]

- Added unpacker from I;16B to I;16 #7125
[radarhere]

- Support float font sizes #7107
[radarhere]

- Use later value for duplicate xref entries in PdfParser #7102
[radarhere]

- Load before getting size in __getstate__ #7105
[bigcat88, radarhere]

- Fixed type handling for include and lib directories #7069
[adisbladis, radarhere]

Expand Down
Binary file added Tests/images/8bit.s.tif
Binary file not shown.
Binary file added Tests/images/duplicate_xref_entry.pdf
Binary file not shown.
Binary file added Tests/images/hopper_emboss_I.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/hopper_emboss_more_I.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/imagedraw_triangle_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions Tests/test_file_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ def test_save_unsupported_mode(self, tmp_path):
with pytest.raises(OSError):
im.save(outfile)

def test_8bit_s(self):
with Image.open("Tests/images/8bit.s.tif") as im:
im.load()
assert im.mode == "L"
assert im.getpixel((50, 50)) == 184

def test_little_endian(self):
with Image.open("Tests/images/16bit.cropped.tif") as im:
assert im.getpixel((0, 0)) == 480
Expand Down
9 changes: 8 additions & 1 deletion Tests/test_image_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from PIL import Image

from .helper import hopper
from .helper import hopper, skip_unless_feature


@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
Expand Down Expand Up @@ -42,3 +42,10 @@ def test_copy_zero():
out = im.copy()
assert out.mode == im.mode
assert out.size == im.size


@skip_unless_feature("libtiff")
def test_deepcopy():
with Image.open("Tests/images/g4_orientation_5.tif") as im:
out = copy.deepcopy(im)
assert out.size == (590, 88)
43 changes: 26 additions & 17 deletions Tests/test_image_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@
ImageFilter.UnsharpMask(10),
),
)
@pytest.mark.parametrize("mode", ("L", "RGB", "CMYK"))
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
def test_sanity(filter_to_apply, mode):
im = hopper(mode)
out = im.filter(filter_to_apply)
assert out.mode == im.mode
assert out.size == im.size
if mode != "I" or isinstance(filter_to_apply, ImageFilter.BuiltinFilter):
out = im.filter(filter_to_apply)
assert out.mode == im.mode
assert out.size == im.size


@pytest.mark.parametrize("mode", ("L", "RGB", "CMYK"))
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
def test_sanity_error(mode):
with pytest.raises(TypeError):
im = hopper(mode)
Expand Down Expand Up @@ -130,10 +131,12 @@ def test_kernel_not_enough_coefficients():
ImageFilter.Kernel((3, 3), (0, 0))


@pytest.mark.parametrize("mode", ("L", "LA", "RGB", "CMYK"))
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
def test_consistency_3x3(mode):
with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss.bmp") as reference:
reference_name = "hopper_emboss"
reference_name += "_I.png" if mode == "I" else ".bmp"
with Image.open("Tests/images/" + reference_name) as reference:
kernel = ImageFilter.Kernel(
(3, 3),
# fmt: off
Expand All @@ -146,16 +149,20 @@ def test_consistency_3x3(mode):
source = source.split() * 2
reference = reference.split() * 2

assert_image_equal(
Image.merge(mode, source[: len(mode)]).filter(kernel),
Image.merge(mode, reference[: len(mode)]),
)
if mode == "I":
source = source[0].convert(mode)
else:
source = Image.merge(mode, source[: len(mode)])
reference = Image.merge(mode, reference[: len(mode)])
assert_image_equal(source.filter(kernel), reference)


@pytest.mark.parametrize("mode", ("L", "LA", "RGB", "CMYK"))
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
def test_consistency_5x5(mode):
with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss_more.bmp") as reference:
reference_name = "hopper_emboss_more"
reference_name += "_I.png" if mode == "I" else ".bmp"
with Image.open("Tests/images/" + reference_name) as reference:
kernel = ImageFilter.Kernel(
(5, 5),
# fmt: off
Expand All @@ -170,10 +177,12 @@ def test_consistency_5x5(mode):
source = source.split() * 2
reference = reference.split() * 2

assert_image_equal(
Image.merge(mode, source[: len(mode)]).filter(kernel),
Image.merge(mode, reference[: len(mode)]),
)
if mode == "I":
source = source[0].convert(mode)
else:
source = Image.merge(mode, source[: len(mode)])
reference = Image.merge(mode, reference[: len(mode)])
assert_image_equal(source.filter(kernel), reference)


def test_invalid_box_blur_filter():
Expand Down
20 changes: 10 additions & 10 deletions Tests/test_imagedraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -1380,20 +1380,20 @@ def test_same_color_outline(bbox):


@pytest.mark.parametrize(
"n_sides, rotation, polygon_name",
[(4, 0, "square"), (8, 0, "regular_octagon"), (4, 45, "square")],
"n_sides, polygon_name, args",
[
(4, "square", {}),
(8, "regular_octagon", {}),
(4, "square_rotate_45", {"rotation": 45}),
(3, "triangle_width", {"width": 5, "outline": "yellow"}),
],
)
def test_draw_regular_polygon(n_sides, rotation, polygon_name):
def test_draw_regular_polygon(n_sides, polygon_name, args):
im = Image.new("RGBA", size=(W, H), color=(255, 0, 0, 0))
filename_base = f"Tests/images/imagedraw_{polygon_name}"
filename = (
f"{filename_base}.png"
if rotation == 0
else f"{filename_base}_rotate_{rotation}.png"
)
filename = f"Tests/images/imagedraw_{polygon_name}.png"
draw = ImageDraw.Draw(im)
bounding_circle = ((W // 2, H // 2), 25)
draw.regular_polygon(bounding_circle, n_sides, rotation=rotation, fill="red")
draw.regular_polygon(bounding_circle, n_sides, fill="red", **args)
assert_image_equal_tofile(im, filename)


Expand Down
10 changes: 10 additions & 0 deletions Tests/test_imagefont.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ def test_getlength(
assert length == length_raqm


def test_float_size():
lengths = []
for size in (48, 48.5, 49):
f = ImageFont.truetype(
"Tests/fonts/NotoSans-Regular.ttf", size, layout_engine=layout_engine
)
lengths.append(f.getlength("text"))
assert lengths[0] != lengths[1] != lengths[2]


def test_render_multiline(font):
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
Expand Down
77 changes: 47 additions & 30 deletions Tests/test_imagepath.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_path():
(6.0, 7.0),
(8.0, 9.0),
]
assert p.tolist(1) == [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
assert p.tolist(True) == [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

assert p.getbbox() == (0.0, 1.0, 8.0, 9.0)

Expand All @@ -38,48 +38,65 @@ def test_path():
p.transform((1, 0, 1, 0, 1, 1))
assert list(p) == [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)]

# alternative constructors
p = ImagePath.Path([0, 1])
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path([0.0, 1.0])
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path([0, 1])
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path([(0, 1)])
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path(p)
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path(p.tolist(0))
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path(p.tolist(1))
assert list(p) == [(0.0, 1.0)]
p = ImagePath.Path(array.array("f", [0, 1]))
assert list(p) == [(0.0, 1.0)]

arr = array.array("f", [0, 1])
p = ImagePath.Path(arr.tobytes())
assert list(p) == [(0.0, 1.0)]
@pytest.mark.parametrize(
"coords",
(
(0, 1),
[0, 1],
(0.0, 1.0),
[0.0, 1.0],
((0, 1),),
[(0, 1)],
((0.0, 1.0),),
[(0.0, 1.0)],
array.array("f", [0, 1]),
array.array("f", [0, 1]).tobytes(),
ImagePath.Path((0, 1)),
),
)
def test_path_constructors(coords):
# Arrange / Act
p = ImagePath.Path(coords)

# Assert
assert list(p) == [(0.0, 1.0)]

def test_invalid_coords():
# Arrange
coords = ["a", "b"]

# Act / Assert
@pytest.mark.parametrize(
"coords",
(
("a", "b"),
([0, 1],),
[[0, 1]],
([0.0, 1.0],),
[[0.0, 1.0]],
),
)
def test_invalid_path_constructors(coords):
# Act
with pytest.raises(ValueError) as e:
ImagePath.Path(coords)

# Assert
assert str(e.value) == "incorrect coordinate type"


def test_path_odd_number_of_coordinates():
# Arrange
coords = [0]

# Act / Assert
@pytest.mark.parametrize(
"coords",
(
(0,),
[0],
(0, 1, 2),
[0, 1, 2],
),
)
def test_path_odd_number_of_coordinates(coords):
# Act
with pytest.raises(ValueError) as e:
ImagePath.Path(coords)

# Assert
assert str(e.value) == "wrong number of coordinates"


Expand Down
1 change: 1 addition & 0 deletions Tests/test_lib_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@ def test_F_float(self):

def test_I16(self):
self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605)
self.assert_unpack("I;16", "I;16B", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16L", "I;16L", 2, 0x0201, 0x0403, 0x0605)
self.assert_unpack("I;16", "I;12", 2, 0x0010, 0x0203, 0x0040)
Expand Down
Loading

0 comments on commit 3de4735

Please sign in to comment.