Skip to content

Commit

Permalink
Merge branch 'main' into imagefont
Browse files Browse the repository at this point in the history
radarhere authored Feb 29, 2024
2 parents 83433d8 + bebf038 commit cc094ca
Showing 66 changed files with 500 additions and 296 deletions.
1 change: 1 addition & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ init:
# Uncomment previous line to get RDP access during the build.

environment:
COVERAGE_CORE: sysmon
EXECUTABLE: python.exe
TEST_OPTIONS:
DEPLOY: YES
1 change: 1 addition & 0 deletions .ci/requirements-mypy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mypy==1.7.1
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
tidelift: "pypi/Pillow"
tidelift: "pypi/pillow"
2 changes: 2 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -7,10 +7,12 @@ on:
paths:
- ".github/workflows/docs.yml"
- "docs/**"
- "src/PIL/**"
pull_request:
paths:
- ".github/workflows/docs.yml"
- "docs/**"
- "src/PIL/**"
workflow_dispatch:

permissions:
3 changes: 3 additions & 0 deletions .github/workflows/test-cygwin.yml
Original file line number Diff line number Diff line change
@@ -26,6 +26,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
COVERAGE_CORE: sysmon

jobs:
build:
runs-on: windows-latest
3 changes: 3 additions & 0 deletions .github/workflows/test-mingw.yml
Original file line number Diff line number Diff line change
@@ -26,6 +26,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
COVERAGE_CORE: sysmon

jobs:
build:
runs-on: windows-latest
17 changes: 14 additions & 3 deletions .github/workflows/test-windows.yml
Original file line number Diff line number Diff line change
@@ -26,13 +26,16 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
COVERAGE_CORE: sysmon

jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13.0-alpha.3"]

timeout-minutes: 30

@@ -66,8 +69,16 @@ jobs:
- name: Print build system information
run: python3 .github/workflows/system-info.py

- name: python3 -m pip install pytest pytest-cov pytest-timeout defusedxml olefile pyroma
run: python3 -m pip install pytest pytest-cov pytest-timeout defusedxml olefile pyroma
- name: Install Python dependencies
run: >
python3 -m pip install
coverage>=7.4.2
defusedxml
olefile
pyroma
pytest
pytest-cov
pytest-timeout
- name: Install dependencies
id: install
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ concurrency:
cancel-in-progress: true

env:
COVERAGE_CORE: sysmon
FORCE_COLOR: 1

jobs:
7 changes: 5 additions & 2 deletions .github/workflows/wheels-dependencies.sh
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ FREETYPE_VERSION=2.13.2
HARFBUZZ_VERSION=8.3.0
LIBPNG_VERSION=1.6.40
JPEGTURBO_VERSION=3.0.1
OPENJPEG_VERSION=2.5.0
OPENJPEG_VERSION=2.5.2
XZ_VERSION=5.4.5
TIFF_VERSION=4.6.0
LCMS2_VERSION=2.16
@@ -40,7 +40,7 @@ BROTLI_VERSION=1.1.0

