Repository navigation
Release Pillow 11.2.0 on April 1, 2025 #8722
Description
Activity
- pinned this issue
on Jan 31, 2025 Release under way: https://github.com/python-pillow/Pillow/actions/runs/14194276478
Wheel build done.
But we've finally hit the PyPI project limit of 10 GB during upload:
WARNING Error during upload. Retry with the --verbose option for more details. ERROR HTTPError: 400 Bad Request from https://upload.pypi.org/legacy/ Project size too large. Limit for project 'pillow' total size is 10 GB. See https://docs.pypi.org/project-management/storage-limits#requesting-a-project-size-limit-increasehttps://github.com/python-pillow/Pillow/actions/runs/14194276478/job/39774057701
I'll request an increase.
73/80 wheels files made it up, sdist not there yet.
The last release had 70 wheels and an sdist and is about 296 MB, an average 4.2 MB per file.
https://pypi.org/project/pillow/11.1.0/#files
This one is 80 wheels and an sdist and is 1.15 GB, an average of 14.2 MB per file.
https://github.com/python-pillow/Pillow/actions/runs/14194276478
It's caused by the new AVIF binaries (#5201).
A couple of comparisons.
Pillow 11.1.0 11.2.0 Times bigger cp313-cp313-macosx_11_0_arm64.whl 3.0 MB 8.5 MB 2.83x cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.2 MB 18 MB 4.29x The avif .so file is a lot bigger than the next biggest .so file. In the manylinux wheel:
11.2.0 Size _avif.cpython-313-x86_64-linux-gnu.so 48 MB _imaging.cpython-313-x86_64-linux-gnu.so 3.3 MB In the macOS wheel:
11.2.0 Size _avif.cpython-313-darwin.so 15 MB _imaging.cpython-313-darwin.so 0.56 MB Wheel files are zip files which means the .so files are compressed, but it makes our release more than 3x as big.
Reacted by Michal PortešFilename 11.1.0 11.2.0 Times bigger 1 cp39-cp39-macosx_10_10_x86_64.whl 3.2 MB 11.4 MB 3.56x 2 cp39-cp39-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 3 cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 4.3 MB 17.1 MB 3.98x 4 cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.4 MB 18.9 MB 4.30x 5 cp39-cp39-manylinux_2_28_aarch64.whl 4.4 MB 17.6 MB 4.00x 6 cp39-cp39-manylinux_2_28_x86_64.whl 4.5 MB 19.6 MB 4.36x 7 cp39-cp39-musllinux_1_2_aarch64.whl 4.3 MB 18.0 MB 4.19x 8 cp39-cp39-musllinux_1_2_x86_64.whl 4.4 MB 19.8 MB 4.50x 9 cp39-cp39-win32.whl 2.3 MB 2.3 MB 1.00x 10 cp39-cp39-win_amd64.whl 2.6 MB 13.8 MB 5.31x 11 cp39-cp39-win_arm64.whl 2.4 MB 2.4 MB 1.00x 12 cp310-cp310-macosx_10_10_x86_64.whl 3.2 MB 11.4 MB 3.56x 13 cp310-cp310-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 14 cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 4.3 MB 17.1 MB 3.98x 15 cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.4 MB 18.9 MB 4.30x 16 cp310-cp310-manylinux_2_28_aarch64.whl 4.4 MB 17.6 MB 4.00x 17 cp310-cp310-manylinux_2_28_x86_64.whl 4.5 MB 19.6 MB 4.36x 18 cp310-cp310-musllinux_1_2_aarch64.whl 4.3 MB 18.0 MB 4.19x 19 cp310-cp310-musllinux_1_2_x86_64.whl 4.4 MB 19.8 MB 4.50x 20 cp310-cp310-win32.whl 2.3 MB 2.3 MB 1.00x 21 cp310-cp310-win_amd64.whl 2.6 MB 13.8 MB 5.31x 22 cp310-cp310-win_arm64.whl 2.4 MB 2.4 MB 1.00x 23 cp311-cp311-macosx_10_10_x86_64.whl 3.2 MB 11.4 MB 3.56x 24 cp311-cp311-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 25 cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 4.3 MB 17.1 MB 3.98x 26 cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.4 MB 18.9 MB 4.30x 27 cp311-cp311-manylinux_2_28_aarch64.whl 4.4 MB 17.6 MB 4.00x 28 cp311-cp311-manylinux_2_28_x86_64.whl 4.5 MB 19.6 MB 4.36x 29 cp311-cp311-musllinux_1_2_aarch64.whl 4.3 MB 18.0 MB 4.19x 30 cp311-cp311-musllinux_1_2_x86_64.whl 4.4 MB 19.8 MB 4.50x 31 cp311-cp311-win32.whl 2.3 MB 2.3 MB 1.00x 32 cp311-cp311-win_amd64.whl 2.6 MB 13.8 MB 5.31x 33 cp311-cp311-win_arm64.whl 2.4 MB 2.4 MB 1.00x 34 cp312-cp312-macosx_10_13_x86_64.whl 3.2 MB 11.4 MB 3.56x 35 cp312-cp312-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 36 cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 4.3 MB 17.1 MB 3.98x 37 cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.4 MB 18.9 MB 4.30x 38 cp312-cp312-manylinux_2_28_aarch64.whl 4.4 MB 17.6 MB 4.00x 39 cp312-cp312-manylinux_2_28_x86_64.whl 4.5 MB 19.6 MB 4.36x 40 cp312-cp312-musllinux_1_2_aarch64.whl 4.3 MB 18.0 MB 4.19x 41 cp312-cp312-musllinux_1_2_x86_64.whl 4.4 MB 19.8 MB 4.50x 42 cp312-cp312-win32.whl 2.3 MB 2.3 MB 1.00x 43 cp312-cp312-win_amd64.whl 2.6 MB 13.8 MB 5.31x 44 cp312-cp312-win_arm64.whl 2.4 MB 2.4 MB 1.00x 45 cp313-cp313-macosx_10_13_x86_64.whl 3.2 MB 11.4 MB 3.56x 46 cp313-cp313-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 47 cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 4.3 MB 17.1 MB 3.98x 48 cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.4 MB 18.9 MB 4.30x 49 cp313-cp313-manylinux_2_28_aarch64.whl 4.4 MB 17.6 MB 4.00x 50 cp313-cp313-manylinux_2_28_x86_64.whl 4.5 MB 19.6 MB 4.36x 51 cp313-cp313-musllinux_1_2_aarch64.whl 4.3 MB 18.0 MB 4.19x 52 cp313-cp313-musllinux_1_2_x86_64.whl 4.4 MB 19.8 MB 4.50x 53 cp313-cp313-win32.whl 2.3 MB 2.3 MB 1.00x 54 cp313-cp313-win_amd64.whl 2.6 MB 13.8 MB 5.31x 55 cp313-cp313-win_arm64.whl 2.4 MB 2.4 MB 1.00x 56 cp313-cp313t-macosx_10_13_x86_64.whl 3.2 MB 11.4 MB 3.56x 57 cp313-cp313t-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 58 cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 4.4 MB 17.1 MB 3.89x 59 cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 4.4 MB 18.9 MB 4.30x 60 cp313-cp313t-manylinux_2_28_aarch64.whl 4.5 MB 17.6 MB 3.91x 61 cp313-cp313t-manylinux_2_28_x86_64.whl 4.5 MB 19.6 MB 4.36x 62 cp313-cp313t-musllinux_1_2_x86_64.whl 4.5 MB 19.8 MB 4.40x 63 cp313-cp313t-win32.whl 2.3 MB 2.3 MB 1.00x 64 cp313-cp313t-win_amd64.whl 2.6 MB 13.8 MB 5.31x 65 cp313-cp313t-win_arm64.whl 2.4 MB 2.4 MB 1.00x 66 pp310-pypy310_pp73-macosx_10_15_x86_64.whl 3.2 MB 11.4 MB 3.56x 67 pp310-pypy310_pp73-macosx_11_0_arm64.whl 3.1 MB 8.9 MB 2.87x 68 pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 3.4 MB 16.1 MB 4.74x 69 pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 3.4 MB 17.8 MB 5.24x 70 pp310-pypy310_pp73-manylinux_2_28_aarch64.whl 3.4 MB 16.6 MB 4.88x 71 pp310-pypy310_pp73-manylinux_2_28_x86_64.whl 3.5 MB 18.5 MB 5.29x 72 pp310-pypy310_pp73-win_amd64.whl 2.6 MB 13.2 MB 5.08x 73 pp311-pypy311_pp73-macosx_10_15_x86_64.whl 11.4 MB 74 pp311-pypy311_pp73-macosx_11_0_arm64.whl 8.9 MB 75 pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl 16.1 MB 76 pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 17.8 MB 77 pp311-pypy311_pp73-manylinux_2_28_aarch64.whl 16.6 MB 78 pp311-pypy311_pp73-manylinux_2_28_x86_64.whl 18.5 MB 79 pp311-pypy311_pp73-win_amd64.whl 13.2 MB Total 258 MB 1.06 GB 4.2x Requested a limit increase from 10 GB to 20 GB: pypi/support#6014.
Opened #8856 to see if we can reduce the wheel size.
Reacted by Michal PortešWhile the release is in a half-released state, plus there's some uncertainty about the wheel sizes, I suggest we "yank" 11.2.0 on PyPI.
Yanking is a reversible action, the files remain on PyPI but are only installed if you specifically request 11.2.0. You won't get it with a normal install or upgrade.
If we choose not to do anything about the wheel size for this release, and when we get a limit increase, we can un-yank the release and upload the remaining files.
Reacted by Jeffrey 'Alex' Clark, Sohang Chopra, Michal Porteš and Alex Schroeder@aclark4life / @wiredfool Please could you give @radarhere and me owner permission on PyPI so we can yank this release?
Reacted by Jeffrey 'Alex' Clark@hugovk Done
Thanks, 11.2.0 has been yanked for now.
@wiredfool @hugovk @radarhere thanks for all the extra hard work getting this one out
Reacted by Hugo van Kemenade7 remaining items
Great! Let's confirm with @hugovk and then go for it, thanks.
I'm AFK right now and can check it over later today, and do the release.
Good news, we got the PyPI increase:
And they also asked if we can use the Limited API, which would drastically reduce the amount of wheels we need. I'm not sure how feasible that is for something of Pillow's vintage and size, but something to look into at some point.
https://docs.python.org/3/c-api/stable.html#limited-c-api
For the release, let's stick to the plan of deleting 11.2.0 and doing 11.2.1.
Let's put something in the release notes to say why this is 11.2.1 and 11.2.0 is pining for the fjörds.
Are there any other PRs that are important to include in this release, beyond the dependency and docs updates?
Reacted by doublex and Jeffrey 'Alex' ClarkAre there any other PRs that are important to include in this release, beyond the dependency and docs updates?
No, I don't think anything else stands out.
And they also asked if we can use the Limited API
I attempted this briefly, and ran into a problem with PyTypeObject - https://docs.python.org/3/c-api/typeobj.html#static-types
since PyTypeObject is only part of the Limited API as an opaque struct, any extension modules using static types must be compiled for a specific Python minor version.
Reacted by Hugo van Kemenade, doublex and Andrey Efremov- Do not include libavif in wheels #8876 is merged
- Add 11.2.1 release notes #8885 updates release notes for 11.2.1
- I'll un-yank 11.2.0 from PyPI so I can delete it (there's no option to delete a yanked release)
- I'll delete the 11.2.0 tag from the repo
- I'll create a new release issue for 11.2.1 with a fresh release checklist and close this
- and then release 11.2.1
11.2.0 tag deleted.
For the record, it was commit 09adcfb.
❯ git show 11.2.0 Found existing alias for "git show". You should use: "gsh" commit 09adcfb4e4bd1ad57896ea176a021d396a7965f4 (tag: 11.2.0) Author: Hugo van Kemenade <[email protected]> Date: Tue Apr 1 12:49:21 2025 +0300 11.2.0 version bump Δ src/PIL/_version.py ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ─────┐ • 1: │ ─────┘ 1 ⋮ 1 │# Master version for Pillow 2 ⋮ 2 │from __future__ import annotations 3 ⋮ 3 │ 4 ⋮ │__version__ = "11.2.0.dev0" ⋮ 4 │__version__ = "11.2.0"
Reacted by dzx-cptbtptpLet's continue 11.2.1 in #8886.
Reacted by Jeffrey 'Alex' Clark- unpinned this issue
on Apr 12, 2025 @hugovk Is there any scenario in which we'd leave the yanked release in place? Or to put it another way, isn't yanking sufficient and preferable over deleting in order to prevent downloads and leave a trail of what happened? That's my current understanding but I could be wrong 😄
It's already deleted, but in theory, if it was left as yanked, then
pip install pillow==11.2.0would still install it -- but only for those platforms that had wheels uploaded. And there was no source zip, to even try building on the other platforms; or for people who don't want wheels, and want to build their own release from source.We don't want that 11.2.0 install to happen in this case, because we removed a feature from there without our normal one-year deprecation period.
So because the release was never completed, I think this is okay -- we've decided 11.2.0 never existed.
If we'd left 11.2.0 as yanked, I would have still wanted to respect out deprecation period.
A case where you may want to yank without deleting: a release was made successfully. But then you discover some ugly bug and fix it. You can then yank the old one, so it doesn't install "normally", but also doesn't break people who have pinned it in their lockfiles. They can upgrade with care as normal for the new release.
Reacted by Jeffrey 'Alex' Clarkimo:
A case where you may want to yank without deleting: a release was made successfully. But then you discover some ugly bug and fix it. You can then yank the old one, so it doesn't install "normally", but also doesn't break people who have pinned it in their lockfiles. They can upgrade with care as normal for the new release.
is exactly what happened here with:
because we removed a feature from [11.2.0] without our normal one-year deprecation period.
(I'm here during a failing production deployment after we ran 11.2.0 through test environments no problem.)
An inadvertent breaking change is a bug, a bugfix is a patch release, doing that in 11.2.1 with the known bug in 11.2.0 is absolutely fine and normal as far as I'm concerned, and would've not caused us a problem (whereas this procedure did).
Reacted by Jeffrey 'Alex' ClarkThanks for letting us know!
We were in the situation where 11.2.0 hadn't been fully released and we were unable to complete the release at the time. The source and many wheels were missing from PyPI, and we hadn't pushed the tags here.
And then we decided to remove features from planned-11.2.0, so it wasn't a bugfix, but feature removal without deprecation. I don't think that would be appropriate in a normal patch release.
I'm curious, do you know how you managed to pick up 11.2.0 in the first place?
(It was partially released and un-yanked for about 18 hours.)
Reacted by Oliver FordFrom a Dependabot PR created 1 April 23:18 GMT. (I'd link but private repo.)
Reacted by Hugo van Kemenade and Sam StephensGot it, so the Dependabot update passed with 11.2.0 during the window, was merged, the yank also didn't cause problems because it was still pinned, but then the delete broke things.
I do hope we won't have to delete, or yank, anything in the future, but won't do so without careful consideration.
Thanks again!
Reacted by Oliver Ford

Main Release
Released quarterly on January 2nd, April 1st, July 1st and October 15th.
mainbranch.mainbranch.src/PIL/_version.pymake release-testin a freshly cloned repo..dev0to version identifier insrc/PIL/_version.pyand then:Publicize Release
Documentation
Docker Images
git clone https://github.com/python-pillow/docker-images cd docker-images ./update-pillow-tag.sh [[release tag]]