mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-01 00:17:27 +03:00 
			
		
		
		
	Merge branch 'main' into main
This commit is contained in:
		
						commit
						54c3c93987
					
				|  | @ -66,7 +66,7 @@ if [[ $(uname) != CYGWIN* ]]; then | |||
|     pushd depends && ./install_raqm.sh && popd | ||||
| 
 | ||||
|     # libavif | ||||
|     pushd depends && CMAKE_POLICY_VERSION_MINIMUM=3.5 ./install_libavif.sh && popd | ||||
|     pushd depends && ./install_libavif.sh && popd | ||||
| 
 | ||||
|     # extra test images | ||||
|     pushd depends && ./install_extra_test_images.sh && popd | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| cibuildwheel==2.23.2 | ||||
| cibuildwheel==2.23.3 | ||||
|  |  | |||
							
								
								
									
										46
									
								
								.github/ISSUE_TEMPLATE/RELEASE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										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]] | ||||
|   ``` | ||||
							
								
								
									
										6
									
								
								.github/workflows/test-windows.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/test-windows.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -84,7 +84,7 @@ jobs: | |||
|         python3 -m pip install --upgrade pip | ||||
| 
 | ||||
|     - name: Install CPython dependencies | ||||
|       if: "!contains(matrix.python-version, 'pypy') && matrix.architecture != 'x86'" | ||||
|       if: "!contains(matrix.python-version, 'pypy') && !contains(matrix.python-version, '3.14') && matrix.architecture != 'x86'" | ||||
|       run: | | ||||
|         python3 -m pip install PyQt6 | ||||
| 
 | ||||
|  | @ -98,8 +98,8 @@ jobs: | |||
|         choco install nasm --no-progress | ||||
|         echo "C:\Program Files\NASM" >> $env:GITHUB_PATH | ||||
| 
 | ||||
|         choco install ghostscript --version=10.5.0 --no-progress | ||||
|         echo "C:\Program Files\gs\gs10.05.0\bin" >> $env:GITHUB_PATH | ||||
|         choco install ghostscript --version=10.5.1 --no-progress | ||||
|         echo "C:\Program Files\gs\gs10.05.1\bin" >> $env:GITHUB_PATH | ||||
| 
 | ||||
|         # Install extra test images | ||||
|         xcopy /S /Y Tests\test-images\* Tests\images | ||||
|  |  | |||
							
								
								
									
										4
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							|  | @ -38,8 +38,8 @@ ARCHIVE_SDIR=pillow-depends-main | |||
| 
 | ||||
| # Package versions for fresh source builds | ||||
| FREETYPE_VERSION=2.13.3 | ||||
| HARFBUZZ_VERSION=11.1.0 | ||||
| LIBPNG_VERSION=1.6.47 | ||||
| HARFBUZZ_VERSION=11.2.1 | ||||
| LIBPNG_VERSION=1.6.48 | ||||
| JPEGTURBO_VERSION=3.1.0 | ||||
| OPENJPEG_VERSION=2.5.3 | ||||
| XZ_VERSION=5.8.1 | ||||
|  |  | |||
							
								
								
									
										7
									
								
								.github/zizmor.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.github/zizmor.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| # Configuration for the zizmor static analysis tool, run via pre-commit in CI | ||||
| # https://woodruffw.github.io/zizmor/configuration/ | ||||
| rules: | ||||
|   unpinned-uses: | ||||
|     config: | ||||
|       policies: | ||||
|         "*": ref-pin | ||||
|  | @ -1,6 +1,6 @@ | |||
| repos: | ||||
|   - repo: https://github.com/astral-sh/ruff-pre-commit | ||||
|     rev: v0.11.4 | ||||
|     rev: v0.11.8 | ||||
|     hooks: | ||||
|       - id: ruff | ||||
|         args: [--exit-non-zero-on-fix] | ||||
|  | @ -24,7 +24,7 @@ repos: | |||
|         exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$) | ||||
| 
 | ||||
|   - repo: https://github.com/pre-commit/mirrors-clang-format | ||||
|     rev: v20.1.0 | ||||
|     rev: v20.1.3 | ||||
|     hooks: | ||||
|       - id: clang-format | ||||
|         types: [c] | ||||
|  | @ -51,14 +51,14 @@ repos: | |||
|         exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/ | ||||
| 
 | ||||
|   - repo: https://github.com/python-jsonschema/check-jsonschema | ||||
|     rev: 0.32.1 | ||||
|     rev: 0.33.0 | ||||
|     hooks: | ||||
|       - id: check-github-workflows | ||||
|       - id: check-readthedocs | ||||
|       - id: check-renovate | ||||
| 
 | ||||
|   - repo: https://github.com/woodruffw/zizmor-pre-commit | ||||
|     rev: v1.5.2 | ||||
|     rev: v1.6.0 | ||||
|     hooks: | ||||
|       - id: zizmor | ||||
| 
 | ||||
|  |  | |||
|  | @ -95,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. | ||||
| 
 | ||||
| ## More Information | ||||
| ## More information | ||||
| 
 | ||||
| - [Documentation](https://pillow.readthedocs.io/) | ||||
|   - [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html) | ||||
|  | @ -107,6 +107,6 @@ The core image library is designed for fast access to data stored in a few basic | |||
| - [Changelog](https://github.com/python-pillow/Pillow/releases) | ||||
|   - [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). | ||||
|  |  | |||
							
								
								
									
										35
									
								
								RELEASING.md
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								RELEASING.md
									
									
									
									
									
								
							|  | @ -1,34 +1,15 @@ | |||
| # Release Checklist | ||||
| # Release checklist | ||||
| 
 | ||||
| See https://pillow.readthedocs.io/en/stable/releasenotes/versioning.html for | ||||
| 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. | ||||
| 
 | ||||
| * [ ] Open a release ticket e.g. https://github.com/python-pillow/Pillow/issues/3154 | ||||
| * [ ] Develop and prepare release in `main` branch. | ||||
| * [ ] 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 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 | ||||
| * [ ] Create a new issue and select the "Maintainers only: Release" template. | ||||
| 
 | ||||
| ## Point release | ||||
| 
 | ||||
| Released as needed for security, installation or critical bug fixes. | ||||
| 
 | ||||
|  | @ -58,7 +39,7 @@ Released as needed for security, installation or critical bug fixes. | |||
|   git push | ||||
|   ``` | ||||
| 
 | ||||
