mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	Merge branch 'main' into add-pyproject.toml
This commit is contained in:
		
						commit
						b2d7f1e899
					
				|  | @ -10,8 +10,8 @@ environment: | |||
|   TEST_OPTIONS: | ||||
|   DEPLOY: YES | ||||
|   matrix: | ||||
|   - PYTHON: C:/Python311-x64 | ||||
|     ARCHITECTURE: x64 | ||||
|   - PYTHON: C:/Python311 | ||||
|     ARCHITECTURE: x86 | ||||
|     APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 | ||||
|   - PYTHON: C:/Python38-x64 | ||||
|     ARCHITECTURE: x64 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								.github/workflows/test-docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/test-docker.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -39,6 +39,7 @@ jobs: | |||
|           centos-stream-8-amd64, | ||||
|           centos-stream-9-amd64, | ||||
|           debian-11-bullseye-amd64, | ||||
|           debian-12-bookworm-x86, | ||||
|           debian-12-bookworm-amd64, | ||||
|           fedora-37-amd64, | ||||
|           fedora-38-amd64, | ||||
|  |  | |||
|  | @ -5,6 +5,15 @@ Changelog (Pillow) | |||
| 10.0.0 (unreleased) | ||||
| ------------------- | ||||
| 
 | ||||
| - Removed support for 32-bit #7228 | ||||
|   [radarhere, hugovk] | ||||
| 
 | ||||
| - Use --config-settings instead of deprecated --global-option #7171 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Better C integer definitions #6645 | ||||
|   [Yay295, hugovk] | ||||
| 
 | ||||
| - Fixed finding dependencies on Cygwin #7175 | ||||
|   [radarhere] | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										8
									
								
								Tests/32bit_segfault_check.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								Tests/32bit_segfault_check.py
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #!/usr/bin/env python3 | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| from PIL import Image | ||||
| 
 | ||||
| if sys.maxsize < 2**32: | ||||
|     im = Image.new("L", (999999, 999999), 0) | ||||
|  | @ -1,3 +1,5 @@ | |||
| import sys | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import Image | ||||
|  | @ -21,6 +23,9 @@ YDIM = 32769 | |||
| XDIM = 48000 | ||||
| 
 | ||||
| 
 | ||||
| pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system") | ||||
| 
 | ||||
| 
 | ||||
| def _write_png(tmp_path, xdim, ydim): | ||||
|     f = str(tmp_path / "temp.png") | ||||
|     im = Image.new("L", (xdim, ydim), 0) | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| import sys | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import Image | ||||
|  | @ -17,6 +19,9 @@ YDIM = 32769 | |||
| XDIM = 48000 | ||||
| 
 | ||||
| 
 | ||||
| pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system") | ||||
| 
 | ||||
| 
 | ||||
| def _write_png(tmp_path, xdim, ydim): | ||||
|     dtype = np.uint8 | ||||
|     a = np.zeros((xdim, ydim), dtype=dtype) | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/zero_width.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/zero_width.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 44 B | 
|  | @ -1,3 +1,5 @@ | |||
| import sys | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import Image | ||||
|  | @ -108,6 +110,9 @@ class TestCoreMemory: | |||
| 
 | ||||
|         with pytest.raises(ValueError): | ||||
|             Image.core.set_blocks_max(-1) | ||||
|         if sys.maxsize < 2**32: | ||||
|             with pytest.raises(ValueError): | ||||
|                 Image.core.set_blocks_max(2**29) | ||||
| 
 | ||||
|     @pytest.mark.skipif(is_pypy(), reason="Images not collected") | ||||
|     def test_set_blocks_max_stats(self): | ||||
|  |  | |||
|  | @ -64,6 +64,15 @@ class TestDecompressionBomb: | |||
|             with pytest.raises(Image.DecompressionBombError): | ||||
|                 im.seek(1) | ||||
| 
 | ||||
|     def test_exception_gif_zero_width(self): | ||||
|         # Set limit to trigger exception on the test file | ||||
|         Image.MAX_IMAGE_PIXELS = 4 * 64 * 128 | ||||
|         assert Image.MAX_IMAGE_PIXELS == 4 * 64 * 128 | ||||
| 
 | ||||
|         with pytest.raises(Image.DecompressionBombError): | ||||
|             with Image.open("Tests/images/zero_width.gif"): | ||||
|                 pass | ||||
| 
 | ||||
