Merge branch 'master' into rm-2.7

This commit is contained in:
Andrew Murray 2019-10-12 18:03:58 +11:00 committed by GitHub
commit 4140cd807b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 681 additions and 63 deletions

View File

@ -28,9 +28,15 @@ environment:
EXECUTABLE: bin/pypy.exe EXECUTABLE: bin/pypy.exe
PIP_DIR: bin PIP_DIR: bin
VENV: YES VENV: YES
- PYTHON: C:\Python38rc1-x64
install: install:
- ps: |
if ($env:PYTHON -eq "C:\Python38rc1-x64") {
curl -o install_python.ps1 https://raw.githubusercontent.com/matthew-brett/multibuild/d0cf77e62028704875073e3dc4626f61d1c33b0e/install_python.ps1
.\install_python.ps1
}
- curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip - curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip
- 7z x pillow-depends.zip -oc:\ - 7z x pillow-depends.zip -oc:\
- mv c:\pillow-depends-master c:\pillow-depends - mv c:\pillow-depends-master c:\pillow-depends

40
.github/workflows/test-docker.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Test Docker
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
docker: [
alpine,
arch,
ubuntu-16.04-xenial-amd64,
ubuntu-18.04-bionic-amd64,
debian-9-stretch-x86,
debian-10-buster-x86,
centos-6-amd64,
centos-7-amd64,
amazon-1-amd64,
amazon-2-amd64,
fedora-29-amd64,
fedora-30-amd64,
]
dockerTag: [master]
name: ${{ matrix.docker }}
steps:
- uses: actions/checkout@v1
- name: Docker pull
run: |
docker pull pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
- name: Docker build
run: |
# The Pillow user in the docker container is UID 1000
sudo chown -R 1000 $GITHUB_WORKSPACE
docker run -v $GITHUB_WORKSPACE:/Pillow pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}

360
.github/workflows/test-windows.yml vendored Normal file
View File