if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "x86_64" ]]; then
function build_openjpeg {
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-2.5.0.tar.gz)
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-${OPENJPEG_VERSION}.tar.gz)
(cd $out_dir \
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
&& make install)
@@ -93,6 +93,9 @@ function build {
done
fi
build_openjpeg
if [ -f /usr/local/lib64/libopenjp2.so ]; then
cp /usr/local/lib64/libopenjp2.so /usr/local/lib
fi

ORIGINAL_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -O3 -DNDEBUG"
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -5,6 +5,12 @@ Changelog (Pillow)
10.3.0 (unreleased)
-------------------

- Release GIL while calling ``WebPAnimDecoderGetNext`` #7782
[evanmiller, radarhere]

- Fixed reading FLI/FLC images with a prefix chunk #7804
[twolife]

- Update wl-paste handling and return None for some errors in grabclipboard() on Linux #7745
[nik012003, radarhere]

5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ As of 2019, Pillow development is
src="https://zenodo.org/badge/17549/python-pillow/Pillow.svg"></a>
<a href="https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=badge"><img
alt="Tidelift"
src="https://tidelift.com/badges/package/pypi/Pillow?style=flat"></a>
src="https://tidelift.com/badges/package/pypi/pillow?style=flat"></a>
<a href="https://pypi.org/project/pillow/"><img
alt="Newest PyPI version"
src="https://img.shields.io/pypi/v/pillow.svg"></a>
@@ -82,9 +82,6 @@ As of 2019, Pillow development is
<a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img
alt="Join the chat at https://gitter.im/python-pillow/Pillow"
src="https://badges.gitter.im/python-pillow/Pillow.svg"></a>
<a href="https://twitter.com/PythonPillow"><img
alt="Follow on https://twitter.com/PythonPillow"
src="https://img.shields.io/badge/tweet-on%20Twitter-00aced.svg"></a>
<a href="https://fosstodon.org/@pillow"><img
alt="Follow on https://fosstodon.org/@pillow"
src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg"
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ Released as needed privately to individual vendors for critical security-related

## Publicize Release

* [ ] Announce release availability via [Twitter](https://twitter.com/pythonpillow) and [Mastodon](https://fosstodon.org/@pillow) e.g. https://twitter.com/PythonPillow/status/1013789184354603010
* [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321

## Documentation

Binary file added Tests/images/2422.flc
Binary file not shown.
6 changes: 3 additions & 3 deletions Tests/test_deprecate.py
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
),
],
)
def test_version(version, expected) -> None:
def test_version(version: int | None, expected: str) -> None:
with pytest.warns(DeprecationWarning, match=expected):
_deprecate.deprecate("Old thing", version, "new thing")

@@ -46,7 +46,7 @@ def test_unknown_version() -> None:
),
],
)
def test_old_version(deprecated, plural, expected) -> None:
def test_old_version(deprecated: str, plural: bool, expected: str) -> None:
expected = r""
with pytest.raises(RuntimeError, match=expected):
_deprecate.deprecate(deprecated, 1, plural=plural)
@@ -76,7 +76,7 @@ def test_replacement_and_action() -> None:
"Upgrade to new thing.",
],
)
def test_action(action) -> None:
def test_action(action: str) -> None:
expected = (
r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
r"Upgrade to new thing\."
7 changes: 4 additions & 3 deletions Tests/test_features.py
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

import io
import re
from typing import Callable

import pytest

@@ -29,7 +30,7 @@ def test_version() -> None:
# Check the correctness of the convenience function
# and the format of version numbers

def test(name, function) -> None:
def test(name: str, function: Callable[[str], bool]) -> None:
version = features.version(name)
if not features.check(name):
assert version is None
@@ -73,12 +74,12 @@ def test_libimagequant_version() -> None:


@pytest.mark.parametrize("feature", features.modules)
def test_check_modules(feature) -> None:
def test_check_modules(feature: str) -> None:
assert features.check_module(feature) in [True, False]


@pytest.mark.parametrize("feature", features.codecs)
def test_check_codecs(feature) -> None:
def test_check_codecs(feature: str) -> None:
assert features.check_codec(feature) in [True, False]


2 changes: 1 addition & 1 deletion Tests/test_file_blp.py
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ def test_save(tmp_path: Path) -> None:
"Tests/images/timeout-ef9112a065e7183fa7faa2e18929b03e44ee16bf.blp",
],
)
def test_crashes(test_file) -> None:
def test_crashes(test_file: str) -> None:
with open(test_file, "rb") as f:
with Image.open(f) as im:
with pytest.raises(OSError):
4 changes: 2 additions & 2 deletions Tests/test_file_bmp.py
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@


def test_sanity(tmp_path: Path) -> None:
def roundtrip(im) -> None:
def roundtrip(im: Image.Image) -> None:
outfile = str(tmp_path / "temp.bmp")

im.save(outfile, "BMP")
@@ -194,7 +194,7 @@ def test_rle4() -> None:
("Tests/images/bmp/g/pal8rle.bmp", 1064),
),
)
def test_rle8_eof(file_name, length) -> None:
def test_rle8_eof(file_name: str, length: int) -> None:
with open(file_name, "rb") as fp:
data = fp.read(length)
with Image.open(io.BytesIO(data)) as im:
25 changes: 23 additions & 2 deletions Tests/test_file_fli.py
Original file line number Diff line number Diff line change
@@ -4,17 +4,20 @@

