Merge branch 'main' into vtf-support

This commit is contained in:
Andrew Murray 2025-05-04 07:42:43 +10:00
commit 1c7b3e4b1f
481 changed files with 13178 additions and 7015 deletions

View File

@ -1,100 +0,0 @@
skip_commits:
files:
- ".github/**/*"
- ".gitmodules"
- "docs/**/*"
- "wheels/**/*"
version: '{build}'
clone_folder: c:\pillow
init:
- ECHO %PYTHON%
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
# Uncomment previous line to get RDP access during the build.
environment:
COVERAGE_CORE: sysmon
EXECUTABLE: python.exe
TEST_OPTIONS:
DEPLOY: YES
matrix:
- PYTHON: C:/Python312
ARCHITECTURE: x86
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
- PYTHON: C:/Python39-x64
ARCHITECTURE: AMD64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
install:
- '%PYTHON%\%EXECUTABLE% --version'
- '%PYTHON%\%EXECUTABLE% -m pip install --upgrade pip'
- curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
- 7z x pillow-test-images.zip -oc:\
- xcopy /S /Y c:\test-images-main\* c:\pillow\tests\images
- curl -fsSL -o nasm-win64.zip https://raw.githubusercontent.com/python-pillow/pillow-depends/main/nasm-2.16.03-win64.zip
- 7z x nasm-win64.zip -oc:\
- choco install ghostscript --version=10.3.1
- path c:\nasm-2.16.03;C:\Program Files\gs\gs10.03.1\bin;%PATH%
- cd c:\pillow\winbuild\
- ps: |
c:\python39\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\
c:\pillow\winbuild\build\build_dep_all.cmd
$host.SetShouldExit(0)
- path C:\pillow\winbuild\build\bin;%PATH%
build_script:
- cd c:\pillow
- winbuild\build\build_env.cmd
- '%PYTHON%\%EXECUTABLE% -m pip install -v -C raqm=vendor -C fribidi=vendor .'
- '%PYTHON%\%EXECUTABLE% selftest.py --installed'
test_script:
- cd c:\pillow
- '%PYTHON%\%EXECUTABLE% -m pip install pytest pytest-cov pytest-timeout defusedxml numpy olefile pyroma'
- c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\%EXECUTABLE%
- '%PYTHON%\%EXECUTABLE% -c "from PIL import Image"'
- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests'
#- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest?
after_test:
- curl -Os https://uploader.codecov.io/latest/windows/codecov.exe
- .\codecov.exe --file coverage.xml --name %PYTHON% --flags AppVeyor
matrix:
fast_finish: true
cache:
- '%LOCALAPPDATA%\pip\Cache'
artifacts:
- path: pillow\*.egg
name: egg
- path: pillow\*.whl
name: wheel
before_deploy:
- cd c:\pillow
- '%PYTHON%\%EXECUTABLE% -m pip wheel -v -C raqm=vendor -C fribidi=vendor .'
- ps: Get-ChildItem .\*.whl | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
deploy:
provider: S3
region: us-west-2
access_key_id: AKIAIRAXC62ZNTVQJMOQ
secret_access_key:
secure: Hwb6klTqtBeMgxAjRoDltiiqpuH8xbwD4UooDzBSiCWXjuFj1lyl4kHgHwTCCGqi
bucket: pillow-nightly
folder: win/$(APPVEYOR_BUILD_NUMBER)/
artifact: /.*egg|wheel/
on:
APPVEYOR_REPO_NAME: python-pillow/Pillow
branch: main
deploy: YES
# Uncomment the following lines to get RDP access after the build/test and block for
# up to the timeout limit (~1hr)
#
#on_finish:
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))

View File

@ -2,8 +2,4 @@
# gather the coverage data # gather the coverage data
python3 -m pip install coverage python3 -m pip install coverage
if [[ $MATRIX_DOCKER ]]; then python3 -m coverage xml
python3 -m coverage xml --ignore-errors
else
python3 -m coverage xml
fi

View File

@ -3,8 +3,5 @@
set -e set -e
python3 -m coverage erase python3 -m coverage erase
if [ $(uname) == "Darwin" ]; then
export CPPFLAGS="-I/usr/local/miniconda/include";
fi
make clean make clean
make install-coverage make install-coverage

View File