@ -0,0 +1,360 @@
name: Test Windows
on: [push, pull_request]
jobs:
build:
runs-on: windows-2016
strategy:
fail-fast: false
matrix:
python-version: ["3.5", "3.6", "3.7", "pypy3.6"]
architecture: ["x86", "x64"]
include:
- architecture: "x86"
platform-vcvars: "x86"
platform-msbuild: "Win32"
- architecture: "x64"
platform-vcvars: "x86_amd64"
platform-msbuild: "x64"
- python-version: "pypy3.6"
pypy-version: "pypy-c-jit-97588-7392d01b93d0-win32"
pypy-url: "http://buildbot.pypy.org/nightly/py3.6/pypy-c-jit-97588-7392d01b93d0-win32.zip"
# pypy-url: "https://bitbucket.org/pypy/pypy/downloads/${{ matrix.pypy-version }}.zip"
exclude:
- python-version: "pypy3.6"
architecture: "x64"
timeout-minutes: 30
name: Python ${{ matrix.python-version }} ${{ matrix.architecture }}
steps:
- uses: actions/checkout@v1
- name: Install PyPy
if: "contains(matrix.python-version, 'pypy')"
run: |
curl -fsSL -o pypy3.zip "${{ matrix.pypy-url }}"
7z x pypy3.zip "-o$env:RUNNER_WORKSPACE\"
mv "$env:RUNNER_WORKSPACE\${{ matrix.pypy-version }}" "$env:RUNNER_WORKSPACE\${{ matrix.python-version }}"
$env:PYTHON="$env:RUNNER_WORKSPACE\${{ matrix.python-version }}"
# set env: pythonLocation
Write-Host "`#`#[set-env name=pythonLocation;]$env:PYTHON" # old syntax https://github.com/actions/toolkit/issues/61
Write-Host "::set-env name=pythonLocation::$env:PYTHON" # new syntax https://github.com/actions/toolkit/blob/5bb77ec03fea98332e41f9347c8fbb1ce1e48f4a/docs/commands.md
New-Item -ItemType SymbolicLink -Path "$env:PYTHON\python.exe" -Target "$env:PYTHON\pypy3.exe"
curl -fsSL -o get-pip.py https://bootstrap.pypa.io/get-pip.py
& $env:PYTHON\python.exe get-pip.py
shell: pwsh
# sets env: pythonLocation
- name: Set up Python
if: "!contains(matrix.python-version, 'pypy')"
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }}
- name: pip install wheel pytest pytest-cov codecov
run: |
"%pythonLocation%\python.exe" -m pip install wheel pytest pytest-cov
pip install codecov
- name: Fetch dependencies
run: |
curl -fsSL -o nasm.zip https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/win64/nasm-2.14.02-win64.zip
7z x nasm.zip "-o$env:RUNNER_WORKSPACE\"
Write-Host "`#`#[add-path]$env:RUNNER_WORKSPACE\nasm-2.14.02"
Write-Host "::add-path::$env:RUNNER_WORKSPACE\nasm-2.14.02"
$env:PYTHON=$env:pythonLocation
curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip
7z x pillow-depends.zip -oc:\
mv c:\pillow-depends-master c:\pillow-depends
xcopy c:\pillow-depends\*.zip $env:GITHUB_WORKSPACE\winbuild\
xcopy c:\pillow-depends\*.tar.gz $env:GITHUB_WORKSPACE\winbuild\
xcopy /s c:\pillow-depends\test_images\* $env:GITHUB_WORKSPACE\tests\images\
cd $env:GITHUB_WORKSPACE/winbuild/
python.exe $env:GITHUB_WORKSPACE\winbuild\build_dep.py
env:
EXECUTABLE: bin\python.exe
shell: pwsh
- name: Build dependencies / libjpeg
if: false
run: |
REM FIXME uses /MT not /MD, see makefile.vc and win32.mak for more info
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\jpeg-9c
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
nmake -nologo -f makefile.vc setup-vc6
nmake -nologo -f makefile.vc clean
nmake -nologo -f makefile.vc nodebug=1 libjpeg.lib cjpeg.exe djpeg.exe
copy /Y /B j*.h %INCLIB%
copy /Y /B *.lib %INCLIB%
copy /Y /B *.exe %INCLIB%
- name: Build dependencies / libjpeg-turbo
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\libjpeg-turbo-2.0.3
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
set CMAKE=%CMAKE% -DENABLE_SHARED:BOOL=OFF -DWITH_JPEG8:BOOL=TRUE -DWITH_CRT_DLL:BOOL=TRUE -DCMAKE_BUILD_TYPE=Release
%CMAKE% -G "NMake Makefiles" .
nmake -nologo -f Makefile clean
nmake -nologo -f Makefile jpeg-static cjpeg-static djpeg-static
copy /Y /B j*.h %INCLIB%
copy /Y /B jpeg-static.lib %INCLIB%\libjpeg.lib
copy /Y /B cjpeg-static.exe %INCLIB%\cjpeg.exe
copy /Y /B djpeg-static.exe %INCLIB%\djpeg.exe
- name: Build dependencies / zlib
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\zlib-1.2.11
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
nmake -nologo -f win32\Makefile.msc clean
nmake -nologo -f win32\Makefile.msc zlib.lib
copy /Y /B z*.h %INCLIB%
copy /Y /B *.lib %INCLIB%
copy /Y /B zlib.lib %INCLIB%\z.lib
- name: Build dependencies / LibTIFF
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\tiff-4.0.10
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
copy %GITHUB_WORKSPACE%\winbuild\tiff.opt nmake.opt
nmake -nologo -f makefile.vc clean
nmake -nologo -f makefile.vc lib
copy /Y /B libtiff\tiff*.h %INCLIB%
copy /Y /B libtiff\*.dll %INCLIB%
copy /Y /B libtiff\*.lib %INCLIB%
- name: Build dependencies / WebP
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\libwebp-1.0.3
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
rmdir /S /Q output\release-static
nmake -nologo -f Makefile.vc CFG=release-static OBJDIR=output ARCH=${{ matrix.architecture }} all
mkdir %INCLIB%\webp
copy /Y /B src\webp\*.h %INCLIB%\webp
copy /Y /B output\release-static\${{ matrix.architecture }}\lib\* %INCLIB%
- name: Build dependencies / FreeType
run: |
REM Toolkit v100 not available; missing VCTargetsPath; Clean fails
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\freetype-2.10.1
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
rmdir /S /Q objs
set DefaultPlatformToolset=v140
set VCTargetsPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCTargets
set MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
powershell -Command "(gc builds\windows\vc2010\freetype.vcxproj) -replace 'MultiThreaded<', 'MultiThreadedDLL<' | Out-File -encoding ASCII builds\windows\vc2010\freetype.vcxproj"
%MSBUILD% builds\windows\vc2010\freetype.sln /t:Build /p:Configuration="Release Static" /p:Platform=${{ matrix.platform-msbuild }} /m
xcopy /Y /E /Q include %INCLIB%
copy /Y /B "objs\${{ matrix.platform-msbuild }}\Release Static\freetype.lib" %INCLIB%
- name: Build dependencies / LCMS2
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\lcms2-2.8
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
rmdir /S /Q Lib
rmdir /S /Q Projects\VC2015\Release
set VCTargetsPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCTargets
set MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
powershell -Command "(gc Projects\VC2015\lcms2_static\lcms2_static.vcxproj) -replace 'MultiThreaded<', 'MultiThreadedDLL<' | Out-File -encoding ASCII Projects\VC2015\lcms2_static\lcms2_static.vcxproj"
%MSBUILD% Projects\VC2015\lcms2.sln /t:Clean;lcms2_static /p:Configuration="Release" /p:Platform=${{ matrix.platform-msbuild }} /m
xcopy /Y /E /Q include %INCLIB%
copy /Y /B Lib\MS\*.lib %INCLIB%
- name: Build dependencies / OpenJPEG
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\openjpeg-2.3.1msvcr10-x32
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
set CMAKE=%CMAKE% -DBUILD_THIRDPARTY:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=OFF
set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
%CMAKE% -G "NMake Makefiles" .
nmake -nologo -f Makefile clean
nmake -nologo -f Makefile
mkdir %INCLIB%\openjpeg-2.3.1
copy /Y /B src\lib\openjp2\*.h %INCLIB%\openjpeg-2.3.1
copy /Y /B bin\*.lib %INCLIB%
# GPL licensed; skip if building wheels
- name: Build dependencies / libimagequant
if: "github.event_name != 'push' || contains(matrix.python-version, 'pypy')"
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
rem ba653c8: Merge tag '2.12.5' into msvc
cd /D %BUILD%\libimagequant-ba653c8ccb34dde4e21c6076d85a72d21ed9d971
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
echo (gc CMakeLists.txt) -replace 'add_library', "add_compile_options(-openmp-)`r`nadd_library" ^| Out-File -encoding ASCII CMakeLists.txt > patch.ps1
echo (gc CMakeLists.txt) -replace ' SHARED', ' STATIC' ^| Out-File -encoding ASCII CMakeLists.txt >> patch.ps1
powershell .\patch.ps1
set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
%CMAKE% -G "NMake Makefiles" .
nmake -nologo -f Makefile clean
nmake -nologo -f Makefile
copy /Y /B *.h %INCLIB%
copy /Y /B *.lib %INCLIB%
# for Raqm
- name: Build dependencies / HarfBuzz
if: "!contains(matrix.python-version, 'pypy')"
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
set INCLUDE=%INCLUDE%;%INCLIB%
set LIB=%LIB%;%INCLIB%
cd /D %BUILD%\harfbuzz-2.6.1
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
set CMAKE=%CMAKE% -DHB_HAVE_FREETYPE:BOOL=ON -DCMAKE_BUILD_TYPE=Release
%CMAKE% -G "NMake Makefiles" .
nmake -nologo -f Makefile clean
nmake -nologo -f Makefile harfbuzz
copy /Y /B src\*.h %INCLIB%
copy /Y /B *.lib %INCLIB%
# for Raqm
- name: Build dependencies / FriBidi
if: "!contains(matrix.python-version, 'pypy')"
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\fribidi-1.0.7
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
copy /Y /B %GITHUB_WORKSPACE%\winbuild\fribidi.cmake CMakeLists.txt
set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
%CMAKE% -G "NMake Makefiles" .
nmake -nologo -f Makefile clean
nmake -nologo -f Makefile fribidi
copy /Y /B lib\*.h %INCLIB%
copy /Y /B *.lib %INCLIB%
# failing with PyPy3
- name: Build dependencies / Raqm
if: "!contains(matrix.python-version, 'pypy')"
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
set INCLUDE=%INCLUDE%;%INCLIB%
set LIB=%LIB%;%INCLIB%
cd /D %BUILD%\libraqm-0.7.0
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
copy /Y /B %GITHUB_WORKSPACE%\winbuild\raqm.cmake CMakeLists.txt
set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
%CMAKE% -G "NMake Makefiles" .
nmake -nologo -f Makefile clean
nmake -nologo -f Makefile libraqm
copy /Y /B src\*.h %INCLIB%
copy /Y /B libraqm.dll %INCLIB%
- name: Build dependencies / ghostscript
run: |
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
set BUILD=%GITHUB_WORKSPACE%\winbuild\build
cd /D %BUILD%\ghostscript-9.27
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
echo on
set MSVC_VERSION=14
set RCOMP="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\RC.Exe"
if "${{ matrix.architecture }}"=="x64" set WIN64=""
nmake -nologo -f psi\msvc.mak
rem Add bin to PATH variable: Copy to INCLIB, then add INCLIB to PATH in Test step.
copy /Y /B bin\* %INCLIB%
- name: Build Pillow
run: |
set PYTHON=%pythonLocation%
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set MPLSRC=%GITHUB_WORKSPACE%
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
cd /D %GITHUB_WORKSPACE%
set LIB=%INCLIB%;%PYTHON%\tcl
set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE%
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
%PYTHON%\python.exe setup.py build_ext install
rem Add GhostScript and Raqm binaries (copied to INCLIB) to PATH.
path %INCLIB%;%PATH%
%PYTHON%\python.exe selftest.py --installed
- name: Test Pillow
run: |
set PYTHON=%pythonLocation%
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
rem Add GhostScript and Raqm binaries (copied to INCLIB) to PATH.
path %INCLIB%;%PATH%
cd /D %GITHUB_WORKSPACE%
%PYTHON%\python.exe -m pytest -vx --cov PIL --cov-report term --cov-report xml Tests
- name: Upload coverage
run: 'codecov --file "%GITHUB_WORKSPACE%\coverage.xml" --name "%pythonLocation%"'
- name: Build wheel
id: wheel
if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')"
run: |
for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ##[set-output name=dist;]dist-%%a
for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ::set-output name=dist::dist-%%a
set PYTHON=%pythonLocation%
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
set MPLSRC=%GITHUB_WORKSPACE%
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
cd /D %GITHUB_WORKSPACE%
set LIB=%INCLIB%;%PYTHON%\tcl
set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE%
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1
%PYTHON%\python.exe setup.py bdist_wheel
- uses: actions/upload-artifact@v1
if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')"
with:
name: ${{ steps.wheel.outputs.dist }}
path: dist