|     def test_exception_bmp(self): | ||||
|         with pytest.raises(Image.DecompressionBombError): | ||||
|             with Image.open("Tests/images/bmp/b/reallybig.bmp"): | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| import io | ||||
| import re | ||||
| import sys | ||||
| import warnings | ||||
| 
 | ||||
| import pytest | ||||
|  | @ -144,6 +145,7 @@ class TestFileWebp: | |||
| 
 | ||||
|         self._roundtrip(tmp_path, "P", 50.0) | ||||
| 
 | ||||
|     @pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system") | ||||
|     def test_write_encoding_error_message(self, tmp_path): | ||||
|         temp_file = str(tmp_path / "temp.webp") | ||||
|         im = Image.new("RGB", (15000, 15000)) | ||||
|  |  | |||
|  | @ -38,7 +38,10 @@ def test_long_integers(): | |||
|     assert put(0xFFFFFFFF) == (255, 255, 255, 255) | ||||
|     assert put(-1) == (255, 255, 255, 255) | ||||
|     assert put(-1) == (255, 255, 255, 255) | ||||
|     if sys.maxsize > 2**32: | ||||
|         assert put(sys.maxsize) == (255, 255, 255, 255) | ||||
|     else: | ||||
|         assert put(sys.maxsize) == (255, 255, 255, 127) | ||||
| 
 | ||||
| 
 | ||||
| def test_pypy_performance(): | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| import sys | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import Image | ||||
|  | @ -34,6 +36,7 @@ def test_tobytes(): | |||
|     Image.MAX_IMAGE_PIXELS = max_pixels | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system") | ||||
| def test_ysize(): | ||||
|     numpy = pytest.importorskip("numpy", reason="NumPy not installed") | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ coverage: | |||
|   status: | ||||
|     project: | ||||
|       default: | ||||
|         threshold: 0.01% | ||||
|         threshold: 0.1% | ||||
| 
 | ||||
| # Matches 'omit:' in .coveragerc | ||||
| ignore: | ||||
|  |  | |||
|  | @ -285,8 +285,11 @@ Many of Pillow's features require external libraries: | |||
| 
 | ||||
| .. tab:: Windows using MSYS2/MinGW | ||||
| 
 | ||||
|     To build Pillow using MSYS2, make sure you run the **MSYS2 MinGW 64-bit** console, | ||||
|     *not* **MSYS2** directly. | ||||
|     To build Pillow using MSYS2, make sure you run the **MSYS2 MinGW 32-bit** or | ||||
|     **MSYS2 MinGW 64-bit** console, *not* **MSYS2** directly. | ||||
| 
 | ||||
|     The following instructions target the 64-bit build, for 32-bit | ||||
|     replace all occurrences of ``mingw-w64-x86_64-`` with ``mingw-w64-i686-``. | ||||
| 
 | ||||
|     Make sure you have Python and GCC installed:: | ||||
| 
 | ||||
|  | @ -336,6 +339,8 @@ Many of Pillow's features require external libraries: | |||
|         pkg install -y python ndk-sysroot clang make \ | ||||
|             libjpeg-turbo | ||||
| 
 | ||||
|     This has been tested within the Termux app on ChromeOS, on x86. | ||||
| 
 | ||||
| Installing | ||||
| ^^^^^^^^^^ | ||||
| 
 | ||||
|  | @ -448,7 +453,7 @@ These platforms are built and tested for every change. | |||
| +----------------------------------+----------------------------+---------------------+ | ||||
| | Debian 11 Bullseye               | 3.9                        | x86-64              | | ||||
| +----------------------------------+----------------------------+---------------------+ | ||||
| | Debian 12 Bookworm               | 3.11                       | x86-64              | | ||||
| | Debian 12 Bookworm               | 3.11                       | x86, x86-64         | | ||||
| +----------------------------------+----------------------------+---------------------+ | ||||
| | Fedora 37                        | 3.11                       | x86-64              | | ||||
| +----------------------------------+----------------------------+---------------------+ | ||||
|  | @ -472,6 +477,8 @@ These platforms are built and tested for every change. | |||
| | Windows Server 2022              | 3.8, 3.9, 3.10, 3.11,      | x86-64              | | ||||
| |                                  | 3.12, PyPy3                |                     | | ||||
| |                                  +----------------------------+---------------------+ | ||||
| |                                  | 3.11                       | x86                 | | ||||
| |                                  +----------------------------+---------------------+ | ||||
| |                                  | 3.9 (MinGW)                | x86-64              | | ||||
| |                                  +----------------------------+---------------------+ | ||||
| |                                  | 3.8, 3.9 (Cygwin)          | x86-64              | | ||||
|  |  | |||
|  | @ -4,11 +4,6 @@ | |||
| Backwards Incompatible Changes | ||||
| ============================== | ||||
| 
 | ||||