@ -2,12 +2,12 @@
aptget_update() aptget_update()
{ {
if [ ! -z $1 ]; then if [ -n "$1" ]; then
echo "" echo ""
echo "Retrying apt-get update..." echo "Retrying apt-get update..."
echo "" echo ""
fi fi
output=`sudo apt-get update 2>&1` output=$(sudo apt-get update 2>&1)
echo "$output" echo "$output"
if [[ $output == *[WE]:\ * ]]; then if [[ $output == *[WE]:\ * ]]; then
return 1 return 1
@ -20,29 +20,28 @@ fi
set -e set -e
if [[ $(uname) != CYGWIN* ]]; then if [[ $(uname) != CYGWIN* ]]; then
sudo apt-get -qq install libfreetype6-dev liblcms2-dev python3-tk\ sudo apt-get -qq install libfreetype6-dev liblcms2-dev libtiff-dev python3-tk\
ghostscript libffi-dev libjpeg-turbo-progs libopenjp2-7-dev\ ghostscript libjpeg-turbo8-dev libopenjp2-7-dev\
cmake meson imagemagick libharfbuzz-dev libfribidi-dev\ cmake meson imagemagick libharfbuzz-dev libfribidi-dev\
sway wl-clipboard libopenblas-dev sway wl-clipboard libopenblas-dev nasm
fi fi
python3 -m pip install --upgrade pip python3 -m pip install --upgrade pip
python3 -m pip install --upgrade wheel python3 -m pip install --upgrade wheel
python3 -m pip install coverage python3 -m pip install coverage
python3 -m pip install defusedxml python3 -m pip install defusedxml
python3 -m pip install ipython
python3 -m pip install olefile python3 -m pip install olefile
python3 -m pip install -U pytest python3 -m pip install -U pytest
python3 -m pip install -U pytest-cov python3 -m pip install -U pytest-cov
python3 -m pip install -U pytest-timeout python3 -m pip install -U pytest-timeout
python3 -m pip install pyroma python3 -m pip install pyroma
# optional test dependency, only install if there's a binary package.
# fails on beta 3.14 and PyPy
python3 -m pip install --only-binary=:all: pyarrow || true
if [[ $(uname) != CYGWIN* ]]; then if [[ $(uname) != CYGWIN* ]]; then
# TODO Update condition when NumPy supports free-threading python3 -m pip install numpy
if [[ "$PYTHON_GIL" == "0" ]]; then
python3 -m pip install numpy --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
else
python3 -m pip install numpy
fi
# PyQt6 doesn't support PyPy3 # PyQt6 doesn't support PyPy3
if [[ $GHA_PYTHON_VERSION == 3.* ]]; then if [[ $GHA_PYTHON_VERSION == 3.* ]]; then
@ -52,12 +51,9 @@ if [[ $(uname) != CYGWIN* ]]; then
fi fi
# Pyroma uses non-isolated build and fails with old setuptools # Pyroma uses non-isolated build and fails with old setuptools
if [[ if [[ $GHA_PYTHON_VERSION == 3.9 ]]; then
$GHA_PYTHON_VERSION == pypy3.9
|| $GHA_PYTHON_VERSION == 3.9
]]; then
# To match pyproject.toml # To match pyproject.toml
python3 -m pip install "setuptools>=67.8" python3 -m pip install "setuptools>=77"
fi fi
# webp # webp
@ -69,6 +65,9 @@ if [[ $(uname) != CYGWIN* ]]; then
# raqm # raqm
pushd depends && ./install_raqm.sh && popd pushd depends && ./install_raqm.sh && popd
# libavif
pushd depends && CMAKE_POLICY_VERSION_MINIMUM=3.5 ./install_libavif.sh && popd
# extra test images # extra test images
pushd depends && ./install_extra_test_images.sh && popd pushd depends && ./install_extra_test_images.sh && popd
else else

View File

@ -1 +1 @@
cibuildwheel==2.19.2 cibuildwheel==2.23.3

View File

@ -1 +1,12 @@
mypy==1.10.1 mypy==1.15.0
IceSpringPySideStubs-PyQt6
IceSpringPySideStubs-PySide6
ipython
numpy
packaging
pytest
sphinx
types-atheris
types-defusedxml
types-olefile
types-setuptools

3
.ci/test.cmd Normal file
View File

@ -0,0 +1,3 @@
python.exe -c "from PIL import Image"
IF ERRORLEVEL 1 EXIT /B
python.exe -bb -m pytest -v -x -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests

View File

@ -4,4 +4,4 @@ set -e
python3 -c "from PIL import Image" python3 -c "from PIL import Image"
python3 -bb -m pytest -v -x -W always --cov PIL --cov Tests --cov-report term Tests $REVERSE python3 -bb -m pytest -v -x -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests $REVERSE

View File

@ -1,5 +1,26 @@
# A clang-format style that approximates Python's PEP 7 # A clang-format style that approximates Python's PEP 7
# Useful for IDE integration # Useful for IDE integration
Language: C
BasedOnStyle: Google
AlwaysBreakAfterReturnType: All
AllowShortIfStatementsOnASingleLine: false
AlignAfterOpenBracket: BlockIndent
BinPackArguments: false
BinPackParameters: false
BreakBeforeBraces: Attach
ColumnLimit: 88
DerivePointerAlignment: false
IndentGotoLabels: false
IndentWidth: 4
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SpaceBeforeParens: ControlStatements
SpacesInParentheses: false
TabWidth: 4
UseTab: Never
---
Language: Cpp
BasedOnStyle: Google BasedOnStyle: Google
AlwaysBreakAfterReturnType: All AlwaysBreakAfterReturnType: All
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false
@ -11,7 +32,6 @@ ColumnLimit: 88
DerivePointerAlignment: false DerivePointerAlignment: false
IndentGotoLabels: false IndentGotoLabels: false
IndentWidth: 4 IndentWidth: 4
Language: Cpp
PointerAlignment: Right PointerAlignment: Right
ReflowComments: true ReflowComments: true
SortIncludes: false SortIncludes: false

View File

@ -9,7 +9,7 @@ Please send a pull request to the `main` branch. Please include [documentation](
- Fork the Pillow repository. - Fork the Pillow repository.
- Create a branch from `main`. - Create a branch from `main`.
- Develop bug fixes, features, tests, etc. - Develop bug fixes, features, tests, etc.
- Run the test suite. You can enable GitHub Actions (https://github.com/MY-USERNAME/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/projects/new) on your repo to catch test failures prior to the pull request, and [Codecov](https://codecov.io/gh) to see if the changed code is covered by tests. - Run the test suite. You can enable GitHub Actions (https://github.com/MY-USERNAME/Pillow/actions) on your repo to catch test failures prior to the pull request, and [Codecov](https://codecov.io/gh) to see if the changed code is covered by tests.
- Create a pull request to pull the changes from your branch to the Pillow `main`. - Create a pull request to pull the changes from your branch to the Pillow `main`.
### Guidelines ### Guidelines
@ -17,9 +17,8 @@ Please send a pull request to the `main` branch. Please include [documentation](
- Separate code commits from reformatting commits. - Separate code commits from reformatting commits.
- Provide tests for any newly added code. - Provide tests for any newly added code.
- Follow PEP 8. - Follow PEP 8.
- When committing only documentation changes please include `[ci skip]` in the commit message to avoid running tests on AppVeyor. - When committing only documentation changes please include `[ci skip]` in the commit message to avoid running extra tests.
- Include [release notes](https://github.com/python-pillow/Pillow/tree/main/docs/releasenotes) as needed or appropriate with your bug fixes, feature additions and tests. - Include [release notes](https://github.com/python-pillow/Pillow/tree/main/docs/releasenotes) as needed or appropriate with your bug fixes, feature additions and tests.
- Do not add to the [changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) for proposed changes, as that is updated after changes are merged.
## Reporting Issues ## Reporting Issues

46
.github/ISSUE_TEMPLATE/RELEASE.md vendored Normal file
View File

@ -0,0 +1,46 @@
---
name: "Maintainers only: Release"
about: For maintainers to schedule a quarterly release
labels: Release
---
## Main release
Released quarterly on January 2nd, April 1st, July 1st and October 15th.
* [ ] Open a release ticket e.g. https://github.com/python-pillow/Pillow/issues/3154
* [ ] Develop and prepare release in `main` branch.
* [ ] Add release notes e.g. https://github.com/python-pillow/Pillow/pull/8885
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) to confirm passing tests in `main` branch.
* [ ] Check that all the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) jobs by manually triggering them.
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
* [ ] Run pre-release check via `make release-test` in a freshly cloned repo.
* [ ] Create branch and tag for release e.g.:
```bash
git branch [[MAJOR.MINOR]].x
git tag [[MAJOR.MINOR]].0
git push --tags
```
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) has passed, including the "Upload release to PyPI" job. This will have been triggered by the new tag.
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases).
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), increment and append `.dev0` to version identifier in `src/PIL/_version.py` and then:
```bash
git push --all
```
## Publicize release
* [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321
## Documentation
* [ ] Make sure the [default version for Read the Docs](https://pillow.readthedocs.io/en/stable/) is up-to-date with the release changes
## Docker images
* [ ] Update Pillow in the Docker Images repository
```bash
git clone https://github.com/python-pillow/docker-images
cd docker-images
./update-pillow-tag.sh [[release tag]]
```

1
.github/mergify.yml vendored
View File

@ -9,7 +9,6 @@ pull_request_rules:
- status-success=Windows Test Successful - status-success=Windows Test Successful
- status-success=MinGW - status-success=MinGW
- status-success=Cygwin Test Successful - status-success=Cygwin Test Successful
- status-success=continuous-integration/appveyor/pr
actions: actions:
merge: merge:
method: merge method: merge

View File

@ -3,18 +3,19 @@ tag-template: "$NEXT_MINOR_VERSION"
change-template: '- $TITLE #$NUMBER [@$AUTHOR]' change-template: '- $TITLE #$NUMBER [@$AUTHOR]'
categories: categories:
- title: "Dependencies" - title: "Removals"
label: "Dependency" label: "Removal"
- title: "Deprecations" - title: "Deprecations"
label: "Deprecation" label: "Deprecation"
- title: "Documentation" - title: "Documentation"
label: "Documentation" label: "Documentation"
- title: "Removals" - title: "Dependencies"
label: "Removal" label: "Dependency"
- title: "Testing" - title: "Testing"
label: "Testing" label: "Testing"
- title: "Type hints" - title: "Type hints"
label: "Type hints" label: "Type hints"
- title: "Other changes"
exclude-labels: exclude-labels:
- "changelog: skip" - "changelog: skip"
@ -23,6 +24,4 @@ template: |
https://pillow.readthedocs.io/en/stable/releasenotes/$NEXT_MINOR_VERSION.html https://pillow.readthedocs.io/en/stable/releasenotes/$NEXT_MINOR_VERSION.html
## Changes
$CHANGES $CHANGES

12
.github/renovate.json vendored
View File

@ -1,7 +1,7 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:base" "config:recommended"
], ],
"labels": [ "labels": [
"Dependency" "Dependency"
@ -9,9 +9,13 @@
"packageRules": [ "packageRules": [
{ {
"groupName": "github-actions", "groupName": "github-actions",
"matchManagers": ["github-actions"], "matchManagers": [
"separateMajorMinor": "false" "github-actions"
],
"separateMajorMinor": false
} }
], ],
"schedule": ["on the 3rd day of the month"] "schedule": [
"* * 3 * *"
]
} }

View File

@ -6,11 +6,13 @@ on:
- "**" - "**"
paths: paths:
- ".github/workflows/cifuzz.yml" - ".github/workflows/cifuzz.yml"
- ".github/workflows/wheels-dependencies.sh"
- "**.c" - "**.c"
- "**.h" - "**.h"
pull_request: pull_request:
paths: paths:
- ".github/workflows/cifuzz.yml" - ".github/workflows/cifuzz.yml"
- ".github/workflows/wheels-dependencies.sh"
- "**.c" - "**.c"
- "**.h" - "**.h"
workflow_dispatch: workflow_dispatch:
@ -24,8 +26,6 @@ concurrency:
jobs: jobs:
Fuzzing: Fuzzing:
# Disabled until google/oss-fuzz#11419 upgrades Python to 3.9+
if: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Build Fuzzers - name: Build Fuzzers

View File

@ -33,6 +33,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5

View File

@ -21,6 +21,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: pre-commit cache - name: pre-commit cache
uses: actions/cache@v4 uses: actions/cache@v4

View File

@ -2,30 +2,40 @@
set -e set -e
if [[ "$ImageOS" == "macos13" ]]; then
brew uninstall gradle maven
fi
brew install \ brew install \
aom \
dav1d \
freetype \ freetype \
ghostscript \ ghostscript \
jpeg-turbo \
libimagequant \ libimagequant \
libjpeg \ libraqm \
libtiff \ libtiff \
little-cms2 \ little-cms2 \
openjpeg \ openjpeg \
rav1e \
svt-av1 \
webp webp
if [[ "$ImageOS" == "macos13" ]]; then
brew install --ignore-dependencies libraqm
else
brew install libraqm
fi
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig" export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"
python3 -m pip install coverage python3 -m pip install coverage
python3 -m pip install defusedxml python3 -m pip install defusedxml
python3 -m pip install ipython
python3 -m pip install olefile python3 -m pip install olefile
python3 -m pip install -U pytest python3 -m pip install -U pytest
python3 -m pip install -U pytest-cov python3 -m pip install -U pytest-cov
python3 -m pip install -U pytest-timeout python3 -m pip install -U pytest-timeout
python3 -m pip install pyroma python3 -m pip install pyroma
python3 -m pip install numpy python3 -m pip install numpy
# optional test dependency, only install if there's a binary package.
# fails on beta 3.14 and PyPy
python3 -m pip install --only-binary=:all: pyarrow || true
# libavif
pushd depends && ./install_libavif.sh && popd
# extra test images # extra test images
pushd depends && ./install_extra_test_images.sh && popd pushd depends && ./install_extra_test_images.sh && popd

View File

@ -6,7 +6,7 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
issues: write contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
@ -15,6 +15,8 @@ concurrency:
jobs: jobs:
stale: stale:
if: github.repository_owner == 'python-pillow' if: github.repository_owner == 'python-pillow'
permissions:
issues: write
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -48,9 +48,11 @@ jobs:
- name: Checkout Pillow - name: Checkout Pillow
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Cygwin - name: Install Cygwin
uses: cygwin/cygwin-install-action@v4 uses: cygwin/cygwin-install-action@v5
with: with:
packages: > packages: >
gcc-g++ gcc-g++
@ -74,6 +76,7 @@ jobs:
perl perl
python3${{ matrix.python-minor-version }}-cython python3${{ matrix.python-minor-version }}-cython
python3${{ matrix.python-minor-version }}-devel python3${{ matrix.python-minor-version }}-devel
python3${{ matrix.python-minor-version }}-ipython
python3${{ matrix.python-minor-version }}-numpy python3${{ matrix.python-minor-version }}-numpy
python3${{ matrix.python-minor-version }}-sip python3${{ matrix.python-minor-version }}-sip
python3${{ matrix.python-minor-version }}-tkinter python3${{ matrix.python-minor-version }}-tkinter
@ -130,11 +133,12 @@ jobs:
- name: After success - name: After success
run: | run: |
bash.exe .ci/after_success.sh bash.exe .ci/after_success.sh
rm C:\cygwin\bin\bash.EXE
- name: Upload coverage - name: Upload coverage
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
file: ./coverage.xml files: ./coverage.xml
flags: GHA_Cygwin flags: GHA_Cygwin
name: Cygwin Python 3.${{ matrix.python-minor-version }} name: Cygwin Python 3.${{ matrix.python-minor-version }}
token: ${{ secrets.CODECOV_ORG_TOKEN }} token: ${{ secrets.CODECOV_ORG_TOKEN }}

View File

@ -29,13 +29,13 @@ concurrency:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: ["ubuntu-latest"]
docker: [ docker: [
# Run slower jobs first to give them a headstart and reduce waiting time # Run slower jobs first to give them a headstart and reduce waiting time
ubuntu-22.04-jammy-arm64v8,
ubuntu-24.04-noble-ppc64le, ubuntu-24.04-noble-ppc64le,
ubuntu-24.04-noble-s390x, ubuntu-24.04-noble-s390x,
# Then run the remainder # Then run the remainder
@ -44,35 +44,40 @@ jobs:
amazon-2023-amd64, amazon-2023-amd64,
arch, arch,
centos-stream-9-amd64, centos-stream-9-amd64,
centos-stream-10-amd64,
debian-12-bookworm-x86, debian-12-bookworm-x86,
debian-12-bookworm-amd64, debian-12-bookworm-amd64,
fedora-39-amd64, fedora-41-amd64,
fedora-40-amd64, fedora-42-amd64,
gentoo, gentoo,
ubuntu-22.04-jammy-amd64, ubuntu-22.04-jammy-amd64,
ubuntu-24.04-noble-amd64, ubuntu-24.04-noble-amd64,
] ]
dockerTag: [main] dockerTag: [main]
include: include:
- docker: "ubuntu-22.04-jammy-arm64v8"
qemu-arch: "aarch64"
- docker: "ubuntu-24.04-noble-ppc64le" - docker: "ubuntu-24.04-noble-ppc64le"
qemu-arch: "ppc64le" qemu-arch: "ppc64le"
- docker: "ubuntu-24.04-noble-s390x" - docker: "ubuntu-24.04-noble-s390x"
qemu-arch: "s390x" qemu-arch: "s390x"
- docker: "ubuntu-24.04-noble-arm64v8"
os: "ubuntu-24.04-arm"
dockerTag: main
name: ${{ matrix.docker }} name: ${{ matrix.docker }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Build system information - name: Build system information
run: python3 .github/workflows/system-info.py run: python3 .github/workflows/system-info.py
- name: Set up QEMU - name: Set up QEMU
if: "matrix.qemu-arch" if: "matrix.qemu-arch"
run: | uses: docker/setup-qemu-action@v3
docker run --rm --privileged aptman/qus -s -- -p ${{ matrix.qemu-arch }} with:
platforms: ${{ matrix.qemu-arch }}
- name: Docker pull - name: Docker pull
run: | run: |
@ -87,22 +92,21 @@ jobs:
- name: After success - name: After success
run: | run: |
PATH="$PATH:~/.local/bin"
docker start pillow_container docker start pillow_container
sudo docker cp pillow_container:/Pillow /Pillow
sudo chown -R runner /Pillow
pil_path=`docker exec pillow_container /vpy3/bin/python -c 'import os, PIL;print(os.path.realpath(os.path.dirname(PIL.__file__)))'` pil_path=`docker exec pillow_container /vpy3/bin/python -c 'import os, PIL;print(os.path.realpath(os.path.dirname(PIL.__file__)))'`
docker stop pillow_container docker stop pillow_container
sudo mkdir -p $pil_path sudo mkdir -p $pil_path
sudo cp src/PIL/*.py $pil_path sudo cp src/PIL/*.py $pil_path
cd /Pillow
.ci/after_success.sh .ci/after_success.sh
env:
MATRIX_DOCKER: ${{ matrix.docker }}
- name: Upload coverage - name: Upload coverage
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
flags: GHA_Docker flags: GHA_Docker
name: ${{ matrix.docker }} name: ${{ matrix.docker }}
gcov: true
token: ${{ secrets.CODECOV_ORG_TOKEN }} token: ${{ secrets.CODECOV_ORG_TOKEN }}
success: success:

View File

@ -46,6 +46,8 @@ jobs:
steps: steps:
- name: Checkout Pillow - name: Checkout Pillow
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up shell - name: Set up shell
run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH
@ -58,35 +60,35 @@ jobs:
mingw-w64-x86_64-gcc \ mingw-w64-x86_64-gcc \
mingw-w64-x86_64-ghostscript \ mingw-w64-x86_64-ghostscript \
mingw-w64-x86_64-lcms2 \ mingw-w64-x86_64-lcms2 \
mingw-w64-x86_64-libavif \
mingw-w64-x86_64-libimagequant \ mingw-w64-x86_64-libimagequant \
mingw-w64-x86_64-libjpeg-turbo \ mingw-w64-x86_64-libjpeg-turbo \
mingw-w64-x86_64-libraqm \ mingw-w64-x86_64-libraqm \
mingw-w64-x86_64-libtiff \ mingw-w64-x86_64-libtiff \
mingw-w64-x86_64-libwebp \ mingw-w64-x86_64-libwebp \
mingw-w64-x86_64-openjpeg2 \ mingw-w64-x86_64-openjpeg2 \
mingw-w64-x86_64-python3-numpy \ mingw-w64-x86_64-python-numpy \
mingw-w64-x86_64-python3-olefile \ mingw-w64-x86_64-python-olefile \
mingw-w64-x86_64-python3-setuptools \ mingw-w64-x86_64-python-pip \
mingw-w64-x86_64-python-pytest \
mingw-w64-x86_64-python-pytest-cov \
mingw-w64-x86_64-python-pytest-timeout \
mingw-w64-x86_64-python-pyqt6 mingw-w64-x86_64-python-pyqt6
python3 -m ensurepip
python3 -m pip install pyroma pytest pytest-cov pytest-timeout
pushd depends && ./install_extra_test_images.sh && popd pushd depends && ./install_extra_test_images.sh && popd
- name: Build Pillow - name: Build Pillow
run: SETUPTOOLS_USE_DISTUTILS="stdlib" CFLAGS="-coverage" python3 -m pip install . run: CFLAGS="-coverage" python3 -m pip install .
- name: Test Pillow - name: Test Pillow
run: | run: |
python3 selftest.py --installed python3 selftest.py --installed
python3 -c "from PIL import Image" .ci/test.sh
python3 -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
- name: Upload coverage - name: Upload coverage
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
file: ./coverage.xml files: ./coverage.xml
flags: GHA_Windows flags: GHA_Windows
name: "MSYS2 MinGW" name: "MSYS2 MinGW"
token: ${{ secrets.CODECOV_ORG_TOKEN }} token: ${{ secrets.CODECOV_ORG_TOKEN }}

View File

@ -40,6 +40,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Build system information - name: Build system information
run: python3 .github/workflows/system-info.py run: python3 .github/workflows/system-info.py

View File

@ -31,29 +31,38 @@ env:
jobs: jobs:
build: build:
runs-on: windows-latest runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["pypy3.10", "pypy3.9", "3.9", "3.10", "3.11", "3.12", "3.13"] python-version: ["pypy3.11", "pypy3.10", "3.10", "3.11", "3.12", "3.13", "3.14"]
architecture: ["x64"]
os: ["windows-latest"]
include:
# Test the oldest Python on 32-bit
- { python-version: "3.9", architecture: "x86", os: "windows-2019" }
timeout-minutes: 30 timeout-minutes: 45
name: Python ${{ matrix.python-version }} name: Python ${{ matrix.python-version }} (${{ matrix.architecture }})
steps: steps:
- name: Checkout Pillow - name: Checkout Pillow
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Checkout cached dependencies - name: Checkout cached dependencies
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
persist-credentials: false
repository: python-pillow/pillow-depends repository: python-pillow/pillow-depends
path: winbuild\depends path: winbuild\depends
- name: Checkout extra test images - name: Checkout extra test images
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
persist-credentials: false
repository: python-pillow/test-images repository: python-pillow/test-images
path: Tests\test-images path: Tests\test-images
@ -63,22 +72,25 @@ jobs:
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
allow-prereleases: true allow-prereleases: true
architecture: ${{ matrix.architecture }}
cache: pip cache: pip
cache-dependency-path: ".github/workflows/test-windows.yml" cache-dependency-path: ".github/workflows/test-windows.yml"
- name: Print build system information - name: Print build system information
run: python3 .github/workflows/system-info.py run: python3 .github/workflows/system-info.py
- name: Install Python dependencies - name: Upgrade pip
run: > run: |
python3 -m pip install python3 -m pip install --upgrade pip
coverage>=7.4.2
defusedxml - name: Install CPython dependencies
olefile if: "!contains(matrix.python-version, 'pypy') && matrix.architecture != 'x86'"
pyroma run: |
pytest python3 -m pip install PyQt6
pytest-cov
pytest-timeout - name: Install PyArrow dependency
run: |
python3 -m pip install --only-binary=:all: pyarrow || true
- name: Install dependencies - name: Install dependencies
id: install id: install
@ -86,8 +98,8 @@ jobs:
choco install nasm --no-progress choco install nasm --no-progress
echo "C:\Program Files\NASM" >> $env:GITHUB_PATH echo "C:\Program Files\NASM" >> $env:GITHUB_PATH
choco install ghostscript --version=10.3.1 --no-progress choco install ghostscript --version=10.5.0 --no-progress
echo "C:\Program Files\gs\gs10.00.0\bin" >> $env:GITHUB_PATH echo "C:\Program Files\gs\gs10.05.0\bin" >> $env:GITHUB_PATH
# Install extra test images # Install extra test images
xcopy /S /Y Tests\test-images\* Tests\images xcopy /S /Y Tests\test-images\* Tests\images
@ -137,6 +149,10 @@ jobs:
if: steps.build-cache.outputs.cache-hit != 'true' if: steps.build-cache.outputs.cache-hit != 'true'
run: "& winbuild\\build\\build_dep_libpng.cmd" run: "& winbuild\\build\\build_dep_libpng.cmd"
- name: Build dependencies / libavif
if: steps.build-cache.outputs.cache-hit != 'true' && matrix.architecture == 'x64'
run: "& winbuild\\build\\build_dep_libavif.cmd"
# for FreeType WOFF2 font support # for FreeType WOFF2 font support
- name: Build dependencies / brotli - name: Build dependencies / brotli
if: steps.build-cache.outputs.cache-hit != 'true' if: steps.build-cache.outputs.cache-hit != 'true'
@ -178,7 +194,7 @@ jobs:
- name: Build Pillow - name: Build Pillow
run: | run: |
$FLAGS="-C raqm=vendor -C fribidi=vendor" $FLAGS="-C raqm=vendor -C fribidi=vendor"
cmd /c "winbuild\build\build_env.cmd && $env:pythonLocation\python.exe -m pip install -v $FLAGS ." cmd /c "winbuild\build\build_env.cmd && $env:pythonLocation\python.exe -m pip install -v $FLAGS .[tests]"
& $env:pythonLocation\python.exe selftest.py --installed & $env:pythonLocation\python.exe selftest.py --installed
shell: pwsh shell: pwsh
@ -190,8 +206,8 @@ jobs:
- name: Test Pillow - name: Test Pillow
run: | run: |
path %GITHUB_WORKSPACE%\\winbuild\\build\\bin;%PATH% path %GITHUB_WORKSPACE%\winbuild\build\bin;%PATH%
python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests .ci\test.cmd
shell: cmd shell: cmd
- name: Prepare to upload errors - name: Prepare to upload errors
@ -213,9 +229,9 @@ jobs:
shell: pwsh shell: pwsh
- name: Upload coverage - name: Upload coverage
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
file: ./coverage.xml files: ./coverage.xml
flags: GHA_Windows flags: GHA_Windows
name: ${{ runner.os }} Python ${{ matrix.python-version }} name: ${{ runner.os }} Python ${{ matrix.python-version }}
token: ${{ secrets.CODECOV_ORG_TOKEN }} token: ${{ secrets.CODECOV_ORG_TOKEN }}

View File

@ -37,12 +37,14 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ os: [
"macos-14", "macos-latest",
"ubuntu-latest", "ubuntu-latest",
] ]
python-version: [ python-version: [
"pypy3.11",
"pypy3.10", "pypy3.10",
"pypy3.9", "3.14",
"3.13t",
"3.13", "3.13",
"3.12", "3.12",
"3.11", "3.11",
@ -53,21 +55,22 @@ jobs:
- { python-version: "3.11", PYTHONOPTIMIZE: 1, REVERSE: "--reverse" } - { python-version: "3.11", PYTHONOPTIMIZE: 1, REVERSE: "--reverse" }
- { python-version: "3.10", PYTHONOPTIMIZE: 2 } - { python-version: "3.10", PYTHONOPTIMIZE: 2 }
# Free-threaded # Free-threaded
- { os: "ubuntu-latest", python-version: "3.13-dev", disable-gil: true } - { python-version: "3.13t", disable-gil: true }
# M1 only available for 3.10+ # M1 only available for 3.10+
- { os: "macos-13", python-version: "3.9" } - { os: "macos-13", python-version: "3.9" }
exclude: exclude:
- { os: "macos-14", python-version: "3.9" } - { os: "macos-latest", python-version: "3.9" }
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
name: ${{ matrix.os }} Python ${{ matrix.python-version }} ${{ matrix.disable-gil && 'free-threaded' || '' }} name: ${{ matrix.os }} Python ${{ matrix.python-version }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5 uses: actions/setup-python@v5
if: "${{ !matrix.disable-gil }}"
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
allow-prereleases: true allow-prereleases: true
@ -76,13 +79,6 @@ jobs:
".ci/*.sh" ".ci/*.sh"
"pyproject.toml" "pyproject.toml"
- name: Set up Python ${{ matrix.python-version }} (free-threaded)
uses: deadsnakes/action@v3.1.0
if: "${{ matrix.disable-gil }}"
with:
python-version: ${{ matrix.python-version }}
nogil: ${{ matrix.disable-gil }}
- name: Set PYTHON_GIL - name: Set PYTHON_GIL
if: "${{ matrix.disable-gil }}" if: "${{ matrix.disable-gil }}"
run: | run: |
@ -115,7 +111,7 @@ jobs:
GHA_PYTHON_VERSION: ${{ matrix.python-version }} GHA_PYTHON_VERSION: ${{ matrix.python-version }}
- name: Register gcc problem matcher - name: Register gcc problem matcher
if: "matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'" if: "matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'"
run: echo "::add-matcher::.github/problem-matchers/gcc.json" run: echo "::add-matcher::.github/problem-matchers/gcc.json"
- name: Build - name: Build
@ -155,11 +151,10 @@ jobs:
.ci/after_success.sh .ci/after_success.sh
- name: Upload coverage - name: Upload coverage
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }} flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }}
name: ${{ matrix.os }} Python ${{ matrix.python-version }} name: ${{ matrix.os }} Python ${{ matrix.python-version }}
gcov: true
token: ${{ secrets.CODECOV_ORG_TOKEN }} token: ${{ secrets.CODECOV_ORG_TOKEN }}
success: success:

View File

@ -1,11 +1,33 @@
#!/bin/bash #!/bin/bash
# Define custom utilities
# Test for macOS with [ -n "$IS_MACOS" ] # Setup that needs to be done before multibuild utils are invoked
if [ -z "$IS_MACOS" ]; then PROJECTDIR=$(pwd)
export MB_ML_LIBC=${AUDITWHEEL_POLICY::9} if [[ "$(uname -s)" == "Darwin" ]]; then
export MB_ML_VER=${AUDITWHEEL_POLICY:9} # Safety check - macOS builds require that CIBW_ARCHS is set, and that it
# only contains a single value (even though cibuildwheel allows multiple
# values in CIBW_ARCHS).
if [[ -z "$CIBW_ARCHS" ]]; then
echo "ERROR: Pillow macOS builds require CIBW_ARCHS be defined."
exit 1
fi
if [[ "$CIBW_ARCHS" == *" "* ]]; then
echo "ERROR: Pillow macOS builds only support a single architecture in CIBW_ARCHS."
exit 1
fi
# Build macOS dependencies in `build/darwin`
# Install them into `build/deps/darwin`
WORKDIR=$(pwd)/build/darwin
BUILD_PREFIX=$(pwd)/build/deps/darwin
else
# Build prefix will default to /usr/local
WORKDIR=$(pwd)/build
MB_ML_LIBC=${AUDITWHEEL_POLICY::9}
MB_ML_VER=${AUDITWHEEL_POLICY:9}
fi fi
export PLAT=$CIBW_ARCHS PLAT="${CIBW_ARCHS:-$AUDITWHEEL_ARCH}"
# Define custom utilities
source wheels/multibuild/common_utils.sh source wheels/multibuild/common_utils.sh
source wheels/multibuild/library_builders.sh source wheels/multibuild/library_builders.sh
if [ -z "$IS_MACOS" ]; then if [ -z "$IS_MACOS" ]; then
@ -15,90 +37,112 @@ fi
ARCHIVE_SDIR=pillow-depends-main ARCHIVE_SDIR=pillow-depends-main
# Package versions for fresh source builds # Package versions for fresh source builds
FREETYPE_VERSION=2.13.2 FREETYPE_VERSION=2.13.3
HARFBUZZ_VERSION=8.5.0 HARFBUZZ_VERSION=11.1.0
LIBPNG_VERSION=1.6.43 LIBPNG_VERSION=1.6.47
JPEGTURBO_VERSION=3.0.3 JPEGTURBO_VERSION=3.1.0
OPENJPEG_VERSION=2.5.2 OPENJPEG_VERSION=2.5.3
XZ_VERSION=5.4.5 XZ_VERSION=5.8.1
TIFF_VERSION=4.6.0 TIFF_VERSION=4.7.0
LCMS2_VERSION=2.16 LCMS2_VERSION=2.17
if [[ -n "$IS_MACOS" ]]; then ZLIB_VERSION=1.3.1
GIFLIB_VERSION=5.2.2 ZLIB_NG_VERSION=2.2.4
else LIBWEBP_VERSION=1.5.0
GIFLIB_VERSION=5.2.1
fi
if [[ -n "$IS_MACOS" ]] || [[ "$MB_ML_VER" != 2014 ]]; then
ZLIB_VERSION=1.3.1
else
ZLIB_VERSION=1.2.8
fi
LIBWEBP_VERSION=1.4.0
BZIP2_VERSION=1.0.8 BZIP2_VERSION=1.0.8
LIBXCB_VERSION=1.17.0 LIBXCB_VERSION=1.17.0
BROTLI_VERSION=1.1.0 BROTLI_VERSION=1.1.0
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "x86_64" ]]; then function build_pkg_config {
function build_openjpeg { if [ -e pkg-config-stamp ]; then return; fi
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-${OPENJPEG_VERSION}.tar.gz) # This essentially duplicates the Homebrew recipe
(cd $out_dir \ CFLAGS="$CFLAGS -Wno-int-conversion" build_simple pkg-config 0.29.2 https://pkg-config.freedesktop.org/releases tar.gz \
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \ --disable-debug --disable-host-tool --with-internal-glib \
&& make install) --with-pc-path=$BUILD_PREFIX/share/pkgconfig:$BUILD_PREFIX/lib/pkgconfig \
touch openjpeg-stamp --with-system-include-path=$(xcrun --show-sdk-path --sdk macosx)/usr/include
} export PKG_CONFIG=$BUILD_PREFIX/bin/pkg-config
fi touch pkg-config-stamp
}
function build_zlib_ng {
if [ -e zlib-stamp ]; then return; fi
build_github zlib-ng/zlib-ng $ZLIB_NG_VERSION --zlib-compat
if [ -n "$IS_MACOS" ]; then
# Ensure that on macOS, the library name is an absolute path, not an
# @rpath, so that delocate picks up the right library (and doesn't need
# DYLD_LIBRARY_PATH to be set). The default Makefile doesn't have an
# option to control the install_name.
install_name_tool -id $BUILD_PREFIX/lib/libz.1.dylib $BUILD_PREFIX/lib/libz.1.dylib
fi
touch zlib-stamp
}
function build_brotli { function build_brotli {
local cmake=$(get_modern_cmake) if [ -e brotli-stamp ]; then return; fi
local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-1.1.0.tar.gz) local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-$BROTLI_VERSION.tar.gz)
(cd $out_dir \ (cd $out_dir \
&& $cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \ && cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_LIBDIR=$BUILD_PREFIX/lib -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
&& make install) && make install)
if [[ "$MB_ML_LIBC" == "manylinux" ]]; then touch brotli-stamp
cp /usr/local/lib64/libbrotli* /usr/local/lib }
cp /usr/local/lib64/pkgconfig/libbrotli* /usr/local/lib/pkgconfig
fi function build_harfbuzz {
if [ -e harfbuzz-stamp ]; then return; fi
python3 -m pip install meson ninja
local out_dir=$(fetch_unpack https://github.com/harfbuzz/harfbuzz/releases/download/$HARFBUZZ_VERSION/harfbuzz-$HARFBUZZ_VERSION.tar.xz harfbuzz-$HARFBUZZ_VERSION.tar.xz)
(cd $out_dir \
&& meson setup build --prefix=$BUILD_PREFIX --libdir=$BUILD_PREFIX/lib --buildtype=minsize -Dfreetype=enabled -Dglib=disabled -Dtests=disabled)
(cd $out_dir/build \
&& meson install)
touch harfbuzz-stamp
} }
function build { function build {
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "arm64" ]]; then
sudo chown -R runner /usr/local
fi
build_xz build_xz
if [ -z "$IS_ALPINE" ] && [ -z "$IS_MACOS" ]; then if [ -z "$IS_ALPINE" ] && [ -z "$SANITIZER" ] && [ -z "$IS_MACOS" ]; then
yum remove -y zlib-devel yum remove -y zlib-devel
fi fi
build_new_zlib if [[ -n "$IS_MACOS" ]] && [[ "$MACOSX_DEPLOYMENT_TARGET" == "10.10" || "$MACOSX_DEPLOYMENT_TARGET" == "10.13" ]]; then
build_new_zlib
else
build_zlib_ng
fi
build_simple xcb-proto 1.17.0 https://xorg.freedesktop.org/archive/individual/proto build_simple xcb-proto 1.17.0 https://xorg.freedesktop.org/archive/individual/proto
if [ -n "$IS_MACOS" ]; then if [ -n "$IS_MACOS" ]; then
build_simple xorgproto 2024.1 https://www.x.org/pub/individual/proto build_simple xorgproto 2024.1 https://www.x.org/pub/individual/proto
build_simple libXau 1.0.11 https://www.x.org/pub/individual/lib build_simple libXau 1.0.12 https://www.x.org/pub/individual/lib
build_simple libpthread-stubs 0.5 https://xcb.freedesktop.org/dist build_simple libpthread-stubs 0.5 https://xcb.freedesktop.org/dist
if [[ "$CIBW_ARCHS" == "arm64" ]]; then
cp /usr/local/share/pkgconfig/xcb-proto.pc /usr/local/lib/pkgconfig
fi
else else
sed s/\${pc_sysrootdir\}// /usr/local/share/pkgconfig/xcb-proto.pc > /usr/local/lib/pkgconfig/xcb-proto.pc sed s/\${pc_sysrootdir\}// $BUILD_PREFIX/share/pkgconfig/xcb-proto.pc > $BUILD_PREFIX/lib/pkgconfig/xcb-proto.pc
fi fi
build_simple libxcb $LIBXCB_VERSION https://www.x.org/releases/individual/lib build_simple libxcb $LIBXCB_VERSION https://www.x.org/releases/individual/lib
build_libjpeg_turbo build_libjpeg_turbo
build_tiff if [ -n "$IS_MACOS" ]; then
# Custom tiff build to include jpeg; by default, configure won't include
# headers/libs in the custom macOS prefix. Explicitly disable webp,
# libdeflate and zstd, because on x86_64 macs, it will pick up the
# Homebrew versions of those libraries from /usr/local.
build_simple tiff $TIFF_VERSION https://download.osgeo.org/libtiff tar.gz \
--with-jpeg-include-dir=$BUILD_PREFIX/include --with-jpeg-lib-dir=$BUILD_PREFIX/lib \
--disable-webp --disable-libdeflate --disable-zstd
else
build_tiff
fi
build_libpng build_libpng
build_lcms2 build_lcms2
build_openjpeg build_openjpeg
if [ -f /usr/local/lib64/libopenjp2.so ]; then
cp /usr/local/lib64/libopenjp2.so /usr/local/lib
fi
ORIGINAL_CFLAGS=$CFLAGS webp_cflags="-O3 -DNDEBUG"
CFLAGS="$CFLAGS -O3 -DNDEBUG"
if [[ -n "$IS_MACOS" ]]; then if [[ -n "$IS_MACOS" ]]; then
CFLAGS="$CFLAGS -Wl,-headerpad_max_install_names" webp_cflags="$webp_cflags -Wl,-headerpad_max_install_names"
fi fi
build_libwebp CFLAGS="$CFLAGS $webp_cflags" build_simple libwebp $LIBWEBP_VERSION \
CFLAGS=$ORIGINAL_CFLAGS https://storage.googleapis.com/downloads.webmproject.org/releases/webp tar.gz \
--enable-libwebpmux --enable-libwebpdemux
build_brotli build_brotli
@ -109,42 +153,50 @@ function build {
build_freetype build_freetype
fi fi
if [ -z "$IS_MACOS" ]; then build_harfbuzz
export FREETYPE_LIBS=-lfreetype
export FREETYPE_CFLAGS=-I/usr/local/include/freetype2/
fi
build_simple harfbuzz $HARFBUZZ_VERSION https://github.com/harfbuzz/harfbuzz/releases/download/$HARFBUZZ_VERSION tar.xz --with-freetype=yes --with-glib=no
if [ -z "$IS_MACOS" ]; then
export FREETYPE_LIBS=""
export FREETYPE_CFLAGS=""
fi
} }
# Perform all dependency builds in the build subfolder.
mkdir -p $WORKDIR
pushd $WORKDIR > /dev/null
# Any stuff that you need to do before you start building the wheels # Any stuff that you need to do before you start building the wheels
# Runs in the root directory of this repository. # Runs in the root directory of this repository.
curl -fsSL -o pillow-depends-main.zip https://github.com/python-pillow/pillow-depends/archive/main.zip if [[ ! -d $WORKDIR/pillow-depends-main ]]; then
untar pillow-depends-main.zip if [[ ! -f $PROJECTDIR/pillow-depends-main.zip ]]; then
echo "Download pillow dependency sources..."
curl -fSL -o $PROJECTDIR/pillow-depends-main.zip https://github.com/python-pillow/pillow-depends/archive/main.zip
fi
echo "Unpacking pillow dependency sources..."
untar $PROJECTDIR/pillow-depends-main.zip
fi
if [[ -n "$IS_MACOS" ]]; then if [[ -n "$IS_MACOS" ]]; then
# libtiff and libxcb cause a conflict with building libtiff and libxcb # Homebrew (or similar packaging environments) install can contain some of
# libxau and libxdmcp cause an issue on macOS < 11 # the libraries that we're going to build. However, they may be compiled
# remove cairo to fix building harfbuzz on arm64 # with a MACOSX_DEPLOYMENT_TARGET that doesn't match what we want to use,
# remove lcms2 and libpng to fix building openjpeg on arm64 # and they may bring in other dependencies that we don't want. The same will
# remove jpeg-turbo to avoid inclusion on arm64 # be true of any other locations on the path. To avoid conflicts, strip the
# remove webp and zstd to avoid inclusion on x86_64 # path down to the bare minimum (which, on macOS, won't include any
# curl from brew requires zstd, use system curl # development dependencies).
brew remove --ignore-dependencies libpng libtiff libxcb libxau libxdmcp curl cairo lcms2 zstd export PATH="$BUILD_PREFIX/bin:$(dirname $(which python3)):/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
if [[ "$CIBW_ARCHS" == "arm64" ]]; then export CMAKE_PREFIX_PATH=$BUILD_PREFIX
brew remove --ignore-dependencies jpeg-turbo
else
brew remove --ignore-dependencies webp
fi
brew install pkg-config # Ensure the basic structure of the build prefix directory exists.
mkdir -p "$BUILD_PREFIX/bin"
mkdir -p "$BUILD_PREFIX/lib"
# Ensure pkg-config is available
build_pkg_config
# Ensure cmake is available
python3 -m pip install cmake
fi fi
wrap_wheel_builder build wrap_wheel_builder build
# Return to the project root to finish the build
popd > /dev/null
# Append licenses # Append licenses
for filename in wheels/dependency_licenses/*; do for filename in wheels/dependency_licenses/*; do
echo -e "\n\n----\n\n$(basename $filename | cut -f 1 -d '.')\n" | cat >> LICENSE echo -e "\n\n----\n\n$(basename $filename | cut -f 1 -d '.')\n" | cat >> LICENSE

View File

@ -11,6 +11,9 @@ if ("$venv" -like "*\cibw-run-*\pp*-win_amd64\*") {
$env:path += ";$pillow\winbuild\build\bin\" $env:path += ";$pillow\winbuild\build\bin\"
& "$venv\Scripts\activate.ps1" & "$venv\Scripts\activate.ps1"
& reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f & reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f
if ("$venv" -like "*\cibw-run-*-win_amd64\*") {
& python -m pip install numpy
}
cd $pillow cd $pillow
& python -VV & python -VV
if (!$?) { exit $LASTEXITCODE } if (!$?) { exit $LASTEXITCODE }

View File

@ -1,26 +1,31 @@
#!/bin/bash #!/bin/bash
set -e set -e
# Ensure fribidi is installed by the system.
if [[ "$OSTYPE" == "darwin"* ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then
brew install fribidi # If Homebrew is on the path during the build, it may leak into the wheels.
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig" # However, we *do* need Homebrew to provide a copy of fribidi for
if [ -f /opt/homebrew/lib/libfribidi.dylib ]; then # testing purposes so that we can verify the fribidi shim works as expected.
sudo cp /opt/homebrew/lib/libfribidi.dylib /usr/local/lib if [[ "$(uname -m)" == "x86_64" ]]; then
HOMEBREW_PREFIX=/usr/local
else
HOMEBREW_PREFIX=/opt/homebrew
fi fi
$HOMEBREW_PREFIX/bin/brew install fribidi
# Add the lib folder for fribidi so that the vendored library can be found.
# Don't use $HOMEWBREW_PREFIX/lib directly - use the lib folder where the
# installed copy of fribidi is cellared. This ensures we don't pick up the
# Homebrew version of any other library that we're dependent on (most notably,
# freetype).
export DYLD_LIBRARY_PATH=$(dirname $(realpath $HOMEBREW_PREFIX/lib/libfribidi.dylib))
elif [ "${AUDITWHEEL_POLICY::9}" == "musllinux" ]; then elif [ "${AUDITWHEEL_POLICY::9}" == "musllinux" ]; then
apk add curl fribidi apk add curl fribidi
else else
yum install -y fribidi yum install -y fribidi
fi fi
if [ "${AUDITWHEEL_POLICY::9}" != "musllinux" ]; then python3 -m pip install numpy
# TODO Update condition when NumPy supports free-threading
if [ $(python3 -c "import sysconfig;print(sysconfig.get_config_var('Py_GIL_DISABLED'))") == "1" ]; then
python3 -m pip install numpy --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
else
python3 -m pip install numpy
fi
fi
if [ ! -d "test-images-main" ]; then if [ ! -d "test-images-main" ]; then
curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip

View File

@ -13,6 +13,7 @@ on:
paths: paths:
- ".ci/requirements-cibw.txt" - ".ci/requirements-cibw.txt"
- ".github/workflows/wheel*" - ".github/workflows/wheel*"
- "pyproject.toml"
- "setup.py" - "setup.py"
- "wheels/*" - "wheels/*"
- "winbuild/build_prepare.py" - "winbuild/build_prepare.py"
@ -23,6 +24,7 @@ on:
paths: paths:
- ".ci/requirements-cibw.txt" - ".ci/requirements-cibw.txt"
- ".github/workflows/wheel*" - ".github/workflows/wheel*"
- "pyproject.toml"
- "setup.py" - "setup.py"
- "wheels/*" - "wheels/*"
- "winbuild/build_prepare.py" - "winbuild/build_prepare.py"
@ -40,75 +42,31 @@ env:
FORCE_COLOR: 1 FORCE_COLOR: 1
jobs: jobs:
build-1-QEMU-emulated-wheels: build-native-wheels:
if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' if: github.event_name != 'schedule' || github.repository_owner == 'python-pillow'
name: aarch64 ${{ matrix.python-version }} ${{ matrix.spec }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- pp39
- pp310
- cp3{9,10,11}
- cp3{12,13}
spec:
- manylinux2014
- manylinux_2_28
- musllinux
exclude:
- { python-version: pp39, spec: musllinux }
- { python-version: pp310, spec: musllinux }
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-python@v5
with:
python-version: "3.x"
# https://github.com/docker/setup-qemu-action
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Install cibuildwheel
run: |
python3 -m pip install -r .ci/requirements-cibw.txt
- name: Build wheels
run: |
python3 -m cibuildwheel --output-dir wheelhouse
env:
# Build only the currently selected Linux architecture (so we can
# parallelise for speed).
CIBW_ARCHS: "aarch64"
# Likewise, select only one Python version per job to speed this up.
CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*"
CIBW_PRERELEASE_PYTHONS: True
# Extra options for manylinux.
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }}
CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }}
- uses: actions/upload-artifact@v4
with:
name: dist-qemu-${{ matrix.python-version }}-${{ matrix.spec }}
path: ./wheelhouse/*.whl
build-2-native-wheels:
name: ${{ matrix.name }} name: ${{ matrix.name }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- name: "macOS x86_64" - name: "macOS 10.10 x86_64"
os: macos-13 os: macos-13
cibw_arch: x86_64 cibw_arch: x86_64
build: "cp3{9,10,11}*"
macosx_deployment_target: "10.10" macosx_deployment_target: "10.10"
- name: "macOS 10.13 x86_64"
os: macos-13
cibw_arch: x86_64
build: "cp3{12,13}*"
macosx_deployment_target: "10.13"
- name: "macOS 10.15 x86_64"
os: macos-13
cibw_arch: x86_64
build: "pp3*"
macosx_deployment_target: "10.15"
- name: "macOS arm64" - name: "macOS arm64"
os: macos-14 os: macos-latest
cibw_arch: arm64 cibw_arch: arm64
macosx_deployment_target: "11.0" macosx_deployment_target: "11.0"
- name: "manylinux2014 and musllinux x86_64" - name: "manylinux2014 and musllinux x86_64"
@ -119,9 +77,18 @@ jobs:
cibw_arch: x86_64 cibw_arch: x86_64
build: "*manylinux*" build: "*manylinux*"
manylinux: "manylinux_2_28" manylinux: "manylinux_2_28"
- name: "manylinux2014 and musllinux aarch64"
os: ubuntu-24.04-arm
cibw_arch: aarch64
- name: "manylinux_2_28 aarch64"
os: ubuntu-24.04-arm
cibw_arch: aarch64
build: "*manylinux*"
manylinux: "manylinux_2_28"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
persist-credentials: false
submodules: true submodules: true
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
@ -138,33 +105,42 @@ jobs:
env: env:
CIBW_ARCHS: ${{ matrix.cibw_arch }} CIBW_ARCHS: ${{ matrix.cibw_arch }}
CIBW_BUILD: ${{ matrix.build }} CIBW_BUILD: ${{ matrix.build }}
CIBW_FREE_THREADED_SUPPORT: True CIBW_ENABLE: cpython-prerelease cpython-freethreading pypy
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux }}
CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.manylinux }}
CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }}
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
CIBW_PRERELEASE_PYTHONS: True CIBW_SKIP: pp39-*
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }} MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
name: dist-${{ matrix.os }}-${{ matrix.cibw_arch }}${{ matrix.manylinux && format('-{0}', matrix.manylinux) }} name: dist-${{ matrix.os }}${{ matrix.macosx_deployment_target && format('-{0}', matrix.macosx_deployment_target) }}-${{ matrix.cibw_arch }}${{ matrix.manylinux && format('-{0}', matrix.manylinux) }}
path: ./wheelhouse/*.whl path: ./wheelhouse/*.whl
windows: windows:
if: github.event_name != 'schedule' || github.repository_owner == 'python-pillow'
name: Windows ${{ matrix.cibw_arch }} name: Windows ${{ matrix.cibw_arch }}
runs-on: windows-latest runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- cibw_arch: x86 - cibw_arch: x86
os: windows-latest
- cibw_arch: AMD64 - cibw_arch: AMD64
os: windows-latest
- cibw_arch: ARM64 - cibw_arch: ARM64
os: windows-11-arm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Checkout extra test images - name: Checkout extra test images
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
persist-credentials: false
repository: python-pillow/test-images repository: python-pillow/test-images
path: Tests\test-images path: Tests\test-images
@ -184,7 +160,7 @@ jobs:
# Install extra test images # Install extra test images
xcopy /S /Y Tests\test-images\* Tests\images xcopy /S /Y Tests\test-images\* Tests\images
& python.exe winbuild\build_prepare.py -v --no-imagequant --architecture=${{ matrix.cibw_arch }} & python.exe winbuild\build_prepare.py -v --no-imagequant --no-avif --architecture=${{ matrix.cibw_arch }}
shell: pwsh shell: pwsh
- name: Build wheels - name: Build wheels
@ -211,8 +187,8 @@ jobs:
CIBW_ARCHS: ${{ matrix.cibw_arch }} CIBW_ARCHS: ${{ matrix.cibw_arch }}
CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd" CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd"
CIBW_CACHE_PATH: "C:\\cibw" CIBW_CACHE_PATH: "C:\\cibw"
CIBW_FREE_THREADED_SUPPORT: True CIBW_ENABLE: cpython-prerelease cpython-freethreading pypy
CIBW_PRERELEASE_PYTHONS: True CIBW_SKIP: pp39-*
CIBW_TEST_SKIP: "*-win_arm64" CIBW_TEST_SKIP: "*-win_arm64"
CIBW_TEST_COMMAND: 'docker run --rm CIBW_TEST_COMMAND: 'docker run --rm
-v {project}:C:\pillow -v {project}:C:\pillow
@ -240,13 +216,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
cache: pip
cache-dependency-path: "Makefile"
- run: make sdist - run: make sdist
@ -256,8 +232,8 @@ jobs:
path: dist/*.tar.gz path: dist/*.tar.gz
scientific-python-nightly-wheels-publish: scientific-python-nightly-wheels-publish:
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' if: github.repository_owner == 'python-pillow' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
needs: [build-2-native-wheels, windows] needs: [build-native-wheels, windows]
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Upload wheels to scientific-python-nightly-wheels name: Upload wheels to scientific-python-nightly-wheels
steps: steps:
@ -267,14 +243,14 @@ jobs:
path: dist path: dist
merge-multiple: true merge-multiple: true
- name: Upload wheels to scientific-python-nightly-wheels - name: Upload wheels to scientific-python-nightly-wheels
uses: scientific-python/upload-nightly-action@b67d7fcc0396e1128a474d1ab2b48aa94680f9fc # 0.5.0 uses: scientific-python/upload-nightly-action@b36e8c0c10dbcfd2e05bf95f17ef8c14fd708dbf # 0.6.2
with: with:
artifacts_path: dist artifacts_path: dist
anaconda_nightly_upload_token: ${{ secrets.ANACONDA_ORG_UPLOAD_TOKEN }} anaconda_nightly_upload_token: ${{ secrets.ANACONDA_ORG_UPLOAD_TOKEN }}
pypi-publish: pypi-publish:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') if: github.repository_owner == 'python-pillow' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
needs: [build-1-QEMU-emulated-wheels, build-2-native-wheels, windows, sdist] needs: [build-native-wheels, windows, sdist]
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Upload release to PyPI name: Upload release to PyPI
environment: environment:
@ -290,3 +266,5 @@ jobs:
merge-multiple: true merge-multiple: true
- name: Publish to PyPI - name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1
with:
attestations: true

5
.gitignore vendored
View File

@ -19,6 +19,7 @@ lib64/
parts/ parts/
sdist/ sdist/
var/ var/
wheelhouse/
*.egg-info/ *.egg-info/
.installed.cfg .installed.cfg
*.egg *.egg
@ -90,5 +91,9 @@ Tests/images/msp
Tests/images/picins Tests/images/picins
Tests/images/sunraster Tests/images/sunraster
# Test and dependency downloads
pillow-depends-main.zip
pillow-test-images.zip
# pyinstaller # pyinstaller
*.spec *.spec

View File

@ -1,17 +1,17 @@
repos: repos:
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.0 rev: v0.11.4
hooks: hooks:
- id: ruff - id: ruff
args: [--exit-non-zero-on-fix] args: [--exit-non-zero-on-fix]
- repo: https://github.com/psf/black-pre-commit-mirror - repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.4.2 rev: 25.1.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/PyCQA/bandit - repo: https://github.com/PyCQA/bandit
rev: 1.7.9 rev: 1.8.3
hooks: hooks:
- id: bandit - id: bandit
args: [--severity-level=high] args: [--severity-level=high]
@ -24,7 +24,7 @@ repos:
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$) exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$)
- repo: https://github.com/pre-commit/mirrors-clang-format - repo: https://github.com/pre-commit/mirrors-clang-format
rev: v18.1.8 rev: v20.1.0
hooks: hooks:
- id: clang-format - id: clang-format
types: [c] types: [c]
@ -36,7 +36,7 @@ repos:
- id: rst-backticks - id: rst-backticks
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0 rev: v5.0.0
hooks: hooks:
- id: check-executables-have-shebangs - id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable - id: check-shebang-scripts-are-executable
@ -44,35 +44,42 @@ repos:
- id: check-json - id: check-json
- id: check-toml - id: check-toml
- id: check-yaml - id: check-yaml
args: [--allow-multiple-documents]
- id: end-of-file-fixer - id: end-of-file-fixer
exclude: ^Tests/images/ exclude: ^Tests/images/
- id: trailing-whitespace - id: trailing-whitespace
exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/ exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/
- repo: https://github.com/python-jsonschema/check-jsonschema - repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.28.6 rev: 0.32.1
hooks: hooks:
- id: check-github-workflows - id: check-github-workflows
- id: check-readthedocs - id: check-readthedocs
- id: check-renovate - id: check-renovate
- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.5.2
hooks:
- id: zizmor
- repo: https://github.com/sphinx-contrib/sphinx-lint - repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v0.9.1 rev: v1.0.0
hooks: hooks:
- id: sphinx-lint - id: sphinx-lint
- repo: https://github.com/tox-dev/pyproject-fmt - repo: https://github.com/tox-dev/pyproject-fmt
rev: 2.1.3 rev: v2.5.1
hooks: hooks:
- id: pyproject-fmt - id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject - repo: https://github.com/abravalheri/validate-pyproject
rev: v0.18 rev: v0.24.1
hooks: hooks:
- id: validate-pyproject - id: validate-pyproject
additional_dependencies: [trove-classifiers>=2024.10.12]
- repo: https://github.com/tox-dev/tox-ini-fmt - repo: https://github.com/tox-dev/tox-ini-fmt
rev: 1.3.1 rev: 1.5.0
hooks: hooks:
- id: tox-ini-fmt - id: tox-ini-fmt

View File

@ -1,5 +1,8 @@
version: 2 version: 2
sphinx:
configuration: docs/conf.py
formats: [pdf] formats: [pdf]
build: build:

View File

@ -2,9 +2,157 @@
Changelog (Pillow) Changelog (Pillow)
================== ==================
11.0.0 (unreleased) 11.1.0 and newer
----------------
See GitHub Releases:
- https://github.com/python-pillow/Pillow/releases
11.0.0 (2024-10-15)
------------------- -------------------
- Update licence to MIT-CMU #8460
[hugovk]
- Conditionally define ImageCms type hint to avoid requiring core #8197
[radarhere]
- Support writing LONG8 offsets in AppendingTiffWriter #8417
[radarhere]
- Use ImageFile.MAXBLOCK when saving TIFF images #8461
[radarhere]
- Do not close provided file handles with libtiff when saving #8458
[radarhere]
- Support ImageFilter.BuiltinFilter for I;16* images #8438
[radarhere]
- Use ImagingCore.ptr instead of ImagingCore.id #8341
[homm, radarhere, hugovk]
- Updated EPS mode when opening images without transparency #8281
[Yay295, radarhere]
- Use transparency when combining P frames from APNGs #8443
[radarhere]
- Support all resampling filters when resizing I;16* images #8422
[radarhere]
- Free memory on early return #8413
[radarhere]
- Cast int before potentially exceeding INT_MAX #8402
[radarhere]
- Check image value before use #8400
[radarhere]
- Improved copying imagequant libraries #8420
[radarhere]
- Use Capsule for WebP saving #8386
[homm, radarhere]
- Fixed writing multiple StripOffsets to TIFF #8317
[Yay295, radarhere]
- Fix dereference before checking for NULL in ImagingTransformAffine #8398
[PavlNekrasov]
- Use transposed size after opening for TIFF images #8390
[radarhere, homm]
- Improve ImageFont error messages #8338
[yngvem, radarhere, hugovk]
- Mention MAX_TEXT_CHUNK limit in PNG error message #8391
[radarhere]
- Cast Dib handle to int #8385
[radarhere]
- Accept float stroke widths #8369
[radarhere]
- Deprecate ICNS (width, height, scale) sizes in favour of load(scale) #8352
[radarhere]
- Improved handling of RGBA palettes when saving GIF images #8366
[radarhere]
- Deprecate isImageType #8364
[radarhere]
- Support converting more modes to LAB by converting to RGBA first #8358
[radarhere]
- Deprecate support for FreeType 2.9.0 #8356
[hugovk, radarhere]
- Removed unused TiffImagePlugin IFD_LEGACY_API #8355
[radarhere]
- Handle duplicate EXIF header #8350
[zakajd, radarhere]
- Return early from BoxBlur if either width or height is zero #8347
[radarhere]
- Check text is either string or bytes #8308
[radarhere]
- Added writing XMP bytes to JPEG #8286
[radarhere]
- Support JPEG2000 RGBA palettes #8256
[radarhere]
- Expand C image to match GIF frame image size #8237
[radarhere]
- Allow saving I;16 images as PPM #8231
[radarhere]
- When IFD is missing, connect get_ifd() dictionary to Exif #8230
[radarhere]
- Skip truncated ICO mask if LOAD_TRUNCATED_IMAGES is enabled #8180
[radarhere]
- Treat unknown JPEG2000 colorspace as unspecified #8343
[radarhere]
- Updated error message when saving WebP with invalid width or height #8322
[radarhere, hugovk]
- Remove warning if NumPy failed to raise an error during conversion #8326
[radarhere]
- If left and right sides meet in ImageDraw.rounded_rectangle(), do not draw rectangle to fill gap #8304
[radarhere]
- Remove WebP support without anim, mux/demux, and with buggy alpha #8213
[homm, radarhere]
- Add missing TIFF CMYK;16B reader #8298
[homm]
- Remove all WITH_* flags from _imaging.c and other flags #8211
[homm]
- Improve ImageDraw2 shape methods #8265
[radarhere]
- Lock around usages of imaging memory arenas #8238
[lysnikolaou]
- Deprecate JpegImageFile huffman_ac and huffman_dc #8274
[radarhere]
- Deprecate ImageMath lambda_eval and unsafe_eval options argument #8242 - Deprecate ImageMath lambda_eval and unsafe_eval options argument #8242
[radarhere] [radarhere]

View File

@ -5,9 +5,9 @@ The Python Imaging Library (PIL) is
Pillow is the friendly PIL fork. It is Pillow is the friendly PIL fork. It is
Copyright © 2010-2024 by Jeffrey A. Clark and contributors Copyright © 2010 by Jeffrey A. Clark and contributors
Like PIL, Pillow is licensed under the open source HPND License: Like PIL, Pillow is licensed under the open source MIT-CMU License:
By obtaining, using, and/or copying this software and/or its associated By obtaining, using, and/or copying this software and/or its associated
documentation, you agree that you have read, understood, and will comply documentation, you agree that you have read, understood, and will comply

View File

@ -20,7 +20,6 @@ graft docs
graft _custom_build graft _custom_build
# build/src control detritus # build/src control detritus
exclude .appveyor.yml
exclude .clang-format exclude .clang-format
exclude .coveragerc exclude .coveragerc
exclude .editorconfig exclude .editorconfig

View File

@ -17,14 +17,16 @@ coverage:
.PHONY: doc .PHONY: doc
.PHONY: html .PHONY: html
doc html: doc html:
python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install .
$(MAKE) -C docs html $(MAKE) -C docs html
.PHONY: htmlview .PHONY: htmlview
htmlview: htmlview:
python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install .
$(MAKE) -C docs htmlview $(MAKE) -C docs htmlview
.PHONY: htmllive
htmllive:
$(MAKE) -C docs htmllive
.PHONY: doccheck .PHONY: doccheck
doccheck: doccheck:
$(MAKE) doc $(MAKE) doc
@ -45,6 +47,7 @@ help:
@echo " docserve run an HTTP server on the docs directory" @echo " docserve run an HTTP server on the docs directory"
@echo " html make HTML docs" @echo " html make HTML docs"
@echo " htmlview open the index page built by the html target in your browser" @echo " htmlview open the index page built by the html target in your browser"
@echo " htmllive rebuild and reload HTML files in your browser"
@echo " install make and install" @echo " install make and install"
@echo " install-coverage make and install with C coverage" @echo " install-coverage make and install with C coverage"
@echo " lint run the lint checks" @echo " lint run the lint checks"
@ -117,7 +120,7 @@ lint-fix:
python3 -c "import black" > /dev/null 2>&1 || python3 -m pip install black python3 -c "import black" > /dev/null 2>&1 || python3 -m pip install black
python3 -m black . python3 -m black .
python3 -c "import ruff" > /dev/null 2>&1 || python3 -m pip install ruff python3 -c "import ruff" > /dev/null 2>&1 || python3 -m pip install ruff
python3 -m ruff --fix . python3 -m ruff check --fix .
.PHONY: mypy .PHONY: mypy
mypy: mypy:

View File

@ -42,16 +42,13 @@ As of 2019, Pillow development is
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-docker.yml"><img <a href="https://github.com/python-pillow/Pillow/actions/workflows/test-docker.yml"><img
alt="GitHub Actions build status (Test Docker)" alt="GitHub Actions build status (Test Docker)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg"></a> src="https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg"></a>
<a href="https://ci.appveyor.com/project/python-pillow/Pillow"><img
alt="AppVeyor CI build status (Windows)"
src="https://img.shields.io/appveyor/build/python-pillow/Pillow/main.svg?label=Windows%20build"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml"><img <a href="https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml"><img
alt="GitHub Actions build status (Wheels)" alt="GitHub Actions build status (Wheels)"
src="https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg"></a> src="https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg"></a>
<a href="https://app.codecov.io/gh/python-pillow/Pillow"><img <a href="https://app.codecov.io/gh/python-pillow/Pillow"><img
alt="Code coverage" alt="Code coverage"
src="https://codecov.io/gh/python-pillow/Pillow/branch/main/graph/badge.svg"></a> src="https://codecov.io/gh/python-pillow/Pillow/branch/main/graph/badge.svg"></a>
<a href="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:pillow"><img <a href="https://issues.oss-fuzz.com/issues?q=title:pillow"><img
alt="Fuzzing Status" alt="Fuzzing Status"
src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/pillow.svg"></a> src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/pillow.svg"></a>
</td> </td>
@ -98,7 +95,7 @@ This library provides extensive file format support, an efficient internal repre
The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool. The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool.
## More Information ## More information
- [Documentation](https://pillow.readthedocs.io/) - [Documentation](https://pillow.readthedocs.io/)
- [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html) - [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html)
@ -107,9 +104,9 @@ The core image library is designed for fast access to data stored in a few basic
- [Issues](https://github.com/python-pillow/Pillow/issues) - [Issues](https://github.com/python-pillow/Pillow/issues)
- [Pull requests](https://github.com/python-pillow/Pillow/pulls) - [Pull requests](https://github.com/python-pillow/Pillow/pulls)
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html) - [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Changelog](https://github.com/python-pillow/Pillow/releases)
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork) - [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
## Report a Vulnerability ## Report a vulnerability
To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security). To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security).

View File

@ -1,46 +1,25 @@
# Release Checklist # Release checklist
See https://pillow.readthedocs.io/en/stable/releasenotes/versioning.html for See https://pillow.readthedocs.io/en/stable/releasenotes/versioning.html for
information about how the version numbers line up with releases. information about how the version numbers line up with releases.
## Main Release ## Main release
Released quarterly on January 2nd, April 1st, July 1st and October 15th. Released quarterly on January 2nd, April 1st, July 1st and October 15th.
* [ ] Open a release ticket e.g. https://github.com/python-pillow/Pillow/issues/3154 * [ ] Create a new issue and select the "Maintainers only: Release" template.
* [ ] Develop and prepare release in `main` branch.
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in `main` branch. ## Point release
* [ ] Check that all the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) jobs by manually triggering them.
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
* [ ] Update `CHANGES.rst`.
* [ ] Run pre-release check via `make release-test` in a freshly cloned repo.
* [ ] Create branch and tag for release e.g.:
```bash
git branch 5.2.x
git tag 5.2.0
git push --tags
```
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
has passed, including the "Upload release to PyPI" job. This will have been triggered
by the new tag.
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases).
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/),
increment and append `.dev0` to version identifier in `src/PIL/_version.py` and then:
```bash
git push --all
```
## Point Release
Released as needed for security, installation or critical bug fixes. Released as needed for security, installation or critical bug fixes.
* [ ] Make necessary changes in `main` branch. * [ ] Make necessary changes in `main` branch.
* [ ] Update `CHANGES.rst`.
* [ ] Check out release branch e.g.: * [ ] Check out release branch e.g.:
```bash ```bash
git checkout -t remotes/origin/5.2.x git checkout -t remotes/origin/5.2.x
``` ```
* [ ] Cherry pick individual commits from `main` branch to release branch e.g. `5.2.x`, then `git push`. * [ ] Cherry pick individual commits from `main` branch to release branch e.g. `5.2.x`, then `git push`.
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in release branch e.g. `5.2.x`. * [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) to confirm passing tests in release branch e.g. `5.2.x`.
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py` * [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
* [ ] Run pre-release check via `make release-test`. * [ ] Run pre-release check via `make release-test`.
* [ ] Create tag for release e.g.: * [ ] Create tag for release e.g.:
@ -60,7 +39,7 @@ Released as needed for security, installation or critical bug fixes.
git push git push
``` ```
## Embargoed Release ## Embargoed release
Released as needed privately to individual vendors for critical security-related bug fixes. Released as needed privately to individual vendors for critical security-related bug fixes.
@ -84,7 +63,7 @@ Released as needed privately to individual vendors for critical security-related
git push origin 2.5.x git push origin 2.5.x
``` ```
## Publicize Release ## Publicize release
* [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321 * [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321
@ -92,7 +71,7 @@ Released as needed privately to individual vendors for critical security-related
* [ ] Make sure the [default version for Read the Docs](https://pillow.readthedocs.io/en/stable/) is up-to-date with the release changes * [ ] Make sure the [default version for Read the Docs](https://pillow.readthedocs.io/en/stable/) is up-to-date with the release changes
## Docker Images ## Docker images
* [ ] Update Pillow in the Docker Images repository * [ ] Update Pillow in the Docker Images repository
```bash ```bash

View File

@ -1,4 +1,4 @@
Pillow Tests Pillow tests
============ ============
Test scripts are named ``test_xxx.py``. Helper classes and functions can be found in ``helper.py``. Test scripts are named ``test_xxx.py``. Helper classes and functions can be found in ``helper.py``.

View File

@ -9,6 +9,6 @@ from PIL import Image
def test_j2k_overflow(tmp_path: Path) -> None: def test_j2k_overflow(tmp_path: Path) -> None:
im = Image.new("RGBA", (1024, 131584)) im = Image.new("RGBA", (1024, 131584))
target = str(tmp_path / "temp.jpc") target = tmp_path / "temp.jpc"
with pytest.raises(OSError): with pytest.raises(OSError):
im.save(target) im.save(target)

View File

@ -32,7 +32,7 @@ pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit sy
def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None: def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None:
f = str(tmp_path / "temp.png") f = tmp_path / "temp.png"
im = Image.new("L", (xdim, ydim), 0) im = Image.new("L", (xdim, ydim), 0)
im.save(f) im.save(f)

View File

@ -28,7 +28,7 @@ pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit sy
def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None: def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None:
dtype = np.uint8 dtype = np.uint8
a = np.zeros((xdim, ydim), dtype=dtype) a = np.zeros((xdim, ydim), dtype=dtype)
f = str(tmp_path / "temp.png") f = tmp_path / "temp.png"
im = Image.fromarray(a, "L") im = Image.fromarray(a, "L")
im.save(f) im.save(f)

View File

@ -3,26 +3,25 @@ from __future__ import annotations
import zlib import zlib
from io import BytesIO from io import BytesIO
import pytest
from PIL import Image, ImageFile, PngImagePlugin from PIL import Image, ImageFile, PngImagePlugin
TEST_FILE = "Tests/images/png_decompression_dos.png" TEST_FILE = "Tests/images/png_decompression_dos.png"
def test_ignore_dos_text() -> None: def test_ignore_dos_text(monkeypatch: pytest.MonkeyPatch) -> None:
ImageFile.LOAD_TRUNCATED_IMAGES = True monkeypatch.setattr(ImageFile, "LOAD_TRUNCATED_IMAGES", True)
try: with Image.open(TEST_FILE) as im:
im = Image.open(TEST_FILE)
im.load() im.load()
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
assert isinstance(im, PngImagePlugin.PngImageFile) assert isinstance(im, PngImagePlugin.PngImageFile)
for s in im.text.values(): for s in im.text.values():
assert len(s) < 1024 * 1024, "Text chunk larger than 1M" assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
for s in im.info.values(): for s in im.info.values():
assert len(s) < 1024 * 1024, "Text chunk larger than 1M" assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
def test_dos_text() -> None: def test_dos_text() -> None:

View File

@ -1,9 +1,12 @@
from __future__ import annotations from __future__ import annotations
import platform
import sys import sys
from PIL import features from PIL import features
from .helper import is_pypy
def test_wheel_modules() -> None: def test_wheel_modules() -> None:
expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp"} expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp"}
@ -34,10 +37,13 @@ def test_wheel_features() -> None:
"fribidi", "fribidi",
"harfbuzz", "harfbuzz",
"libjpeg_turbo", "libjpeg_turbo",
"zlib_ng",
"xcb", "xcb",
} }
if sys.platform == "win32": if sys.platform == "win32":
expected_features.remove("xcb") expected_features.remove("xcb")
elif sys.platform == "darwin" and not is_pypy() and platform.processor() != "arm":
expected_features.remove("zlib_ng")
assert set(features.get_supported_features()) == expected_features assert set(features.get_supported_features()) == expected_features

View File

@ -9,11 +9,11 @@ import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
import sysconfig
import tempfile import tempfile
from collections.abc import Sequence from collections.abc import Sequence
from functools import lru_cache from functools import lru_cache
from io import BytesIO from io import BytesIO
from pathlib import Path
from typing import Any, Callable from typing import Any, Callable
import pytest import pytest
@ -96,7 +96,10 @@ def assert_image_equal(a: Image.Image, b: Image.Image, msg: str | None = None) -
def assert_image_equal_tofile( def assert_image_equal_tofile(
a: Image.Image, filename: str, msg: str | None = None, mode: str | None = None a: Image.Image,
filename: str | Path,
msg: str | None = None,
mode: str | None = None,
) -> None: ) -> None:
with Image.open(filename) as img: with Image.open(filename) as img:
if mode: if mode:
@ -137,21 +140,14 @@ def assert_image_similar(
def assert_image_similar_tofile( def assert_image_similar_tofile(
a: Image.Image, a: Image.Image,
filename: str, filename: str | Path,
epsilon: float, epsilon: float,
msg: str | None = None, msg: str | None = None,
mode: str | None = None,
) -> None: ) -> None:
with Image.open(filename) as img: with Image.open(filename) as img:
if mode:
img = img.convert(mode)
assert_image_similar(a, img, epsilon, msg) assert_image_similar(a, img, epsilon, msg)
def assert_all_same(items: Sequence[Any], msg: str | None = None) -> None:
assert items.count(items[0]) == len(items), msg
def assert_not_all_same(items: Sequence[Any], msg: str | None = None) -> None: def assert_not_all_same(items: Sequence[Any], msg: str | None = None) -> None:
assert items.count(items[0]) != len(items), msg assert items.count(items[0]) != len(items), msg
@ -327,16 +323,7 @@ def magick_command() -> list[str] | None:
return None return None
def on_appveyor() -> bool:
return "APPVEYOR" in os.environ
def on_github_actions() -> bool:
return "GITHUB_ACTIONS" in os.environ
def on_ci() -> bool: def on_ci() -> bool:
# GitHub Actions and AppVeyor have "CI"
return "CI" in os.environ return "CI" in os.environ
@ -358,10 +345,6 @@ def is_pypy() -> bool:
return hasattr(sys, "pypy_translation_info") return hasattr(sys, "pypy_translation_info")
def is_mingw() -> bool:
return sysconfig.get_platform() == "mingw"
class CachedProperty: class CachedProperty:
def __init__(self, func: Callable[[Any], Any]) -> None: def __init__(self, func: Callable[[Any], Any]) -> None:
self.func = func self.func = func

BIN
Tests/images/avif/exif.avif Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Tests/images/avif/star.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
Tests/images/avif/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

BIN
Tests/images/eps/1.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,260 @@
GIMP Palette
Name: fullpalette
Columns: 4
#
0 0 0 Index 0
1 1 1 Index 1
2 2 2 Index 2
3 3 3 Index 3
4 4 4 Index 4
5 5 5 Index 5
6 6 6 Index 6
7 7 7 Index 7
8 8 8 Index 8
9 9 9 Index 9
10 10 10 Index 10
11 11 11 Index 11
12 12 12 Index 12
13 13 13 Index 13
14 14 14 Index 14
15 15 15 Index 15
16 16 16 Index 16
17 17 17 Index 17
18 18 18 Index 18
19 19 19 Index 19
20 20 20 Index 20
21 21 21 Index 21
22 22 22 Index 22
23 23 23 Index 23
24 24 24 Index 24
25 25 25 Index 25
26 26 26 Index 26
27 27 27 Index 27
28 28 28 Index 28
29 29 29 Index 29
30 30 30 Index 30
31 31 31 Index 31
32 32 32 Index 32
33 33 33 Index 33
34 34 34 Index 34
35 35 35 Index 35
36 36 36 Index 36
37 37 37 Index 37
38 38 38 Index 38
39 39 39 Index 39
40 40 40 Index 40
41 41 41 Index 41
42 42 42 Index 42
43 43 43 Index 43
44 44 44 Index 44
45 45 45 Index 45
46 46 46 Index 46
47 47 47 Index 47
48 48 48 Index 48
49 49 49 Index 49
50 50 50 Index 50
51 51 51 Index 51
52 52 52 Index 52
53 53 53 Index 53
54 54 54 Index 54
55 55 55 Index 55
56 56 56 Index 56
57 57 57 Index 57
58 58 58 Index 58
59 59 59 Index 59
60 60 60 Index 60
61 61 61 Index 61
62 62 62 Index 62
63 63 63 Index 63
64 64 64 Index 64
65 65 65 Index 65
66 66 66 Index 66
67 67 67 Index 67
68 68 68 Index 68
69 69 69 Index 69
70 70 70 Index 70
71 71 71 Index 71
72 72 72 Index 72
73 73 73 Index 73
74 74 74 Index 74
75 75 75 Index 75
76 76 76 Index 76
77 77 77 Index 77
78 78 78 Index 78
79 79 79 Index 79
80 80 80 Index 80
81 81 81 Index 81
82 82 82 Index 82
83 83 83 Index 83
84 84 84 Index 84
85 85 85 Index 85
86 86 86 Index 86
87 87 87 Index 87
88 88 88 Index 88
89 89 89 Index 89
90 90 90 Index 90
91 91 91 Index 91
92 92 92 Index 92
93 93 93 Index 93
94 94 94 Index 94
95 95 95 Index 95
96 96 96 Index 96
97 97 97 Index 97
98 98 98 Index 98
99 99 99 Index 99
100 100 100 Index 100
101 101 101 Index 101
102 102 102 Index 102
103 103 103 Index 103
104 104 104 Index 104
105 105 105 Index 105
106 106 106 Index 106
107 107 107 Index 107
108 108 108 Index 108
109 109 109 Index 109
110 110 110 Index 110
111 111 111 Index 111
112 112 112 Index 112
113 113 113 Index 113
114 114 114 Index 114
115 115 115 Index 115
116 116 116 Index 116
117 117 117 Index 117
118 118 118 Index 118
119 119 119 Index 119
120 120 120 Index 120
121 121 121 Index 121
122 122 122 Index 122
123 123 123 Index 123
124 124 124 Index 124
125 125 125 Index 125
126 126 126 Index 126
127 127 127 Index 127
128 128 128 Index 128
129 129 129 Index 129
130 130 130 Index 130
131 131 131 Index 131
132 132 132 Index 132
133 133 133 Index 133
134 134 134 Index 134
135 135 135 Index 135
136 136 136 Index 136
137 137 137 Index 137
138 138 138 Index 138
139 139 139 Index 139
140 140 140 Index 140
141 141 141 Index 141
142 142 142 Index 142
143 143 143 Index 143
144 144 144 Index 144
145 145 145 Index 145
146 146 146 Index 146
147 147 147 Index 147
148 148 148 Index 148
149 149 149 Index 149
150 150 150 Index 150
151 151 151 Index 151
152 152 152 Index 152
153 153 153 Index 153
154 154 154 Index 154
155 155 155 Index 155
156 156 156 Index 156
157 157 157 Index 157
158 158 158 Index 158
159 159 159 Index 159
160 160 160 Index 160
161 161 161 Index 161
162 162 162 Index 162
163 163 163 Index 163
164 164 164 Index 164
165 165 165 Index 165
166 166 166 Index 166
167 167 167 Index 167
168 168 168 Index 168
169 169 169 Index 169
170 170 170 Index 170
171 171 171 Index 171
172 172 172 Index 172
173 173 173 Index 173
174 174 174 Index 174
175 175 175 Index 175
176 176 176 Index 176
177 177 177 Index 177
178 178 178 Index 178
179 179 179 Index 179
180 180 180 Index 180
181 181 181 Index 181
182 182 182 Index 182
183 183 183 Index 183
184 184 184 Index 184
185 185 185 Index 185
186 186 186 Index 186
187 187 187 Index 187
188 188 188 Index 188
189 189 189 Index 189
190 190 190 Index 190
191 191 191 Index 191
192 192 192 Index 192
193 193 193 Index 193
194 194 194 Index 194
195 195 195 Index 195
196 196 196 Index 196
197 197 197 Index 197
198 198 198 Index 198
199 199 199 Index 199
200 200 200 Index 200
201 201 201 Index 201
202 202 202 Index 202
203 203 203 Index 203
204 204 204 Index 204
205 205 205 Index 205
206 206 206 Index 206
207 207 207 Index 207
208 208 208 Index 208
209 209 209 Index 209
210 210 210 Index 210
211 211 211 Index 211
212 212 212 Index 212
213 213 213 Index 213
214 214 214 Index 214
215 215 215 Index 215
216 216 216 Index 216
217 217 217 Index 217
218 218 218 Index 218
219 219 219 Index 219
220 220 220 Index 220
221 221 221 Index 221
222 222 222 Index 222
223 223 223 Index 223
224 224 224 Index 224
225 225 225 Index 225
226 226 226 Index 226
227 227 227 Index 227
228 228 228 Index 228
229 229 229 Index 229
230 230 230 Index 230
231 231 231 Index 231
232 232 232 Index 232
233 233 233 Index 233
234 234 234 Index 234
235 235 235 Index 235
236 236 236 Index 236
237 237 237 Index 237
238 238 238 Index 238
239 239 239 Index 239
240 240 240 Index 240
241 241 241 Index 241
242 242 242 Index 242
243 243 243 Index 243
244 244 244 Index 244
245 245 245 Index 245
246 246 246 Index 246
247 247 247 Index 247
248 248 248 Index 248
249 249 249 Index 249
250 250 250 Index 250
251 251 251 Index 251
252 252 252 Index 252
253 253 253 Index 253
254 254 254 Index 254
255 255 255 Index 255

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

View File

@ -16,8 +16,9 @@
import atheris import atheris
from atheris.import_hook import instrument_imports
with atheris.instrument_imports(): with instrument_imports():
import sys import sys
import fuzzers import fuzzers

View File

@ -14,8 +14,9 @@
import atheris import atheris
from atheris.import_hook import instrument_imports
with atheris.instrument_imports(): with instrument_imports():
import sys import sys
import fuzzers import fuzzers

View File

@ -1,5 +1,5 @@
{ {
<py3_8_encode_current_locale> <py3_10_encode_current_locale>
Memcheck:Cond Memcheck:Cond
... ...
fun:encode_current_locale fun:encode_current_locale

Some files were not shown because too many files have changed in this diff Show More