| ## Embargoed Release | ||||
| ## Embargoed release | ||||
| 
 | ||||
| Released as needed privately to individual vendors for critical security-related bug fixes. | ||||
| 
 | ||||
|  | @ -82,7 +63,7 @@ Released as needed privately to individual vendors for critical security-related | |||
|   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 | ||||
| 
 | ||||
|  | @ -90,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 | ||||
| 
 | ||||
| ## Docker Images | ||||
| ## Docker images | ||||
| 
 | ||||
| * [ ] Update Pillow in the Docker Images repository | ||||
|   ```bash | ||||
|  |  | |||
|  | @ -161,6 +161,12 @@ def assert_tuple_approx_equal( | |||
|             pytest.fail(msg + ": " + repr(actuals) + " != " + repr(targets)) | ||||
| 
 | ||||
| 
 | ||||
| def timeout_unless_slower_valgrind(timeout: float) -> pytest.MarkDecorator: | ||||
|     if "PILLOW_VALGRIND_TEST" in os.environ: | ||||
|         return pytest.mark.pil_noop_mark() | ||||
|     return pytest.mark.timeout(timeout) | ||||
| 
 | ||||
| 
 | ||||
| def skip_unless_feature(feature: str) -> pytest.MarkDecorator: | ||||
|     reason = f"{feature} not available" | ||||
|     return pytest.mark.skipif(not features.check(feature), reason=reason) | ||||
|  |  | |||
|  | @ -233,7 +233,7 @@ class TestFileAvif: | |||
|         with Image.open(out_gif) as reread: | ||||
|             reread_value = reread.convert("RGB").getpixel((1, 1)) | ||||
|         difference = sum([abs(original_value[i] - reread_value[i]) for i in range(3)]) | ||||
|         assert difference <= 3 | ||||
|         assert difference <= 6 | ||||
| 
 | ||||
|     def test_save_single_frame(self, tmp_path: Path) -> None: | ||||
|         temp_file = tmp_path / "temp.avif" | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ from .helper import ( | |||
|     is_win32, | ||||
|     mark_if_feature_version, | ||||
|     skip_unless_feature, | ||||
|     timeout_unless_slower_valgrind, | ||||
| ) | ||||
| 
 | ||||
| HAS_GHOSTSCRIPT = EpsImagePlugin.has_ghostscript() | ||||
|  | @ -398,7 +399,7 @@ def test_emptyline() -> None: | |||
|     assert image.format == "EPS" | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.timeout(timeout=5) | ||||
| @timeout_unless_slower_valgrind(5) | ||||
| @pytest.mark.parametrize( | ||||
|     "test_file", | ||||
|     ["Tests/images/eps/timeout-d675703545fee17acab56e5fec644c19979175de.eps"], | ||||
|  |  | |||
|  | @ -7,7 +7,12 @@ import pytest | |||
| 
 | ||||
| from PIL import FliImagePlugin, Image, ImageFile | ||||
| 
 | ||||
| from .helper import assert_image_equal, assert_image_equal_tofile, is_pypy | ||||
| from .helper import ( | ||||
|     assert_image_equal, | ||||
|     assert_image_equal_tofile, | ||||
|     is_pypy, | ||||
|     timeout_unless_slower_valgrind, | ||||
| ) | ||||
| 
 | ||||
| # created as an export of a palette image from Gimp2.6 | ||||
| # save as...-> hopper.fli, default options. | ||||
|  | @ -189,7 +194,7 @@ def test_seek() -> None: | |||
|         "Tests/images/timeout-bff0a9dc7243a8e6ede2408d2ffa6a9964698b87.fli", | ||||
|     ], | ||||
| ) | ||||
| @pytest.mark.timeout(timeout=3) | ||||
| @timeout_unless_slower_valgrind(3) | ||||
| def test_timeouts(test_file: str) -> None: | ||||
|     with open(test_file, "rb") as f: | ||||
|         with Image.open(f) as im: | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ from .helper import ( | |||
|     is_win32, | ||||
|     mark_if_feature_version, | ||||
|     skip_unless_feature, | ||||
|     timeout_unless_slower_valgrind, | ||||
| ) | ||||
| 
 | ||||
| ElementTree: ModuleType | None | ||||
|  | @ -1033,7 +1034,7 @@ class TestFileJpeg: | |||
|         with pytest.raises(ValueError): | ||||
|             im.save(f, xmp=b"1" * 65505) | ||||
| 
 | ||||
|     @pytest.mark.timeout(timeout=1) | ||||
|     @timeout_unless_slower_valgrind(1) | ||||
|     def test_eof(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||||
|         # Even though this decoder never says that it is finished | ||||
|         # the image should still end when there is no new data | ||||
|  |  | |||
|  | @ -13,7 +13,12 @@ import pytest | |||
| 
 | ||||
| from PIL import Image, PdfParser, features | ||||
| 
 | ||||
| from .helper import hopper, mark_if_feature_version, skip_unless_feature | ||||
| from .helper import ( | ||||
|     hopper, | ||||
|     mark_if_feature_version, | ||||
|     skip_unless_feature, | ||||
|     timeout_unless_slower_valgrind, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| def helper_save_as_pdf(tmp_path: Path, mode: str, **kwargs: Any) -> str: | ||||
|  | @ -339,8 +344,7 @@ def test_pdf_append_to_bytesio() -> None: | |||
|     assert len(f.getvalue()) > initial_size | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.timeout(1) | ||||
| @pytest.mark.skipif("PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower") | ||||
| @timeout_unless_slower_valgrind(1) | ||||
| @pytest.mark.parametrize("newline", (b"\r", b"\n")) | ||||
| def test_redos(newline: bytes) -> None: | ||||
|     malicious = b" trailer<<>>" + newline * 3456 | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ from .helper import ( | |||
|     hopper, | ||||
|     is_pypy, | ||||
|     is_win32, | ||||
|     timeout_unless_slower_valgrind, | ||||
| ) | ||||
| 
 | ||||
| ElementTree: ModuleType | None | ||||
|  | @ -988,7 +989,7 @@ class TestFileTiff: | |||
|             with pytest.raises(OSError): | ||||
|                 im.load() | ||||
| 
 | ||||
|     @pytest.mark.timeout(6) | ||||
|     @timeout_unless_slower_valgrind(6) | ||||
|     @pytest.mark.filterwarnings("ignore:Truncated File Read") | ||||
|     def test_timeout(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||||
|         with Image.open("Tests/images/timeout-6646305047838720") as im: | ||||
|  | @ -1001,7 +1002,7 @@ class TestFileTiff: | |||
|             "Tests/images/oom-225817ca0f8c663be7ab4b9e717b02c661e66834.tif", | ||||
|         ], | ||||
|     ) | ||||
|     @pytest.mark.timeout(2) | ||||
|     @timeout_unless_slower_valgrind(2) | ||||
|     def test_oom(self, test_file: str) -> None: | ||||
|         with pytest.raises(UnidentifiedImageError): | ||||
|             with pytest.warns(UserWarning): | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ from .helper import ( | |||
|     is_win32, | ||||
|     mark_if_feature_version, | ||||
|     skip_unless_feature, | ||||
|     timeout_unless_slower_valgrind, | ||||
| ) | ||||
| 
 | ||||
| ElementTree: ModuleType | None | ||||
|  | @ -572,10 +573,7 @@ class TestImage: | |||
|         i = Image.new("RGB", [1, 1]) | ||||
|         assert isinstance(i.size, tuple) | ||||
| 
 | ||||
|     @pytest.mark.timeout(0.75) | ||||
|     @pytest.mark.skipif( | ||||
|         "PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower" | ||||
|     ) | ||||
|     @timeout_unless_slower_valgrind(0.75) | ||||
|     @pytest.mark.parametrize("size", ((0, 100000000), (100000000, 0))) | ||||
|     def test_empty_image(self, size: tuple[int, int]) -> None: | ||||
|         Image.new("RGB", size) | ||||
|  |  | |||
|  | @ -462,7 +462,7 @@ class TestCoreResampleBox: | |||
|         im.resize((32, 32), resample, (20, 20, 20, 100)) | ||||
|         im.resize((32, 32), resample, (20, 20, 100, 20)) | ||||
| 
 | ||||
|         with pytest.raises(TypeError, match="must be sequence of length 4"): | ||||
|         with pytest.raises(TypeError, match="must be (sequence|tuple) of length 4"): | ||||
|             im.resize((32, 32), resample, (im.width, im.height))  # type: ignore[arg-type] | ||||
| 
 | ||||
|         with pytest.raises(ValueError, match="can't be negative"): | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import pytest | |||
| 
 | ||||
| from PIL import Image, ImageDraw, ImageFont, _util, features | ||||
| 
 | ||||
| from .helper import assert_image_equal_tofile | ||||
| from .helper import assert_image_equal_tofile, timeout_unless_slower_valgrind | ||||
| 
 | ||||
| fonts = [ImageFont.load_default_imagefont()] | ||||
| if not features.check_module("freetype2"): | ||||
|  | @ -72,7 +72,7 @@ def test_decompression_bomb() -> None: | |||
|         font.getmask("A" * 1_000_000) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.timeout(4) | ||||
| @timeout_unless_slower_valgrind(4) | ||||
| def test_oom() -> None: | ||||
|     glyph = struct.pack( | ||||
|         ">hhhhhhhhhh", 1, 0, -32767, -32767, 32767, 32767, -32767, -32767, 32767, 32767 | ||||
|  |  | |||
|  | @ -162,3 +162,13 @@ def test_pickle_font_file(tmp_path: Path, protocol: int) -> None: | |||
| 
 | ||||
|     # Assert | ||||
|     helper_assert_pickled_font_images(font, unpickled_font) | ||||
| 
 | ||||
| 
 | ||||
| def test_load_earlier_data() -> None: | ||||
|     im = pickle.loads( | ||||
|         b"\x80\x04\x95@\x00\x00\x00\x00\x00\x00\x00\x8c\x12PIL.PngImagePlugin" | ||||
|         b"\x94\x8c\x0cPngImageFile\x94\x93\x94)\x81\x94]\x94(}\x94\x8c\x01L\x94K\x01" | ||||
|         b"K\x01\x86\x94NC\x01\x00\x94eb." | ||||
|     ) | ||||
|     assert im.mode == "L" | ||||
|     assert im.size == (1, 1) | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| #!/usr/bin/env bash | ||||
| set -eo pipefail | ||||
| 
 | ||||
| version=1.2.1 | ||||
| version=1.3.0 | ||||
| 
 | ||||
| ./download-and-extract.sh libavif-$version https://github.com/AOMediaCodec/libavif/archive/refs/tags/v$version.tar.gz | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,17 +3,23 @@ | |||
| 
 | ||||
| # You can set these variables from the command line.
 | ||||
| PYTHON        = python3 | ||||
| SPHINXOPTS    = | ||||
| SPHINXBUILD   = $(PYTHON) -m sphinx.cmd.build | ||||
| PAPER         = | ||||
| SPHINXOPTS    = --fail-on-warning | ||||
| BUILDDIR      = _build | ||||
| BUILDER       = html | ||||
| JOBS          = auto | ||||
| PAPER         = | ||||
| 
 | ||||
| # Internal variables.
 | ||||
| PAPEROPT_a4     = --define latex_paper_size=a4 | ||||
| PAPEROPT_letter = --define latex_paper_size=letter | ||||
| ALLSPHINXOPTS   = --doctree-dir $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . | ||||
| # the i18n builder cannot share the environment and doctrees with the others
 | ||||
| I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . | ||||
| 
 | ||||
| ALLSPHINXOPTS   = --builder $(BUILDER) \
 | ||||
|                   --doctree-dir $(BUILDDIR)/doctrees \
 | ||||
|                   --jobs $(JOBS) \
 | ||||
|                   $(PAPEROPT_$(PAPER)) \
 | ||||
|                   $(SPHINXOPTS) \
 | ||||
|                   . $(BUILDDIR)/$(BUILDER) | ||||
| 
 | ||||
| .PHONY: help | ||||
| help: | ||||
|  | @ -36,31 +42,19 @@ install-sphinx: | |||
| .PHONY: html | ||||
| html: | ||||
| 	$(MAKE) install-sphinx | ||||
| 	$(SPHINXBUILD) --builder html --fail-on-warning --keep-going $(ALLSPHINXOPTS) $(BUILDDIR)/html | ||||
| 	@echo | ||||
| 	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html." | ||||
| 	$(SPHINXBUILD) $(ALLSPHINXOPTS) | ||||
| 
 | ||||
| .PHONY: dirhtml | ||||
| dirhtml: | ||||
| 	$(MAKE) install-sphinx | ||||
| 	$(SPHINXBUILD) --builder dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml | ||||
| 	@echo | ||||
| 	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." | ||||
| dirhtml: BUILDER = dirhtml | ||||
| dirhtml: html | ||||
| 
 | ||||
| .PHONY: singlehtml | ||||
| singlehtml: | ||||
| 	$(MAKE) install-sphinx | ||||
| 	$(SPHINXBUILD) --builder singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml | ||||
| 	@echo | ||||
| 	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." | ||||
| singlehtml: BUILDER = singlehtml | ||||
| singlehtml: html | ||||
| 
 | ||||
| .PHONY: linkcheck | ||||
| linkcheck: | ||||
| 	$(MAKE) install-sphinx | ||||
| 	$(SPHINXBUILD) --builder linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck -j auto | ||||
| 	@echo | ||||
| 	@echo "Link check complete; look for any errors in the above output " \
 | ||||
| 	      "or in $(BUILDDIR)/linkcheck/output.txt." | ||||
| linkcheck: BUILDER = linkcheck | ||||
| linkcheck: html | ||||
| 
 | ||||
| .PHONY: htmlview | ||||
| htmlview: html | ||||
|  |  | |||
|  | @ -7,10 +7,8 @@ if "%SPHINXBUILD%" == "" ( | |||
| ) | ||||
| set BUILDDIR=_build | ||||
| set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . | ||||
| set I18NSPHINXOPTS=%SPHINXOPTS% . | ||||
| if NOT "%PAPER%" == "" ( | ||||
| 	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% | ||||
| 	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% | ||||
| ) | ||||
| 
 | ||||
| if "%1" == "" goto help | ||||
|  |  | |||
							
								
								
									
										21
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -46,7 +46,7 @@ WEBP_ROOT = None | |||
| ZLIB_ROOT = None | ||||
| FUZZING_BUILD = "LIB_FUZZING_ENGINE" in os.environ | ||||
| 
 | ||||
| if sys.platform == "win32" and sys.version_info >= (3, 14): | ||||
| if sys.platform == "win32" and sys.version_info >= (3, 15): | ||||
|     import atexit | ||||
| 
 | ||||
|     atexit.register( | ||||
|  | @ -224,13 +224,14 @@ def _add_directory( | |||
|         path.insert(where, subdir) | ||||
| 
 | ||||
| 
 | ||||
| def _find_include_file(self: pil_build_ext, include: str) -> int: | ||||
| def _find_include_file(self: pil_build_ext, include: str) -> str | None: | ||||
|     for directory in self.compiler.include_dirs: | ||||
|         _dbg("Checking for include file %s in %s", (include, directory)) | ||||
|         if os.path.isfile(os.path.join(directory, include)): | ||||
|         path = os.path.join(directory, include) | ||||
|         if os.path.isfile(path): | ||||
|             _dbg("Found %s", include) | ||||
|             return 1 | ||||
|     return 0 | ||||
|             return path | ||||
|     return None | ||||
| 
 | ||||
| 
 | ||||
| def _find_library_file(self: pil_build_ext, library: str) -> str | None: | ||||
|  | @ -852,9 +853,13 @@ class pil_build_ext(build_ext): | |||
| 
 | ||||
|         if feature.want("avif"): | ||||
|             _dbg("Looking for avif") | ||||
|             if _find_include_file(self, "avif/avif.h"): | ||||
|                 if _find_library_file(self, "avif"): | ||||
|                     feature.set("avif", "avif") | ||||
|             if avif_h := _find_include_file(self, "avif/avif.h"): | ||||
|                 with open(avif_h, "rb") as fp: | ||||
|                     major_version = int( | ||||
|                         fp.read().split(b"#define AVIF_VERSION_MAJOR ")[1].split()[0] | ||||
|                     ) | ||||
|                     if major_version >= 1 and _find_library_file(self, "avif"): | ||||
|                         feature.set("avif", "avif") | ||||
| 
 | ||||
|         for f in feature: | ||||
|             if not feature.get(f) and feature.require(f): | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ except ImportError: | |||
| # Decoder options as module globals, until there is a way to pass parameters | ||||
| # to Image.open (see https://github.com/python-pillow/Pillow/issues/569) | ||||
| DECODE_CODEC_CHOICE = "auto" | ||||
| # Decoding is only affected by this for libavif **0.8.4** or greater. | ||||
| DEFAULT_MAX_THREADS = 0 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -257,7 +257,8 @@ class ImageFile(Image.Image): | |||
| 
 | ||||
|     def __setstate__(self, state: list[Any]) -> None: | ||||
|         self.tile = [] | ||||
|         self.filename = state[5] | ||||
|         if len(state) > 5: | ||||
|             self.filename = state[5] | ||||
|         super().__setstate__(state) | ||||
| 
 | ||||
|     def verify(self) -> None: | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ class WmfStubImageFile(ImageFile.StubImageFile): | |||
| 
 | ||||
|     def _open(self) -> None: | ||||
|         # check placable header | ||||
|         s = self.fp.read(80) | ||||
|         s = self.fp.read(44) | ||||
| 
 | ||||
|         if s.startswith(b"\xd7\xcd\xc6\x9a\x00\x00"): | ||||
|             # placeable windows metafile | ||||
|  |  | |||
|  | @ -113,12 +113,12 @@ V = { | |||
|     "BROTLI": "1.1.0", | ||||
|     "FREETYPE": "2.13.3", | ||||
|     "FRIBIDI": "1.0.16", | ||||
|     "HARFBUZZ": "11.1.0", | ||||
|     "HARFBUZZ": "11.2.1", | ||||
|     "JPEGTURBO": "3.1.0", | ||||
|     "LCMS2": "2.17", | ||||
|     "LIBAVIF": "1.2.1", | ||||
|     "LIBAVIF": "1.3.0", | ||||
|     "LIBIMAGEQUANT": "4.3.4", | ||||
|     "LIBPNG": "1.6.47", | ||||
|     "LIBPNG": "1.6.48", | ||||
|     "LIBWEBP": "1.5.0", | ||||
|     "OPENJPEG": "2.5.3", | ||||
|     "TIFF": "4.7.0", | ||||
|  | @ -389,6 +389,7 @@ DEPS: dict[str, dict[str, Any]] = { | |||
|         "filename": f"libavif-{V['LIBAVIF']}.zip", | ||||
|         "license": "LICENSE", | ||||
|         "build": [ | ||||
|             "rustup update", | ||||
|             f"{sys.executable} -m pip install meson", | ||||
|             *cmds_cmake( | ||||
|                 "avif_static", | ||||
|  | @ -399,7 +400,6 @@ DEPS: dict[str, dict[str, Any]] = { | |||
|                 "-DAVIF_CODEC_DAV1D=LOCAL", | ||||
|                 "-DAVIF_CODEC_RAV1E=LOCAL", | ||||
|                 "-DAVIF_CODEC_SVT=LOCAL", | ||||
|                 "-DCMAKE_POLICY_VERSION_MINIMUM=3.5", | ||||
|             ), | ||||
|             cmd_xcopy("include", "{inc_dir}"), | ||||
|         ], | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user