| 32-bit support | ||||
| ^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| 32-bit architecture is no longer supported and 32-bit wheels are no longer provided. | ||||
| 
 | ||||
| Categories | ||||
| ^^^^^^^^^^ | ||||
| 
 | ||||
|  | @ -129,14 +124,6 @@ Image.coerce_e | |||
| 
 | ||||
| This undocumented method has been removed. | ||||
| 
 | ||||
| Deprecations | ||||
| ============ | ||||
| 
 | ||||
| TODO | ||||
| ^^^^ | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| API Changes | ||||
| =========== | ||||
| 
 | ||||
|  | @ -165,6 +152,11 @@ TODO | |||
| Other Changes | ||||
| ============= | ||||
| 
 | ||||
| 32-bit wheels | ||||
| ^^^^^^^^^^^^^ | ||||
| 
 | ||||
| 32-bit wheels are no longer provided. | ||||
| 
 | ||||
| Support display_jpeg() in IPython | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										20
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -152,13 +152,16 @@ def _find_library_dirs_ldconfig(): | |||
| 
 | ||||
|     ldconfig = "ldconfig" if shutil.which("ldconfig") else "/sbin/ldconfig" | ||||
|     if sys.platform.startswith("linux") or sys.platform.startswith("gnu"): | ||||
|         machine = os.uname()[4] | ||||
|         if struct.calcsize("l") == 4: | ||||
|             machine = os.uname()[4] + "-32" | ||||
|         else: | ||||
|             machine = os.uname()[4] + "-64" | ||||
|         mach_map = { | ||||
|             "x86_64": "libc6,x86-64", | ||||
|             "ppc64": "libc6,64bit", | ||||
|             "sparc64": "libc6,64bit", | ||||
|             "s390x": "libc6,64bit", | ||||
|             "ia64": "libc6,IA-64", | ||||
|             "x86_64-64": "libc6,x86-64", | ||||
|             "ppc64-64": "libc6,64bit", | ||||
|             "sparc64-64": "libc6,64bit", | ||||
|             "s390x-64": "libc6,64bit", | ||||
|             "ia64-64": "libc6,IA-64", | ||||
|         } | ||||
|         abi_type = mach_map.get(machine, "libc6") | ||||
| 
 | ||||
|  | @ -580,7 +583,10 @@ class pil_build_ext(build_ext): | |||
|                 # user libs are at $PREFIX/lib | ||||
|                 _add_directory( | ||||
|                     library_dirs, | ||||
|                     os.path.join(os.environ["ANDROID_ROOT"], "lib64"), | ||||
|                     os.path.join( | ||||
|                         os.environ["ANDROID_ROOT"], | ||||
|                         "lib" if struct.calcsize("l") == 4 else "lib64", | ||||
|                     ), | ||||
|                 ) | ||||
| 
 | ||||
|         elif sys.platform.startswith("netbsd"): | ||||
|  |  | |||
|  | @ -3141,7 +3141,7 @@ def _decompression_bomb_check(size): | |||
|     if MAX_IMAGE_PIXELS is None: | ||||
|         return | ||||
| 
 | ||||
|     pixels = size[0] * size[1] | ||||
|     pixels = max(1, size[0]) * max(1, size[1]) | ||||
| 
 | ||||