import pytest

from PIL import FliImagePlugin, Image
from PIL import FliImagePlugin, Image, ImageFile

from .helper import assert_image_equal, assert_image_equal_tofile, is_pypy

# created as an export of a palette image from Gimp2.6
# save as...-> hopper.fli, default options.
static_test_file = "Tests/images/hopper.fli"

# From https://samples.libav.org/fli-flc/
# From https://samples.ffmpeg.org/fli-flc/
animated_test_file = "Tests/images/a.fli"

# From https://samples.ffmpeg.org/fli-flc/
animated_test_file_with_prefix_chunk = "Tests/images/2422.flc"


def test_sanity() -> None:
with Image.open(static_test_file) as im:
@@ -32,6 +35,24 @@ def test_sanity() -> None:
assert im.is_animated


def test_prefix_chunk() -> None:
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
with Image.open(animated_test_file_with_prefix_chunk) as im:
assert im.mode == "P"
assert im.size == (320, 200)
assert im.format == "FLI"
assert im.info["duration"] == 171
assert im.is_animated

palette = im.getpalette()
assert palette[3:6] == [255, 255, 255]
assert palette[381:384] == [204, 204, 12]
assert palette[765:] == [252, 0, 0]
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False


@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file() -> None:
def open() -> None:
2 changes: 1 addition & 1 deletion Tests/test_file_ico.py
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ def test_different_bit_depths(tmp_path: Path) -> None:


@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB", "RGBA"))
def test_save_to_bytes_bmp(mode) -> None:
def test_save_to_bytes_bmp(mode: str) -> None:
output = io.BytesIO()
im = hopper(mode)
im.save(output, "ico", bitmap_format="bmp", sizes=[(32, 32), (64, 64)])
2 changes: 1 addition & 1 deletion Tests/test_file_im.py
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ def test_eoferror() -> None:


@pytest.mark.parametrize("mode", ("RGB", "P", "PA"))
def test_roundtrip(mode, tmp_path: Path) -> None:
def test_roundtrip(mode: str, tmp_path: Path) -> None:
out = str(tmp_path / "temp.im")
im = hopper(mode)
im.save(out)
2 changes: 1 addition & 1 deletion Tests/test_file_iptc.py
Original file line number Diff line number Diff line change
@@ -98,7 +98,7 @@ def test_i() -> None:
assert ret == 97


def test_dump(monkeypatch) -> None:
def test_dump(monkeypatch: pytest.MonkeyPatch) -> None:
# Arrange
c = b"abc"
# Temporarily redirect stdout
2 changes: 1 addition & 1 deletion Tests/test_file_msp.py
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ def test_open_windows_v1() -> None:
assert isinstance(im, MspImagePlugin.MspImageFile)


def _assert_file_image_equal(source_path, target_path) -> None:
def _assert_file_image_equal(source_path: str, target_path: str) -> None:
with Image.open(source_path) as im:
assert_image_equal_tofile(im, target_path)

6 changes: 3 additions & 3 deletions Tests/test_file_pcx.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
from .helper import assert_image_equal, hopper


def _roundtrip(tmp_path: Path, im) -> None:
def _roundtrip(tmp_path: Path, im: Image.Image) -> None:
f = str(tmp_path / "temp.pcx")
im.save(f)
with Image.open(f) as im2:
@@ -44,7 +44,7 @@ def test_invalid_file() -> None:


@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB"))
def test_odd(tmp_path: Path, mode) -> None:
def test_odd(tmp_path: Path, mode: str) -> None:
# See issue #523, odd sized images should have a stride that's even.
# Not that ImageMagick or GIMP write PCX that way.
# We were not handling properly.
@@ -89,7 +89,7 @@ def test_large_count(tmp_path: Path) -> None:
_roundtrip(tmp_path, im)


def _test_buffer_overflow(tmp_path: Path, im, size: int = 1024) -> None:
def _test_buffer_overflow(tmp_path: Path, im: Image.Image, size: int = 1024) -> None:
_last = ImageFile.MAXBLOCK
ImageFile.MAXBLOCK = size
try:
Loading

0 comments on commit cc094ca

Please sign in to comment.