View File

@ -14,7 +14,7 @@ Pillow is the friendly PIL fork by `Alex Clark and Contributors <https://github.
* - docs * - docs
- |docs| - |docs|
* - tests * - tests
- |linux| |macos| |windows| |coverage| - |linux| |macos| |windows| |gha_lint| |gha_docker| |coverage|
* - package * - package
- |zenodo| |tidelift| |version| |downloads| - |zenodo| |tidelift| |version| |downloads|
* - social * - social
@ -60,6 +60,12 @@ To report a security vulnerability, please follow the procedure described in the
:target: https://ci.appveyor.com/project/python-pillow/Pillow :target: https://ci.appveyor.com/project/python-pillow/Pillow
:alt: AppVeyor CI build status (Windows) :alt: AppVeyor CI build status (Windows)
.. |gha_lint| image:: https://github.com/python-pillow/Pillow/workflows/Lint/badge.svg
:alt: GitHub Actions build status (Lint)
.. |gha_docker| image:: https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg
:alt: GitHub Actions build status (Test Docker)
.. |coverage| image:: https://codecov.io/gh/python-pillow/Pillow/branch/master/graph/badge.svg .. |coverage| image:: https://codecov.io/gh/python-pillow/Pillow/branch/master/graph/badge.svg
:target: https://codecov.io/gh/python-pillow/Pillow :target: https://codecov.io/gh/python-pillow/Pillow
:alt: Code coverage :alt: Code coverage

View File

@ -1,15 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys
from PIL import Image from PIL import Image
from .helper import PillowTestCase, unittest from .helper import PillowTestCase, is_win32, unittest
min_iterations = 100 min_iterations = 100
max_iterations = 10000 max_iterations = 10000
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestImagingLeaks(PillowTestCase): class TestImagingLeaks(PillowTestCase):
def _get_mem_usage(self): def _get_mem_usage(self):
from resource import getpagesize, getrusage, RUSAGE_SELF from resource import getpagesize, getrusage, RUSAGE_SELF

View File

@ -1,9 +1,8 @@
import sys
from io import BytesIO from io import BytesIO
from PIL import Image from PIL import Image
from .helper import PillowTestCase, unittest from .helper import PillowTestCase, is_win32, unittest
# Limits for testing the leak # Limits for testing the leak
mem_limit = 1024 * 1048576 mem_limit = 1024 * 1048576
@ -13,7 +12,7 @@ codecs = dir(Image.core)
test_file = "Tests/images/rgb_trns_ycbc.jp2" test_file = "Tests/images/rgb_trns_ycbc.jp2"
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestJpegLeaks(PillowTestCase): class TestJpegLeaks(PillowTestCase):
def setUp(self): def setUp(self):
if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs: if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs:

View File

@ -1,7 +1,6 @@
import sys
from io import BytesIO from io import BytesIO
from .helper import PillowTestCase, hopper, unittest from .helper import PillowTestCase, hopper, is_win32, unittest
iterations = 5000 iterations = 5000
@ -15,7 +14,7 @@ valgrind --tool=massif python test-installed.py -s -v Tests/check_jpeg_leaks.py
""" """
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestJpegLeaks(PillowTestCase): class TestJpegLeaks(PillowTestCase):
""" """

View File

@ -350,10 +350,25 @@ def on_appveyor():
return "APPVEYOR" in os.environ return "APPVEYOR" in os.environ
def on_github_actions():
return "GITHUB_ACTIONS" in os.environ
def on_ci(): def on_ci():
# Travis and AppVeyor have "CI" # Travis and AppVeyor have "CI"
# Azure Pipelines has "TF_BUILD" # Azure Pipelines has "TF_BUILD"
return "CI" in os.environ or "TF_BUILD" in os.environ # GitHub Actions has "GITHUB_ACTIONS"
return (
"CI" in os.environ or "TF_BUILD" in os.environ or "GITHUB_ACTIONS" in os.environ
)
def is_win32():
return sys.platform.startswith("win32")
def is_pypy():
return hasattr(sys, "pypy_translation_info")
if sys.platform == "win32": if sys.platform == "win32":

View File

@ -2,9 +2,7 @@ import sys
from PIL import Image from PIL import Image
from .helper import PillowTestCase, unittest from .helper import PillowTestCase, is_pypy, unittest
is_pypy = hasattr(sys, "pypy_version_info")
class TestCoreStats(PillowTestCase): class TestCoreStats(PillowTestCase):
@ -85,7 +83,7 @@ class TestCoreMemory(PillowTestCase):
stats = Image.core.get_stats() stats = Image.core.get_stats()
self.assertGreaterEqual(stats["new_count"], 1) self.assertGreaterEqual(stats["new_count"], 1)
self.assertGreaterEqual(stats["allocated_blocks"], 64) self.assertGreaterEqual(stats["allocated_blocks"], 64)
if not is_pypy: if not is_pypy():
self.assertGreaterEqual(stats["freed_blocks"], 64) self.assertGreaterEqual(stats["freed_blocks"], 64)
def test_get_blocks_max(self): def test_get_blocks_max(self):
@ -106,7 +104,7 @@ class TestCoreMemory(PillowTestCase):
if sys.maxsize < 2 ** 32: if sys.maxsize < 2 ** 32:
self.assertRaises(ValueError, Image.core.set_blocks_max, 2 ** 29) self.assertRaises(ValueError, Image.core.set_blocks_max, 2 ** 29)
@unittest.skipIf(is_pypy, "images are not collected") @unittest.skipIf(is_pypy(), "images are not collected")
def test_set_blocks_max_stats(self): def test_set_blocks_max_stats(self):
Image.core.reset_stats() Image.core.reset_stats()
Image.core.set_blocks_max(128) Image.core.set_blocks_max(128)
@ -121,7 +119,7 @@ class TestCoreMemory(PillowTestCase):
self.assertEqual(stats["freed_blocks"], 0) self.assertEqual(stats["freed_blocks"], 0)
self.assertEqual(stats["blocks_cached"], 64) self.assertEqual(stats["blocks_cached"], 64)
@unittest.skipIf(is_pypy, "images are not collected") @unittest.skipIf(is_pypy(), "images are not collected")
def test_clear_cache_stats(self): def test_clear_cache_stats(self):
Image.core.reset_stats() Image.core.reset_stats()
Image.core.clear_cache() Image.core.clear_cache()
@ -151,7 +149,7 @@ class TestCoreMemory(PillowTestCase):
self.assertGreaterEqual(stats["allocated_blocks"], 16) self.assertGreaterEqual(stats["allocated_blocks"], 16)
self.assertGreaterEqual(stats["reused_blocks"], 0) self.assertGreaterEqual(stats["reused_blocks"], 0)
self.assertEqual(stats["blocks_cached"], 0) self.assertEqual(stats["blocks_cached"], 0)
if not is_pypy: if not is_pypy():
self.assertGreaterEqual(stats["freed_blocks"], 16) self.assertGreaterEqual(stats["freed_blocks"], 16)

View File

@ -1,10 +1,16 @@
import os import os
import sys
from io import BytesIO from io import BytesIO
from PIL import Image, ImageFile, JpegImagePlugin from PIL import Image, ImageFile, JpegImagePlugin
from .helper import PillowTestCase, cjpeg_available, djpeg_available, hopper, unittest from .helper import (
PillowTestCase,
cjpeg_available,
djpeg_available,
hopper,
is_win32,
unittest,
)
codecs = dir(Image.core) codecs = dir(Image.core)
@ -654,7 +660,7 @@ class TestFileJpeg(PillowTestCase):
self.assertNotIn("photoshop", im.info) self.assertNotIn("photoshop", im.info)
@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") @unittest.skipUnless(is_win32(), "Windows only")
class TestFileCloseW32(PillowTestCase): class TestFileCloseW32(PillowTestCase):
def setUp(self): def setUp(self):
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:

View File

@ -1,10 +1,9 @@
import sys
import zlib import zlib
from io import BytesIO from io import BytesIO
from PIL import Image, ImageFile, PngImagePlugin from PIL import Image, ImageFile, PngImagePlugin
from .helper import PillowLeakTestCase, PillowTestCase, hopper, unittest from .helper import PillowLeakTestCase, PillowTestCase, hopper, is_win32, unittest
try: try:
from PIL import _webp from PIL import _webp
@ -646,7 +645,7 @@ class TestFilePng(PillowTestCase):
self.assert_image_similar(im, expected, 0.23) self.assert_image_similar(im, expected, 0.23)
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestTruncatedPngPLeaks(PillowLeakTestCase): class TestTruncatedPngPLeaks(PillowLeakTestCase):
mem_limit = 2 * 1024 # max increase in K mem_limit = 2 * 1024 # max increase in K
iterations = 100 # Leak is 56k/iteration, this will leak 5.6megs iterations = 100 # Leak is 56k/iteration, this will leak 5.6megs

View File

@ -1,12 +1,11 @@
import logging import logging
import os import os
import sys
from io import BytesIO from io import BytesIO
from PIL import Image, TiffImagePlugin from PIL import Image, TiffImagePlugin
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION
from .helper import PillowTestCase, hopper, unittest from .helper import PillowTestCase, hopper, is_win32, unittest
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -572,7 +571,7 @@ class TestFileTiff(PillowTestCase):
Image.open("Tests/images/string_dimension.tiff") Image.open("Tests/images/string_dimension.tiff")
@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") @unittest.skipUnless(is_win32(), "Windows only")
class TestFileTiffW32(PillowTestCase): class TestFileTiffW32(PillowTestCase):
def test_fd_leak(self): def test_fd_leak(self):
tmpfile = self.tempfile("temp.tif") tmpfile = self.tempfile("temp.tif")

View File

@ -1,11 +1,9 @@
import sys
from PIL import Image, ImageDraw, ImageFont, features from PIL import Image, ImageDraw, ImageFont, features
from .helper import PillowLeakTestCase, unittest from .helper import PillowLeakTestCase, is_win32, unittest
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestTTypeFontLeak(PillowLeakTestCase): class TestTTypeFontLeak(PillowLeakTestCase):
# fails at iteration 3 in master # fails at iteration 3 in master
iterations = 10 iterations = 10

View File

@ -1,11 +1,10 @@
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
from PIL import Image from PIL import Image
from .helper import PillowTestCase, hopper, unittest from .helper import PillowTestCase, hopper, is_win32, unittest
class TestImage(PillowTestCase): class TestImage(PillowTestCase):
@ -142,9 +141,7 @@ class TestImage(PillowTestCase):
im.paste(0, (0, 0, 100, 100)) im.paste(0, (0, 0, 100, 100))
self.assertFalse(im.readonly) self.assertFalse(im.readonly)
@unittest.skipIf( @unittest.skipIf(is_win32(), "Test requires opening tempfile twice")
sys.platform.startswith("win32"), "Test requires opening tempfile twice"
)
def test_readonly_save(self): def test_readonly_save(self):
temp_file = self.tempfile("temp.bmp") temp_file = self.tempfile("temp.bmp")
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file) shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)

View File

@ -6,7 +6,7 @@ from distutils import ccompiler, sysconfig
from PIL import Image from PIL import Image
from .helper import PillowTestCase, hopper, on_appveyor, unittest from .helper import PillowTestCase, hopper, is_win32, on_ci, unittest
# CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2 # CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2
# https://github.com/eliben/pycparser/pull/198#issuecomment-317001670 # https://github.com/eliben/pycparser/pull/198#issuecomment-317001670
@ -336,8 +336,8 @@ class TestCffi(AccessTest):
class TestEmbeddable(unittest.TestCase): class TestEmbeddable(unittest.TestCase):
@unittest.skipIf( @unittest.skipIf(
not sys.platform.startswith("win32") or on_appveyor(), not is_win32() or on_ci(),
"Failing on AppVeyor when run from subprocess, not from shell", "Failing on AppVeyor / GitHub Actions when run from subprocess, not from shell",
) )
def test_embeddable(self): def test_embeddable(self):
with open("embed_pil.c", "w") as fh: with open("embed_pil.c", "w") as fh:

View File

@ -8,7 +8,7 @@ from io import BytesIO
from PIL import Image, ImageDraw, ImageFont, features from PIL import Image, ImageDraw, ImageFont, features
from .helper import PillowTestCase, unittest from .helper import PillowTestCase, is_pypy, is_win32, unittest
FONT_PATH = "Tests/fonts/FreeMono.ttf" FONT_PATH = "Tests/fonts/FreeMono.ttf"
FONT_SIZE = 20 FONT_SIZE = 20
@ -463,7 +463,7 @@ class TestImageFont(PillowTestCase):
with self.assertRaises(UnicodeEncodeError): with self.assertRaises(UnicodeEncodeError):
font.getsize("") font.getsize("")
@unittest.skipIf(hasattr(sys, "pypy_translation_info"), "requires CPython") @unittest.skipIf(is_pypy(), "requires CPython")
def test_unicode_extended(self): def test_unicode_extended(self):
# issue #3777 # issue #3777
text = "A\u278A\U0001F12B" text = "A\u278A\U0001F12B"
@ -500,7 +500,7 @@ class TestImageFont(PillowTestCase):
name = font.getname() name = font.getname()
self.assertEqual(("FreeMono", "Regular"), name) self.assertEqual(("FreeMono", "Regular"), name)
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
def test_find_linux_font(self): def test_find_linux_font(self):
# A lot of mocking here - this is more for hitting code and # A lot of mocking here - this is more for hitting code and
# catching syntax like errors # catching syntax like errors
@ -546,7 +546,7 @@ class TestImageFont(PillowTestCase):
font_directory + "/Duplicate.ttf", "Duplicate" font_directory + "/Duplicate.ttf", "Duplicate"
) )
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
def test_find_macos_font(self): def test_find_macos_font(self):
# Like the linux test, more cover hitting code rather than testing # Like the linux test, more cover hitting code rather than testing
# correctness. # correctness.

View File

@ -1,6 +1,6 @@
from PIL import Image, ImageShow from PIL import Image, ImageShow
from .helper import PillowTestCase, hopper, on_ci, unittest from .helper import PillowTestCase, hopper, is_win32, on_ci, on_github_actions, unittest
class TestImageShow(PillowTestCase): class TestImageShow(PillowTestCase):
@ -34,7 +34,10 @@ class TestImageShow(PillowTestCase):
# Restore original state # Restore original state
ImageShow._viewers.pop(0) ImageShow._viewers.pop(0)
@unittest.skipUnless(on_ci(), "Only run on CIs") @unittest.skipUnless(
on_ci() and not (is_win32() and on_github_actions()),
"Only run on CIs; hangs on Windows on GitHub Actions",
)
def test_show(self): def test_show(self):
for mode in ("1", "I;16", "LA", "RGB", "RGBA"): for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
im = hopper(mode) im = hopper(mode)

View File

@ -1,8 +1,6 @@
import sys
from PIL import ImageWin from PIL import ImageWin
from .helper import PillowTestCase, hopper, unittest from .helper import PillowTestCase, hopper, is_win32, unittest
class TestImageWin(PillowTestCase): class TestImageWin(PillowTestCase):
@ -32,7 +30,7 @@ class TestImageWin(PillowTestCase):
self.assertEqual(wnd2, 50) self.assertEqual(wnd2, 50)
@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") @unittest.skipUnless(is_win32(), "Windows only")
class TestImageWinDib(PillowTestCase): class TestImageWinDib(PillowTestCase):
def test_dib_image(self): def test_dib_image(self):
# Arrange # Arrange

View File

@ -1,14 +1,13 @@
import ctypes import ctypes
import sys
from io import BytesIO from io import BytesIO
from PIL import Image, ImageWin from PIL import Image, ImageWin
from .helper import PillowTestCase, hopper from .helper import PillowTestCase, hopper, is_win32
# see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652 # see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652
if sys.platform.startswith("win32"): if is_win32():
import ctypes.wintypes import ctypes.wintypes
class BITMAPFILEHEADER(ctypes.Structure): class BITMAPFILEHEADER(ctypes.Structure):

View File

@ -3,8 +3,14 @@ import subprocess
import sys import sys
from unittest import TestCase from unittest import TestCase
from .helper import is_pypy, is_win32, on_github_actions, unittest
class TestMain(TestCase): class TestMain(TestCase):
@unittest.skipIf(
is_win32() and is_pypy() and on_github_actions(),
"Failing on Windows on GitHub Actions running PyPy",
)
def test_main(self): def test_main(self):
out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8") out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8")
lines = out.splitlines() lines = out.splitlines()

View File

@ -2,7 +2,7 @@ import sys
from PIL import Image from PIL import Image
from .helper import PillowTestCase, unittest from .helper import PillowTestCase, is_win32, unittest
try: try:
import numpy import numpy
@ -10,7 +10,7 @@ except ImportError:
numpy = None numpy = None
@unittest.skipIf(sys.platform.startswith("win32"), "Win32 does not call map_buffer") @unittest.skipIf(is_win32(), "Win32 does not call map_buffer")
class TestMap(PillowTestCase): class TestMap(PillowTestCase):
def test_overflow(self): def test_overflow(self):
# There is the potential to overflow comparisons in map.c # There is the potential to overflow comparisons in map.c

View File

@ -1,5 +1,4 @@
import shutil import shutil
import sys
from PIL import GifImagePlugin, Image, JpegImagePlugin from PIL import GifImagePlugin, Image, JpegImagePlugin
@ -7,6 +6,7 @@ from .helper import (
PillowTestCase, PillowTestCase,
cjpeg_available, cjpeg_available,
djpeg_available, djpeg_available,
is_win32,
netpbm_available, netpbm_available,
unittest, unittest,
) )
@ -17,7 +17,7 @@ TEST_GIF = "Tests/images/hopper.gif"
test_filenames = ("temp_';", 'temp_";', "temp_'\"|", "temp_'\"||", "temp_'\"&&") test_filenames = ("temp_';", 'temp_";', "temp_'\"|", "temp_'\"||", "temp_'\"&&")
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestShellInjection(PillowTestCase): class TestShellInjection(PillowTestCase):
def assert_save_filename_check(self, src_img, save_func): def assert_save_filename_check(self, src_img, save_func):
for filename in test_filenames: for filename in test_filenames:

View File

@ -104,6 +104,15 @@ the file format handler (see the chapter on :ref:`image-file-formats`). Most
handlers add properties to the :py:attr:`~PIL.Image.Image.info` attribute when handlers add properties to the :py:attr:`~PIL.Image.Image.info` attribute when
loading an image, but ignore it when saving images. loading an image, but ignore it when saving images.
Orientation
-----------
A common element of the :py:attr:`~PIL.Image.Image.info` attribute for JPG and
TIFF images is the EXIF orientation tag. This is an instruction for how the
image data should be oriented. For example, it may instruct an image to be
rotated by 90 degrees, or to be mirrored. To apply this information to an
image, :py:meth:`~PIL.ImageOps.exif_transpose` can be used.
.. _concept-filters: .. _concept-filters:
Filters Filters

View File

@ -8,13 +8,13 @@ The :py:mod:`ImageOps` module contains a number of ready-made image
processing operations. This module is somewhat experimental, and most operators processing operations. This module is somewhat experimental, and most operators
only work on L and RGB images. only work on L and RGB images.
Only bug fixes have been added since the Pillow fork.
.. versionadded:: 1.1.3 .. versionadded:: 1.1.3
.. autofunction:: autocontrast .. autofunction:: autocontrast
.. autofunction:: colorize .. autofunction:: colorize
.. autofunction:: pad
.. autofunction:: crop .. autofunction:: crop
.. autofunction:: scale
.. autofunction:: deform .. autofunction:: deform
.. autofunction:: equalize .. autofunction:: equalize
.. autofunction:: expand .. autofunction:: expand
@ -25,3 +25,4 @@ Only bug fixes have been added since the Pillow fork.
.. autofunction:: mirror .. autofunction:: mirror
.. autofunction:: posterize .. autofunction:: posterize
.. autofunction:: solarize .. autofunction:: solarize
.. autofunction:: exif_transpose

View File

@ -124,7 +124,7 @@ set INCLUDE=%%INCLUDE%%;%%INCLIB%%\%(inc_dir)s;%%INCLIB%%\tcl%(tcl_ver)s\include
setlocal setlocal
set LIB=%%LIB%%;C:\Python%(py_ver)s\tcl%(vc_setup)s set LIB=%%LIB%%;C:\Python%(py_ver)s\tcl%(vc_setup)s
call %(python_path)s\%(executable)s setup.py %(imaging_libs)s %%BLDOPT%% call %(python_path)s\%(executable)s setup.py %(imaging_libs)s %%BLDOPT%%
call %(python_path)s\%(executable)s -c "from PIL import _webp;import os, shutil;shutil.copy('%%INCLIB%%\\freetype.dll', os.path.dirname(_webp.__file__));" call %(python_path)s\%(executable)s -c "from PIL import _webp;import os, shutil;shutil.copy(r'%%INCLIB%%\freetype.dll', os.path.dirname(_webp.__file__));"
endlocal endlocal
endlocal endlocal

View File

@ -202,7 +202,7 @@ setlocal
+ vc_setup(compiler, bit) + vc_setup(compiler, bit)
+ r""" + r"""
rem do after building jpeg and zlib rem do after building jpeg and zlib
copy %%~dp0\nmake.opt %%TIFF%% copy %%~dp0\tiff.opt %%TIFF%%\nmake.opt
cd /D %%TIFF%% cd /D %%TIFF%%
nmake -nologo -f makefile.vc clean nmake -nologo -f makefile.vc clean
@ -270,6 +270,7 @@ def build_lcms_70(compiler):
r""" r"""
rem Build lcms2 rem Build lcms2
setlocal setlocal
set LCMS=%%LCMS-2.7%%
rd /S /Q %%LCMS%%\Lib rd /S /Q %%LCMS%%\Lib
rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release
%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:Clean /p:Configuration="Release" /p:Platform=Win32 /m %%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:Clean /p:Configuration="Release" /p:Platform=Win32 /m
@ -287,8 +288,10 @@ def build_lcms_71(compiler):
r""" r"""
rem Build lcms2 rem Build lcms2
setlocal setlocal
set LCMS=%%LCMS-2.8%%
rd /S /Q %%LCMS%%\Lib rd /S /Q %%LCMS%%\Lib
rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release
powershell -Command "(gc Projects\VC2015\lcms2_static\lcms2_static.vcxproj) -replace 'MultiThreadedDLL', 'MultiThreaded' | Out-File -encoding ASCII Projects\VC2015\lcms2_static\lcms2_static.vcxproj"
%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:Clean /p:Configuration="Release" /p:Platform=%(platform)s /m %%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:Clean /p:Configuration="Release" /p:Platform=%(platform)s /m
%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:lcms2_static /p:Configuration="Release" /p:Platform=%(platform)s /m %%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:lcms2_static /p:Configuration="Release" /p:Platform=%(platform)s /m
xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%% xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%%

View File

@ -1,13 +1,19 @@
import os import os
SF_MIRROR = "http://iweb.dl.sourceforge.net" SF_MIRROR = "https://iweb.dl.sourceforge.net"
PILLOW_DEPENDS_DIR = "C:\\pillow-depends\\" PILLOW_DEPENDS_DIR = "C:\\pillow-depends\\"
pythons = { pythons = {
# for AppVeyor
"35": {"compiler": 7.1, "vc": 2015}, "35": {"compiler": 7.1, "vc": 2015},
"36": {"compiler": 7.1, "vc": 2015}, "36": {"compiler": 7.1, "vc": 2015},
"pypy3": {"compiler": 7.1, "vc": 2015}, "pypy3": {"compiler": 7.1, "vc": 2015},
"37": {"compiler": 7.1, "vc": 2015}, "37": {"compiler": 7.1, "vc": 2015},
"38rc1-x64": {"compiler": 7.1, "vc": 2015},
# for GitHub Actions
"3.5": {"compiler": 7.1, "vc": 2015},
"3.6": {"compiler": 7.1, "vc": 2015},
"3.7": {"compiler": 7.1, "vc": 2015},
} }
VIRT_BASE = "c:/vp/" VIRT_BASE = "c:/vp/"
@ -38,11 +44,16 @@ libs = {
"filename": PILLOW_DEPENDS_DIR + "freetype-2.10.1.tar.gz", "filename": PILLOW_DEPENDS_DIR + "freetype-2.10.1.tar.gz",
"dir": "freetype-2.10.1", "dir": "freetype-2.10.1",
}, },
"lcms": { "lcms-2.7": {
"url": SF_MIRROR + "/project/lcms/lcms/2.7/lcms2-2.7.zip", "url": SF_MIRROR + "/project/lcms/lcms/2.7/lcms2-2.7.zip",
"filename": PILLOW_DEPENDS_DIR + "lcms2-2.7.zip", "filename": PILLOW_DEPENDS_DIR + "lcms2-2.7.zip",
"dir": "lcms2-2.7", "dir": "lcms2-2.7",
}, },
"lcms-2.8": {
"url": SF_MIRROR + "/project/lcms/lcms/2.8/lcms2-2.8.zip",
"filename": PILLOW_DEPENDS_DIR + "lcms2-2.8.zip",
"dir": "lcms2-2.8",
},
"ghostscript": { "ghostscript": {
"url": "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs927/ghostscript-9.27.tar.gz", # noqa: E501 "url": "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs927/ghostscript-9.27.tar.gz", # noqa: E501
"filename": PILLOW_DEPENDS_DIR + "ghostscript-9.27.tar.gz", "filename": PILLOW_DEPENDS_DIR + "ghostscript-9.27.tar.gz",
@ -80,6 +91,33 @@ libs = {
"filename": PILLOW_DEPENDS_DIR + "openjpeg-2.3.1.tar.gz", "filename": PILLOW_DEPENDS_DIR + "openjpeg-2.3.1.tar.gz",
"dir": "openjpeg-2.3.1", "dir": "openjpeg-2.3.1",
}, },
"jpeg-turbo": {
"url": SF_MIRROR + "/project/libjpeg-turbo/2.0.3/libjpeg-turbo-2.0.3.tar.gz",
"filename": PILLOW_DEPENDS_DIR + "libjpeg-turbo-2.0.3.tar.gz",
"dir": "libjpeg-turbo-2.0.3",
},
# ba653c8: Merge tag '2.12.5' into msvc
"imagequant": {
"url": "https://github.com/ImageOptim/libimagequant/archive/ba653c8ccb34dde4e21c6076d85a72d21ed9d971.zip", # noqa: E501
"filename": PILLOW_DEPENDS_DIR
+ "libimagequant-ba653c8ccb34dde4e21c6076d85a72d21ed9d971.zip",
"dir": "libimagequant-ba653c8ccb34dde4e21c6076d85a72d21ed9d971",
},
"harfbuzz": {
"url": "https://github.com/harfbuzz/harfbuzz/archive/2.6.1.zip",
"filename": PILLOW_DEPENDS_DIR + "harfbuzz-2.6.1.zip",
"dir": "harfbuzz-2.6.1",
},
"fribidi": {
"url": "https://github.com/fribidi/fribidi/archive/v1.0.7.zip",
"filename": PILLOW_DEPENDS_DIR + "fribidi-1.0.7.zip",
"dir": "fribidi-1.0.7",
},
"libraqm": {
"url": "https://github.com/HOST-Oman/libraqm/archive/v0.7.0.zip",
"filename": PILLOW_DEPENDS_DIR + "libraqm-0.7.0.zip",
"dir": "libraqm-0.7.0",
},
} }
compilers = { compilers = {

102
winbuild/fribidi.cmake Normal file
View File

@ -0,0 +1,102 @@
cmake_minimum_required(VERSION 3.13)
project(fribidi)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(lib)
function(extract_regex_1 var text regex)
string(REGEX MATCH ${regex} _ ${text})
set(${var} "${CMAKE_MATCH_1}" PARENT_SCOPE)
endfunction()
function(fribidi_conf)
file(READ configure.ac FRIBIDI_CONF)
extract_regex_1(FRIBIDI_MAJOR_VERSION "${FRIBIDI_CONF}" "\\(fribidi_major_version, ([0-9]+)\\)")
extract_regex_1(FRIBIDI_MINOR_VERSION "${FRIBIDI_CONF}" "\\(fribidi_minor_version, ([0-9]+)\\)")
extract_regex_1(FRIBIDI_MICRO_VERSION "${FRIBIDI_CONF}" "\\(fribidi_micro_version, ([0-9]+)\\)")
extract_regex_1(FRIBIDI_INTERFACE_VERSION "${FRIBIDI_CONF}" "\\(fribidi_interface_version, ([0-9]+)\\)")
extract_regex_1(FRIBIDI_INTERFACE_AGE "${FRIBIDI_CONF}" "\\(fribidi_interface_age, ([0-9]+)\\)")
extract_regex_1(FRIBIDI_BINARY_AGE "${FRIBIDI_CONF}" "\\(fribidi_binary_age, ([0-9]+)\\)")
set(FRIBIDI_VERSION "${FRIBIDI_MAJOR_VERSION}.${FRIBIDI_MINOR_VERSION}.${FRIBIDI_MICRO_VERSION}")
set(PACKAGE "fribidi")
set(PACKAGE_NAME "GNU FriBidi")
set(PACKAGE_BUGREPORT "https://github.com/fribidi/fribidi/issues/new")
set(SIZEOF_INT 4)
set(FRIBIDI_MSVC_BUILD_PLACEHOLDER "#define FRIBIDI_BUILT_WITH_MSVC")
message("detected ${PACKAGE_NAME} version ${FRIBIDI_VERSION}")
configure_file(lib/fribidi-config.h.in lib/fribidi-config.h @ONLY)
endfunction()
fribidi_conf()
function(prepend var prefix)
set(out "")
foreach(f ${ARGN})
list(APPEND out "${prefix}${f}")
endforeach()
set(${var} "${out}" PARENT_SCOPE)
endfunction()
macro(fribidi_definitions _TGT)
target_compile_definitions(${_TGT} PUBLIC
HAVE_MEMSET
HAVE_MEMMOVE
HAVE_STRDUP
HAVE_STDLIB_H=1
HAVE_STRING_H=1
HAVE_MEMORY_H=1
#HAVE_STRINGS_H
#HAVE_SYS_TIMES_H
STDC_HEADERS=1
HAVE_STRINGIZE=1)
endmacro()
function(fribidi_gen _NAME _OUTNAME _PARAM)
set(_OUT lib/${_OUTNAME})
prepend(_DEP "${CMAKE_CURRENT_SOURCE_DIR}/gen.tab/" ${ARGN})
add_executable(gen-${_NAME}
gen.tab/gen-${_NAME}.c
gen.tab/packtab.c)
fribidi_definitions(gen-${_NAME})
target_compile_definitions(gen-${_NAME}
PUBLIC DONT_HAVE_FRIBIDI_CONFIG_H)
add_custom_command(
COMMAND gen-${_NAME} ${_PARAM} ${_DEP} > ${_OUT}
DEPENDS ${_DEP}
OUTPUT ${_OUT})
list(APPEND FRIBIDI_SOURCES_GENERATED "${_OUT}")
set(FRIBIDI_SOURCES_GENERATED ${FRIBIDI_SOURCES_GENERATED} PARENT_SCOPE)
endfunction()
fribidi_gen(unicode-version fribidi-unicode-version.h ""
unidata/ReadMe.txt unidata/BidiMirroring.txt)
macro(fribidi_tab _NAME)
fribidi_gen(${_NAME}-tab ${_NAME}.tab.i 2 ${ARGN})
target_sources(gen-${_NAME}-tab
PRIVATE lib/fribidi-unicode-version.h)
endmacro()
fribidi_tab(bidi-type unidata/UnicodeData.txt)
fribidi_tab(joining-type unidata/UnicodeData.txt unidata/ArabicShaping.txt)
fribidi_tab(arabic-shaping unidata/UnicodeData.txt)
fribidi_tab(mirroring unidata/BidiMirroring.txt)
fribidi_tab(brackets unidata/BidiBrackets.txt unidata/UnicodeData.txt)
fribidi_tab(brackets-type unidata/BidiBrackets.txt)
file(GLOB FRIBIDI_SOURCES lib/*.c)
file(GLOB FRIBIDI_HEADERS lib/*.h)
add_library(fribidi STATIC
${FRIBIDI_SOURCES}
${FRIBIDI_HEADERS}
${FRIBIDI_SOURCES_GENERATED})
fribidi_definitions(fribidi)
target_compile_definitions(fribidi
PUBLIC -DFRIBIDI_ENTRY=extern)

39
winbuild/raqm.cmake Normal file
View File

@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.13)
project(libraqm)
find_library(fribidi NAMES fribidi)
find_library(harfbuzz NAMES harfbuzz)
find_library(freetype NAMES freetype)
add_definitions(-DFRIBIDI_ENTRY=extern)
function(raqm_conf)
file(READ configure.ac RAQM_CONF)
string(REGEX MATCH "\\[([0-9]+)\\.([0-9]+)\\.([0-9]+)\\]," _ "${RAQM_CONF}")
set(RAQM_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(RAQM_VERSION_MINOR "${CMAKE_MATCH_2}")
set(RAQM_VERSION_MICRO "${CMAKE_MATCH_3}")
set(RAQM_VERSION "${RAQM_VERSION_MAJOR}.${RAQM_VERSION_MINOR}.${RAQM_VERSION_MICRO}")
message("detected libraqm version ${RAQM_VERSION}")
configure_file(src/raqm-version.h.in src/raqm-version.h @ONLY)
endfunction()
raqm_conf()
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(RAQM_SOURCES
src/raqm.c)
set(RAQM_HEADERS
src/raqm.h
src/raqm-version.h)
add_library(libraqm SHARED
${RAQM_SOURCES}
${RAQM_HEADERS})
target_link_libraries(libraqm
${fribidi}
${harfbuzz}
${freetype})