|     if pixels > 2 * MAX_IMAGE_PIXELS: | ||||
|         msg = ( | ||||
|  |  | |||
|  | @ -880,7 +880,7 @@ font_render(FontObject *self, PyObject *args) { | |||
|     width += stroke_width * 2 + ceil(x_start); | ||||
|     height += stroke_width * 2 + ceil(y_start); | ||||
|     if (max_image_pixels != Py_None) { | ||||
|         if ((long long)width * height > PyLong_AsLongLong(max_image_pixels) * 2) { | ||||
|         if ((long long)(width > 1 ? width : 1) * (height > 1 ? height : 1) > PyLong_AsLongLong(max_image_pixels) * 2) { | ||||
|             PyMem_Del(glyph_info); | ||||
|             return Py_BuildValue("O(ii)(ii)", Py_None, width, height, 0, 0); | ||||
|         } | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| /* This is to work around a bug in GCC prior 4.9 in 64 bit mode.
 | ||||
|    GCC generates code with partial dependency which is 3 times slower. | ||||
|    See: https://stackoverflow.com/a/26588074/253146 */
 | ||||
| #if defined(__SSE__) && !defined(__NO_INLINE__) && \ | ||||
| #if defined(__x86_64__) && defined(__SSE__) && !defined(__NO_INLINE__) && \ | ||||
|     !defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900) | ||||
| static float __attribute__((always_inline)) inline _i2f(int v) { | ||||
|     float x; | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ Download and install: | |||
| * `Ninja <https://ninja-build.org/>`_ | ||||
|   (optional, use ``--nmake`` if not available; bundled in Visual Studio CMake component) | ||||
| 
 | ||||
| * x64: `Netwide Assembler (NASM) <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_ | ||||
| * x86/x64: `Netwide Assembler (NASM) <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_ | ||||
| 
 | ||||
| Any version of Visual Studio 2017 or newer should be supported, | ||||
| including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019. | ||||
|  | @ -42,7 +42,7 @@ Run ``build_prepare.py`` to configure the build:: | |||
| 
 | ||||
|     usage: winbuild\build_prepare.py [-h] [-v] [-d PILLOW_BUILD] | ||||
|                                      [--depends PILLOW_DEPS] | ||||
|                                      [--architecture {x64,ARM64}] [--nmake] | ||||
|                                      [--architecture {x86,x64,ARM64}] [--nmake] | ||||
|                                      [--no-imagequant] [--no-fribidi] | ||||
| 
 | ||||
|     Download and generate build scripts for Pillow dependencies. | ||||
|  | @ -55,7 +55,7 @@ Run ``build_prepare.py`` to configure the build:: | |||
|       --depends PILLOW_DEPS | ||||
|                             directory used to store cached dependencies (default: | ||||
|                             'winbuild\depends') | ||||
|       --architecture {x64,ARM64} | ||||
|       --architecture {x86,x64,ARM64} | ||||
|                             build architecture (default: same as host Python) | ||||
|       --nmake               build dependencies using NMake instead of Ninja | ||||
|       --no-imagequant       skip GPL-licensed optional dependency libimagequant | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import os | |||
| import platform | ||||
| import re | ||||
| import shutil | ||||
| import struct | ||||
| import subprocess | ||||
| 
 | ||||
| 
 | ||||
|  | @ -96,6 +97,7 @@ def cmd_msbuild( | |||
| SF_PROJECTS = "https://sourceforge.net/projects" | ||||
| 
 | ||||
| architectures = { | ||||
|     "x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"}, | ||||
|     "x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"}, | ||||
|     "ARM64": {"vcvars_arch": "x86_arm64", "msbuild_arch": "ARM64"}, | ||||
| } | ||||
|  | @ -227,9 +229,9 @@ deps = { | |||
|         "libs": ["*.lib"], | ||||
|     }, | ||||
|     "freetype": { | ||||
|         "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.13.0.tar.gz",  # noqa: E501 | ||||
|         "filename": "freetype-2.13.0.tar.gz", | ||||
|         "dir": "freetype-2.13.0", | ||||
|         "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.13.1.tar.gz",  # noqa: E501 | ||||
|         "filename": "freetype-2.13.1.tar.gz", | ||||
|         "dir": "freetype-2.13.1", | ||||
|         "license": ["LICENSE.TXT", r"docs\FTL.TXT", r"docs\GPLv2.TXT"], | ||||
|         "patch": { | ||||
|             r"builds\windows\vc2010\freetype.vcxproj": { | ||||
|  | @ -597,7 +599,11 @@ if __name__ == "__main__": | |||
|         choices=architectures, | ||||
|         default=os.environ.get( | ||||
|             "ARCHITECTURE", | ||||
|             "ARM64" if platform.machine() == "ARM64" else "x64", | ||||
|             ( | ||||
|                 "ARM64" | ||||
|                 if platform.machine() == "ARM64" | ||||
|                 else ("x86" if struct.calcsize("P") == 4 else "x64") | ||||
|             ), | ||||
|         ), | ||||
|         help="build architecture (default: same as host Python)", | ||||
|     ) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user