Skip to content

Commit

Permalink
Merge branch 'main' into image_equals
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere authored Jul 19, 2024
2 parents 900d807 + 011da4b commit ebd1eed
Show file tree
Hide file tree
Showing 76 changed files with 1,395 additions and 779 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
BasedOnStyle: Google
AlwaysBreakAfterReturnType: All
AllowShortIfStatementsOnASingleLine: false
AlignAfterOpenBracket: AlwaysBreak
AlignAfterOpenBracket: BlockIndent
BinPackArguments: false
BinPackParameters: false
BreakBeforeBraces: Attach
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/cifuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ concurrency:

jobs:
Fuzzing:
# Disabled until google/oss-fuzz#11419 upgrades Python to 3.9+
if: false
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
name: Wheels

on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# │ │ │ │ │
- cron: "42 1 * * 0,3"
push:
paths:
- ".ci/requirements-cibw.txt"
Expand Down Expand Up @@ -33,6 +41,7 @@ env:

jobs:
build-1-QEMU-emulated-wheels:
if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch'
name: aarch64 ${{ matrix.python-version }} ${{ matrix.spec }}
runs-on: ubuntu-latest
strategy:
Expand Down Expand Up @@ -227,6 +236,7 @@ jobs:
path: winbuild\build\bin\fribidi*

sdist:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -245,6 +255,23 @@ jobs:
name: dist-sdist
path: dist/*.tar.gz

scientific-python-nightly-wheels-publish:
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
needs: [build-2-native-wheels, windows]
runs-on: ubuntu-latest
name: Upload wheels to scientific-python-nightly-wheels
steps:
- uses: actions/download-artifact@v4
with:
pattern: dist-*
path: dist
merge-multiple: true
- name: Upload wheels to scientific-python-nightly-wheels
uses: scientific-python/upload-nightly-action@b67d7fcc0396e1128a474d1ab2b48aa94680f9fc # 0.5.0
with:
artifacts_path: dist
anaconda_nightly_upload_token: ${{ secrets.ANACONDA_ORG_UPLOAD_TOKEN }}

pypi-publish:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
needs: [build-1-QEMU-emulated-wheels, build-2-native-wheels, windows, sdist]
Expand Down
12 changes: 12 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ Changelog (Pillow)
11.0.0 (unreleased)
-------------------

- Deprecate ImageMath lambda_eval and unsafe_eval options argument #8242
[radarhere]

- Changed ContainerIO to subclass IO #8240
[radarhere]

- Move away from APIs that use borrowed references under the free-threaded build #8216
[hugovk, lysnikolaou]

- Allow size argument to resize() to be a NumPy array #8201
[radarhere]

- Drop support for Python 3.8 #8183
[hugovk, radarhere]

Expand Down
91 changes: 80 additions & 11 deletions Tests/test_file_container.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

from typing import Literal

import pytest

from PIL import ContainerIO, Image
Expand All @@ -23,6 +21,13 @@ def test_isatty() -> None:
assert container.isatty() is False


def test_seekable() -> None:
with hopper() as im:
container = ContainerIO.ContainerIO(im, 0, 0)

assert container.seekable() is True


@pytest.mark.parametrize(
"mode, expected_position",
(
Expand All @@ -31,7 +36,7 @@ def test_isatty() -> None:
(2, 100),
),
)
def test_seek_mode(mode: Literal[0, 1, 2], expected_position: int) -> None:
def test_seek_mode(mode: int, expected_position: int) -> None:
# Arrange
with open(TEST_FILE, "rb") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
Expand All @@ -44,14 +49,22 @@ def test_seek_mode(mode: Literal[0, 1, 2], expected_position: int) -> None:
assert container.tell() == expected_position


@pytest.mark.parametrize("bytesmode", (True, False))
def test_readable(bytesmode: bool) -> None:
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)

assert container.readable() is True


@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n0(bytesmode: bool) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)

# Act
container.seek(81)
assert container.seek(81) == 81
data = container.read()

# Assert
Expand All @@ -67,7 +80,7 @@ def test_read_n(bytesmode: bool) -> None:
container = ContainerIO.ContainerIO(fh, 22, 100)

# Act
container.seek(81)
assert container.seek(81) == 81
data = container.read(3)

# Assert
Expand All @@ -83,7 +96,7 @@ def test_read_eof(bytesmode: bool) -> None:
container = ContainerIO.ContainerIO(fh, 22, 100)

# Act
container.seek(100)
assert container.seek(100) == 100
data = container.read()

# Assert
Expand All @@ -94,21 +107,65 @@ def test_read_eof(bytesmode: bool) -> None:

@pytest.mark.parametrize("bytesmode", (True, False))
def test_readline(bytesmode: bool) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)

# Act
data = container.readline()

# Assert
if bytesmode:
data = data.decode()
assert data == "This is line 1\n"

data = container.readline(4)
if bytesmode:
data = data.decode()
assert data == "This"


@pytest.mark.parametrize("bytesmode", (True, False))
def test_readlines(bytesmode: bool) -> None:
expected = [
"This is line 1\n",
"This is line 2\n",
"This is line 3\n",
"This is line 4\n",
"This is line 5\n",
"This is line 6\n",
"This is line 7\n",
"This is line 8\n",
]
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)

data = container.readlines()
if bytesmode:
data = [line.decode() for line in data]
assert data == expected

assert container.seek(0) == 0

data = container.readlines(2)
if bytesmode:
data = [line.decode() for line in data]
assert data == expected[:2]


@pytest.mark.parametrize("bytesmode", (True, False))
def test_write(bytesmode: bool) -> None:
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)

assert container.writable() is False

with pytest.raises(NotImplementedError):
container.write(b"" if bytesmode else "")
with pytest.raises(NotImplementedError):
container.writelines([])
with pytest.raises(NotImplementedError):
container.truncate()


@pytest.mark.parametrize("bytesmode", (True, False))
def test_iter(bytesmode: bool) -> None:
# Arrange
expected = [
"This is line 1\n",
Expand All @@ -124,9 +181,21 @@ def test_readlines(bytesmode: bool) -> None:
container = ContainerIO.ContainerIO(fh, 0, 120)

# Act
data = container.readlines()
data = []
for line in container:
data.append(line)

# Assert
if bytesmode:
data = [line.decode() for line in data]
assert data == expected


@pytest.mark.parametrize("bytesmode", (True, False))
def test_file(bytesmode: bool) -> None:
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)

assert isinstance(container.fileno(), int)
container.flush()
container.close()
Loading

0 comments on commit ebd1eed

Please sign in to comment.