Merge branch 'main' into vtf-support
							
								
								
									
										100
									
								
								.appveyor.yml
									
									
									
									
									
								
							
							
						
						|  | @ -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')) |  | ||||||
|  | @ -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 |  | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 |  | ||||||
|     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 |     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 | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| cibuildwheel==2.19.2 | cibuildwheel==2.23.3 | ||||||
|  |  | ||||||
|  | @ -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
									
								
							
							
						
						|  | @ -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 | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								.github/release-drafter.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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
									
									
								
							
							
						
						|  | @ -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 * *" | ||||||
|  |     ] | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								.github/workflows/cifuzz.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/docs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								.github/workflows/macos-install.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								.github/workflows/test-cygwin.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 }} | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								.github/workflows/test-docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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: | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								.github/workflows/test-mingw.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 }} | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/test-valgrind.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										58
									
								
								.github/workflows/test-windows.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 }} | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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: | ||||||
|  |  | ||||||
							
								
								
									
										218
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |     if [[ -n "$IS_MACOS" ]] && [[ "$MACOSX_DEPLOYMENT_TARGET" == "10.10" || "$MACOSX_DEPLOYMENT_TARGET" == "10.13" ]]; then | ||||||
|         build_new_zlib |         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 | ||||||
|  |     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 |         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 | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								.github/workflows/wheels-test.ps1
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 } | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								.github/workflows/wheels-test.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										124
									
								
								.github/workflows/wheels.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -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
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,8 @@ | ||||||
| version: 2 | version: 2 | ||||||
| 
 | 
 | ||||||
|  | sphinx: | ||||||
|  |   configuration: docs/conf.py | ||||||
|  | 
 | ||||||
| formats: [pdf] | formats: [pdf] | ||||||
| 
 | 
 | ||||||
| build: | build: | ||||||
|  |  | ||||||
							
								
								
									
										150
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						|  | @ -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] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						|  | @ -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: | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						|  | @ -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). | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								RELEASING.md
									
									
									
									
									
								
							
							
						
						|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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``. | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,19 +3,18 @@ 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(): | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/hopper-missing-pixi.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/hopper.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/hopper.heif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/hopper_avif_write.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 30 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/icc_profile.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/icc_profile_none.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot0mir0.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot0mir1.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot1mir0.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot1mir1.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot2mir0.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot2mir1.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot3mir0.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/rot3mir1.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/star.avifs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/star.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/star.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/transparency.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/avif/xmp_tags_orientation.avif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/drawing_emf_ref_72_144.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 984 B | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/eps/1.bmp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/eps/1_boundingbox_after_imagedata.eps
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/eps/1_second_imagedata.eps
									
									
									
									
									
										Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB | 
| Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB | 
| Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB | 
| Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB | 
| Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB | 
| Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB | 
							
								
								
									
										260
									
								
								Tests/images/full_gimp_palette.gpl
									
									
									
									
									
										Normal 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 | ||||||
| Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 533 B | 
| After Width: | Height: | Size: 411 B | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/imagedraw_stroke_float.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/jfif_unit_cm.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 391 B | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/multiline_text_justify.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/test_extents_transparency.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 415 B | 
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||