diff --git a/.appveyor.yml b/.appveyor.yml index 8ab594134..9ec837996 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -40,11 +40,6 @@ install: - xcopy c:\pillow-depends\*.tar.gz c:\pillow\winbuild\ - xcopy /s c:\pillow-depends\test_images\* c:\pillow\tests\images - cd c:\pillow\winbuild\ -- ps: | - if ($env:PYTHON -eq "c:/vp/pypy2") - { - c:\pillow\winbuild\appveyor_install_pypy2.cmd - } - ps: | if ($env:PYTHON -eq "c:/vp/pypy3") { @@ -61,6 +56,9 @@ install: c:\pillow\winbuild\build_deps.cmd $host.SetShouldExit(0) } +- curl -fsSL -o gs950.exe https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs950/gs950w32.exe +- gs950.exe /S +- path %path%;C:\Program Files (x86)\gs\gs9.50\bin build_script: - ps: | diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b3d456659..3d27b5d88 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -9,14 +9,14 @@ Please send a pull request to the master branch. Please include [documentation]( - Fork the Pillow repository. - Create a branch from master. - Develop bug fixes, features, tests, etc. -- Run the test suite on Python 2.7 and 3.x. You can enable [Travis CI](https://travis-ci.org/profile/) and [AppVeyor](https://ci.appveyor.com/projects/new) on your repo to catch test failures prior to the pull request, and [Codecov](https://codecov.io/gh) to see if the changed code is covered by tests. +- Run the test suite. You can enable [Travis CI](https://travis-ci.org/profile/) and [AppVeyor](https://ci.appveyor.com/projects/new) on your repo to catch test failures prior to the pull request, and [Codecov](https://codecov.io/gh) to see if the changed code is covered by tests. - Create a pull request to pull the changes from your branch to the Pillow master. ### Guidelines - Separate code commits from reformatting commits. - Provide tests for any newly added code. -- Follow PEP8. +- Follow PEP 8. - When committing only documentation changes please include [ci skip] in the commit message to avoid running tests on Travis-CI and AppVeyor. ## Reporting Issues diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index aa4761f68..bed18d155 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.5", "3.6", "3.7"] + python-version: ["3.5", "3.6", "3.7", "3.8", "pypy3.6"] architecture: ["x86", "x64"] include: - architecture: "x86" @@ -31,6 +31,11 @@ jobs: steps: - uses: actions/checkout@v1 + - uses: actions/checkout@v1 + with: + repository: python-pillow/pillow-depends + ref: master + - name: Cache uses: actions/cache@v1 with: @@ -73,24 +78,18 @@ jobs: - 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\" + 7z x ..\pillow-depends\nasm-2.14.02-win64.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" - # 32-bit should work on both platforms - curl -fsSL -o gs950.exe https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs950/gs950w32.exe - ./gs950.exe /S + ..\pillow-depends\gs950w32.exe /S Write-Host "`#`#[add-path]C:\Program Files (x86)\gs\gs9.50\bin" Write-Host "::add-path::C:\Program Files (x86)\gs\gs9.50\bin" $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\ + xcopy ..\pillow-depends\*.zip $env:GITHUB_WORKSPACE\winbuild\ + xcopy ..\pillow-depends\*.tar.gz $env:GITHUB_WORKSPACE\winbuild\ + xcopy /s ..\pillow-depends\test_images\* $env:GITHUB_WORKSPACE\tests\images\ cd $env:GITHUB_WORKSPACE/winbuild/ python.exe $env:GITHUB_WORKSPACE\winbuild\build_dep.py env: @@ -263,7 +262,6 @@ jobs: # 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 @@ -284,7 +282,6 @@ jobs: # 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 @@ -302,9 +299,7 @@ jobs: copy /Y /B *.lib %INCLIB% shell: cmd - # 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 @@ -334,6 +329,7 @@ jobs: set LIB=%INCLIB%;%PYTHON%\tcl set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE% call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }} + set MSSdk=1 set DISTUTILS_USE_SDK=1 set py_vcruntime_redist=true %PYTHON%\python.exe setup.py build_ext install diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 68d2731bb..d2151bee5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -91,5 +91,6 @@ jobs: run: | .travis/after_success.sh env: + MATRIX_OS: ${{ matrix.os }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} diff --git a/.travis.yml b/.travis.yml index 56542996b..9dea5fb14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ notifications: irc: "chat.freenode.net#pil" # Run fast lint first to get fast feedback. -# Run slow PyPy* next, to give them a headstart and reduce waiting time. -# Run latest 3.x and 2.x next, to get quick compatibility results. +# Run slow PyPy next, to give it a headstart and reduce waiting time. +# Run latest 3.x next, to get quick compatibility results. # Then run the remainder, with fastest Docker jobs last. matrix: diff --git a/.travis/after_success.sh b/.travis/after_success.sh index 1dca2ccb9..badf04484 100755 --- a/.travis/after_success.sh +++ b/.travis/after_success.sh @@ -1,7 +1,12 @@ #!/bin/bash # gather the coverage data -sudo apt-get -qq install lcov +if [[ "$MATRIX_OS" == "macOS-latest" ]]; then + brew install lcov +else + sudo apt-get -qq install lcov +fi + lcov --capture --directory . -b . --output-file coverage.info # filter to remove system headers lcov --remove coverage.info '/usr/*' -o coverage.filtered.info @@ -11,16 +16,12 @@ coveralls-lcov -v -n coverage.filtered.info > coverage.c.json coverage report pip install codecov -if [[ $TRAVIS_PYTHON_VERSION != "2.7_with_system_site_packages" ]]; then - # Not working here. Just skip it, it's being removed soon. - pip install coveralls-merge - coveralls-merge coverage.c.json -fi +pip install coveralls-merge +coveralls-merge coverage.c.json codecov -if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ] && [ "$DOCKER" == "" ]; then +if [ "$TRAVIS_PYTHON_VERSION" == "3.7" ] && [ "$DOCKER" == "" ]; then # Coverage and quality reports on just the latest diff. - # (Installation is very slow on Py3, so just do it for Py2.) depends/diffcover-install.sh depends/diffcover-run.sh fi diff --git a/.travis/install.sh b/.travis/install.sh index 6ad89402e..747acb448 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -20,8 +20,8 @@ if [[ $TRAVIS_PYTHON_VERSION == 3.* ]]; then pip install pyqt5 fi -# docs only on Python 2.7 -if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then pip install -r requirements.txt ; fi +# docs only on Python 3.7 +if [ "$TRAVIS_PYTHON_VERSION" == "3.7" ]; then pip install -r requirements.txt ; fi # webp pushd depends && ./install_webp.sh && popd diff --git a/.travis/test.sh b/.travis/test.sh index 67c390ebd..a65e620b8 100755 --- a/.travis/test.sh +++ b/.travis/test.sh @@ -5,4 +5,4 @@ set -e python -m pytest -v -x --cov PIL --cov-report term Tests # Docs -if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then make doccheck; fi +if [ "$TRAVIS_PYTHON_VERSION" == "3.7" ]; then make doccheck; fi diff --git a/CHANGES.rst b/CHANGES.rst index eb96600ed..d3922f328 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,15 @@ Changelog (Pillow) 7.0.0 (unreleased) ------------------ +- Drop support for EOL Python 2.7 #4109 + [hugovk, radarhere, jdufresne] + +- Added UnidentifiedImageError #4182 + [radarhere, hugovk] + +- Remove deprecated __version__ from plugins #4197 + [hugovk, radarhere] + - Fixed freeing unallocated pointer when resizing with height too large #4116 [radarhere] @@ -14,7 +23,7 @@ Changelog (Pillow) - Corrected DdsImagePlugin setting info gamma #4171 [radarhere] -- Depends: Update libtiff to 4.1.0 #4195 +- Depends: Update libtiff to 4.1.0 #4195, Tk Tcl to 8.6.10 #4229 [radarhere] - Improve handling of file resources #3577 diff --git a/Makefile b/Makefile index 1803e617d..fdde3416b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ .DEFAULT_GOAL := release-test clean: - python setup.py clean + python3 setup.py clean rm src/PIL/*.so || true rm -r build || true find . -name __pycache__ | xargs rm -r || true @@ -15,8 +15,8 @@ co: done coverage: - python selftest.py - python setup.py test + python3 selftest.py + python3 setup.py test rm -r htmlcov || true coverage report @@ -30,7 +30,7 @@ doccheck: $(MAKE) -C docs linkcheck || true docserve: - cd docs/_build/html && python -mSimpleHTTPServer 2> /dev/null& + cd docs/_build/html && python3 -mSimpleHTTPServer 2> /dev/null& help: @echo "Welcome to Pillow development. Please use \`make \` where is one of" @@ -50,22 +50,22 @@ help: @echo " upload-test build and upload sdists to test.pythonpackages.com" inplace: clean - python setup.py develop build_ext --inplace + python3 setup.py develop build_ext --inplace install: - python setup.py install - python selftest.py + python3 setup.py install + python3 selftest.py install-coverage: - CFLAGS="-coverage" python setup.py build_ext install - python selftest.py + CFLAGS="-coverage" python3 setup.py build_ext install + python3 selftest.py debug: # make a debug version if we don't have a -dbg python. Leaves in symbols # for our stuff, kills optimization, and redirects to dev null so we # see any build failures. make clean > /dev/null - CFLAGS='-g -O0' python setup.py build_ext install > /dev/null + CFLAGS='-g -O0' python3 setup.py build_ext install > /dev/null install-req: pip install -r requirements.txt @@ -76,17 +76,17 @@ install-venv: release-test: $(MAKE) install-req - python setup.py develop - python selftest.py - python -m pytest Tests - python setup.py install - python -m pytest -qq + python3 setup.py develop + python3 selftest.py + python3 -m pytest Tests + python3 setup.py install + python3 -m pytest -qq check-manifest pyroma . viewdoc sdist: - python setup.py sdist --format=gztar + python3 setup.py sdist --format=gztar test: pytest -qq @@ -97,10 +97,10 @@ upload-test: # username: # password: # repository = http://test.pythonpackages.com - python setup.py sdist --format=gztar upload -r test + python3 setup.py sdist --format=gztar upload -r test upload: - python setup.py sdist --format=gztar upload + python3 setup.py sdist --format=gztar upload readme: viewdoc diff --git a/Tests/bench_cffi_access.py b/Tests/bench_cffi_access.py index 99c7006fa..1797d34fc 100644 --- a/Tests/bench_cffi_access.py +++ b/Tests/bench_cffi_access.py @@ -1,8 +1,9 @@ import time +import unittest from PIL import PyAccess -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper # Not running this test by default. No DOS against Travis CI. diff --git a/Tests/check_fli_overflow.py b/Tests/check_fli_overflow.py index db6559f1e..fa6037c2e 100644 --- a/Tests/check_fli_overflow.py +++ b/Tests/check_fli_overflow.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase TEST_FILE = "Tests/images/fli_overflow.fli" diff --git a/Tests/check_imaging_leaks.py b/Tests/check_imaging_leaks.py index a109b5cd5..2c1793a4f 100755 --- a/Tests/check_imaging_leaks.py +++ b/Tests/check_imaging_leaks.py @@ -1,10 +1,9 @@ #!/usr/bin/env python - -from __future__ import division +import unittest from PIL import Image -from .helper import PillowTestCase, is_win32, unittest +from .helper import PillowTestCase, is_win32 min_iterations = 100 max_iterations = 10000 diff --git a/Tests/check_j2k_leaks.py b/Tests/check_j2k_leaks.py index d9c6c68b7..1635f1001 100755 --- a/Tests/check_j2k_leaks.py +++ b/Tests/check_j2k_leaks.py @@ -1,8 +1,9 @@ +import unittest from io import BytesIO from PIL import Image -from .helper import PillowTestCase, is_win32, unittest +from .helper import PillowTestCase, is_win32 # Limits for testing the leak mem_limit = 1024 * 1048576 diff --git a/Tests/check_j2k_overflow.py b/Tests/check_j2k_overflow.py index 3e6cf8d34..d5b6e455f 100644 --- a/Tests/check_j2k_overflow.py +++ b/Tests/check_j2k_overflow.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase class TestJ2kEncodeOverflow(PillowTestCase): diff --git a/Tests/check_jpeg_leaks.py b/Tests/check_jpeg_leaks.py index 8cb93f2dd..6b2801a21 100644 --- a/Tests/check_jpeg_leaks.py +++ b/Tests/check_jpeg_leaks.py @@ -1,6 +1,7 @@ +import unittest from io import BytesIO -from .helper import PillowTestCase, hopper, is_win32, unittest +from .helper import PillowTestCase, hopper, is_win32 iterations = 5000 diff --git a/Tests/check_large_memory.py b/Tests/check_large_memory.py index 5df476e0a..7fcaa4cf9 100644 --- a/Tests/check_large_memory.py +++ b/Tests/check_large_memory.py @@ -1,8 +1,9 @@ import sys +import unittest from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase # This test is not run automatically. # diff --git a/Tests/check_large_memory_numpy.py b/Tests/check_large_memory_numpy.py index 4653a6013..8e65dc1cb 100644 --- a/Tests/check_large_memory_numpy.py +++ b/Tests/check_large_memory_numpy.py @@ -1,8 +1,9 @@ import sys +import unittest from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase # This test is not run automatically. # diff --git a/Tests/check_libtiff_segfault.py b/Tests/check_libtiff_segfault.py index ae9a46d1b..a0263f725 100644 --- a/Tests/check_libtiff_segfault.py +++ b/Tests/check_libtiff_segfault.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase TEST_FILE = "Tests/images/libtiff_segfault.tif" diff --git a/Tests/check_png_dos.py b/Tests/check_png_dos.py index 5c78ce122..f133b2695 100644 --- a/Tests/check_png_dos.py +++ b/Tests/check_png_dos.py @@ -1,9 +1,10 @@ +import unittest import zlib from io import BytesIO from PIL import Image, ImageFile, PngImagePlugin -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase TEST_FILE = "Tests/images/png_decompression_dos.png" diff --git a/Tests/createfontdatachunk.py b/Tests/createfontdatachunk.py index 4d189dbad..c7055995e 100755 --- a/Tests/createfontdatachunk.py +++ b/Tests/createfontdatachunk.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function - import base64 import os diff --git a/Tests/helper.py b/Tests/helper.py index 57bbab0c9..0f8e05c19 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -1,7 +1,6 @@ """ Helper functions. """ -from __future__ import print_function import logging import os @@ -12,7 +11,6 @@ import unittest from io import BytesIO from PIL import Image, ImageMath -from PIL._util import py3 logger = logging.getLogger(__name__) @@ -76,10 +74,13 @@ class PillowTestCase(unittest.TestCase): def assert_deep_equal(self, a, b, msg=None): try: self.assertEqual( - len(a), len(b), msg or "got length %s, expected %s" % (len(a), len(b)) + len(a), + len(b), + msg or "got length {}, expected {}".format(len(a), len(b)), ) self.assertTrue( - all(x == y for x, y in zip(a, b)), msg or "got %s, expected %s" % (a, b) + all(x == y for x, y in zip(a, b)), + msg or "got {}, expected {}".format(a, b), ) except Exception: self.assertEqual(a, b, msg) @@ -87,20 +88,24 @@ class PillowTestCase(unittest.TestCase): def assert_image(self, im, mode, size, msg=None): if mode is not None: self.assertEqual( - im.mode, mode, msg or "got mode %r, expected %r" % (im.mode, mode) + im.mode, + mode, + msg or "got mode {!r}, expected {!r}".format(im.mode, mode), ) if size is not None: self.assertEqual( - im.size, size, msg or "got size %r, expected %r" % (im.size, size) + im.size, + size, + msg or "got size {!r}, expected {!r}".format(im.size, size), ) def assert_image_equal(self, a, b, msg=None): self.assertEqual( - a.mode, b.mode, msg or "got mode %r, expected %r" % (a.mode, b.mode) + a.mode, b.mode, msg or "got mode {!r}, expected {!r}".format(a.mode, b.mode) ) self.assertEqual( - a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size) + a.size, b.size, msg or "got size {!r}, expected {!r}".format(a.size, b.size) ) if a.tobytes() != b.tobytes(): if HAS_UPLOADER: @@ -121,10 +126,10 @@ class PillowTestCase(unittest.TestCase): def assert_image_similar(self, a, b, epsilon, msg=None): epsilon = float(epsilon) self.assertEqual( - a.mode, b.mode, msg or "got mode %r, expected %r" % (a.mode, b.mode) + a.mode, b.mode, msg or "got mode {!r}, expected {!r}".format(a.mode, b.mode) ) self.assertEqual( - a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size) + a.size, b.size, msg or "got size {!r}, expected {!r}".format(a.size, b.size) ) a, b = convert_to_comparable(a, b) @@ -216,12 +221,12 @@ class PillowTestCase(unittest.TestCase): def open_withImagemagick(self, f): if not imagemagick_available(): - raise IOError() + raise OSError() outfile = self.tempfile("temp.png") if command_succeeds([IMCONVERT, f, outfile]): return Image.open(outfile) - raise IOError() + raise OSError() @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") @@ -264,11 +269,6 @@ class PillowLeakTestCase(PillowTestCase): # helpers -if not py3: - # Remove DeprecationWarning in Python 3 - PillowTestCase.assertRaisesRegex = PillowTestCase.assertRaisesRegexp - PillowTestCase.assertRegex = PillowTestCase.assertRegexpMatches - def fromstring(data): return Image.open(BytesIO(data)) @@ -306,11 +306,10 @@ def command_succeeds(cmd): Runs the command, which must be a list of strings. Returns True if the command succeeds, or False if an OSError was raised by subprocess.Popen. """ - with open(os.devnull, "wb") as f: - try: - subprocess.call(cmd, stdout=f, stderr=subprocess.STDOUT) - except OSError: - return False + try: + subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) + except OSError: + return False return True @@ -373,7 +372,7 @@ def distro(): return line.strip().split("=")[1] -class cached_property(object): +class cached_property: def __init__(self, func): self.func = func diff --git a/Tests/import_all.py b/Tests/import_all.py index 4dfacb291..33b07f9a2 100644 --- a/Tests/import_all.py +++ b/Tests/import_all.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import glob import os import sys diff --git a/Tests/make_hash.py b/Tests/make_hash.py index bacb391fa..7199f8c7f 100644 --- a/Tests/make_hash.py +++ b/Tests/make_hash.py @@ -1,7 +1,5 @@ # brute-force search for access descriptor hash table -from __future__ import print_function - modes = [ "1", "L", diff --git a/Tests/test_bmp_reference.py b/Tests/test_bmp_reference.py index f7a60cfd7..3a33d2c8a 100644 --- a/Tests/test_bmp_reference.py +++ b/Tests/test_bmp_reference.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import os from PIL import Image @@ -109,4 +107,4 @@ class TestBmpReference(PillowTestCase): os.path.join(base, "g", "pal4rle.bmp"), ) if f not in unsupported: - self.fail("Unsupported Image %s: %s" % (f, msg)) + self.fail("Unsupported Image {}: {}".format(f, msg)) diff --git a/Tests/test_color_lut.py b/Tests/test_color_lut.py index ca82209c2..96461ca3a 100644 --- a/Tests/test_color_lut.py +++ b/Tests/test_color_lut.py @@ -1,10 +1,9 @@ -from __future__ import division - +import unittest from array import array from PIL import Image, ImageFilter -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase try: import numpy diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py index 0aedb91c9..ac2970de2 100644 --- a/Tests/test_core_resources.py +++ b/Tests/test_core_resources.py @@ -1,10 +1,9 @@ -from __future__ import division, print_function - import sys +import unittest from PIL import Image -from .helper import PillowTestCase, is_pypy, unittest +from .helper import PillowTestCase, is_pypy class TestCoreStats(PillowTestCase): diff --git a/Tests/test_features.py b/Tests/test_features.py index 06da35ee4..eb51407a1 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -1,10 +1,9 @@ -from __future__ import unicode_literals - import io +import unittest from PIL import features -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase try: from PIL import _webp diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py index 9b1a1ec40..0ab14e4eb 100644 --- a/Tests/test_file_eps.py +++ b/Tests/test_file_eps.py @@ -1,8 +1,9 @@ import io +import unittest from PIL import EpsImagePlugin, Image -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper HAS_GHOSTSCRIPT = EpsImagePlugin.has_ghostscript() @@ -91,7 +92,7 @@ class TestFileEps(PillowTestCase): def test_iobase_object(self): # issue 479 with Image.open(file1) as image1: - with io.open(self.tempfile("temp_iobase.eps"), "wb") as fh: + with open(self.tempfile("temp_iobase.eps"), "wb") as fh: image1.save(fh, "EPS") @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") diff --git a/Tests/test_file_fpx.py b/Tests/test_file_fpx.py index 68412c8ca..7c985be30 100644 --- a/Tests/test_file_fpx.py +++ b/Tests/test_file_fpx.py @@ -1,4 +1,6 @@ -from .helper import PillowTestCase, unittest +import unittest + +from .helper import PillowTestCase try: from PIL import FpxImagePlugin diff --git a/Tests/test_file_gd.py b/Tests/test_file_gd.py index 9208dcbff..0b7543a31 100644 --- a/Tests/test_file_gd.py +++ b/Tests/test_file_gd.py @@ -1,4 +1,4 @@ -from PIL import GdImageFile +from PIL import GdImageFile, UnidentifiedImageError from .helper import PillowTestCase @@ -17,4 +17,4 @@ class TestFileGd(PillowTestCase): def test_invalid_file(self): invalid_file = "Tests/images/flower.jpg" - self.assertRaises(IOError, GdImageFile.open, invalid_file) + self.assertRaises(UnidentifiedImageError, GdImageFile.open, invalid_file) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 7c1de5891..bed25c890 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -1,8 +1,9 @@ +import unittest from io import BytesIO from PIL import GifImagePlugin, Image, ImageDraw, ImagePalette -from .helper import PillowTestCase, hopper, is_pypy, netpbm_available, unittest +from .helper import PillowTestCase, hopper, is_pypy, netpbm_available try: from PIL import _webp @@ -87,9 +88,7 @@ class TestFileGif(PillowTestCase): def check(colors, size, expected_palette_length): # make an image with empty colors in the start of the palette range im = Image.frombytes( - "P", - (colors, colors), - bytes(bytearray(range(256 - colors, 256)) * colors), + "P", (colors, colors), bytes(range(256 - colors, 256)) * colors ) im = im.resize((size, size)) outfile = BytesIO() @@ -119,7 +118,7 @@ class TestFileGif(PillowTestCase): check(256, 511, 256) def test_optimize_full_l(self): - im = Image.frombytes("L", (16, 16), bytes(bytearray(range(256)))) + im = Image.frombytes("L", (16, 16), bytes(range(256))) test_file = BytesIO() im.save(test_file, "GIF", optimize=True) self.assertEqual(im.mode, "L") @@ -632,8 +631,7 @@ class TestFileGif(PillowTestCase): # Tests appending using a generator def imGenerator(ims): - for im in ims: - yield im + yield from ims im.save(out, save_all=True, append_images=imGenerator(ims)) @@ -655,7 +653,7 @@ class TestFileGif(PillowTestCase): # that's > 128 items where the transparent color is actually # the top palette entry to trigger the bug. - data = bytes(bytearray(range(1, 254))) + data = bytes(range(1, 254)) palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3) im = Image.new("L", (253, 1)) @@ -703,7 +701,7 @@ class TestFileGif(PillowTestCase): im = hopper("P") im_l = Image.frombytes("L", im.size, im.tobytes()) - palette = bytes(bytearray(im.getpalette())) + palette = bytes(im.getpalette()) out = self.tempfile("temp.gif") im_l.save(out, palette=palette) @@ -718,7 +716,7 @@ class TestFileGif(PillowTestCase): # Forcing a non-straight grayscale palette. im = hopper("P") - palette = bytes(bytearray([255 - i // 3 for i in range(768)])) + palette = bytes([255 - i // 3 for i in range(768)]) out = self.tempfile("temp.gif") im.save(out, palette=palette) @@ -759,7 +757,7 @@ class TestFileGif(PillowTestCase): im.putpalette(ImagePalette.ImagePalette("RGB")) im.info = {"background": 0} - passed_palette = bytes(bytearray([255 - i // 3 for i in range(768)])) + passed_palette = bytes([255 - i // 3 for i in range(768)]) GifImagePlugin._FORCE_OPTIMIZE = True try: diff --git a/Tests/test_file_icns.py b/Tests/test_file_icns.py index 4d7f95ec3..e258601ce 100644 --- a/Tests/test_file_icns.py +++ b/Tests/test_file_icns.py @@ -1,9 +1,10 @@ import io import sys +import unittest from PIL import IcnsImagePlugin, Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase # sample icon file TEST_FILE = "Tests/images/pillow.icns" diff --git a/Tests/test_file_iptc.py b/Tests/test_file_iptc.py index 1dd18a759..b6cc4c225 100644 --- a/Tests/test_file_iptc.py +++ b/Tests/test_file_iptc.py @@ -1,3 +1,6 @@ +import sys +from io import StringIO + from PIL import Image, IptcImagePlugin from .helper import PillowTestCase, hopper @@ -52,12 +55,6 @@ class TestFileIptc(PillowTestCase): # Arrange c = b"abc" # Temporarily redirect stdout - try: - from cStringIO import StringIO - except ImportError: - from io import StringIO - import sys - old_stdout = sys.stdout sys.stdout = mystdout = StringIO() diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index e7c3615c2..dba053e60 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import base64 import distutils.version import io @@ -10,7 +8,6 @@ from collections import namedtuple from ctypes import c_float from PIL import Image, TiffImagePlugin, TiffTags, features -from PIL._util import py3 from .helper import PillowTestCase, hopper @@ -263,7 +260,6 @@ class TestFileLibTiff(LibTiffTestCase): tc(4.25, TiffTags.FLOAT, True), tc(4.25, TiffTags.DOUBLE, True), tc("custom tag value", TiffTags.ASCII, True), - tc(u"custom tag value", TiffTags.ASCII, True), tc(b"custom tag value", TiffTags.BYTE, True), tc((4, 5, 6), TiffTags.SHORT, True), tc((123456789, 9, 34, 234, 219387, 92432323), TiffTags.LONG, True), @@ -361,12 +357,8 @@ class TestFileLibTiff(LibTiffTestCase): b = im.tobytes() # Bytes are in image native order (little endian) - if py3: - self.assertEqual(b[0], ord(b"\xe0")) - self.assertEqual(b[1], ord(b"\x01")) - else: - self.assertEqual(b[0], b"\xe0") - self.assertEqual(b[1], b"\x01") + self.assertEqual(b[0], ord(b"\xe0")) + self.assertEqual(b[1], ord(b"\x01")) out = self.tempfile("temp.tif") # out = "temp.le.tif" @@ -387,12 +379,8 @@ class TestFileLibTiff(LibTiffTestCase): b = im.tobytes() # Bytes are in image native order (big endian) - if py3: - self.assertEqual(b[0], ord(b"\x01")) - self.assertEqual(b[1], ord(b"\xe0")) - else: - self.assertEqual(b[0], b"\x01") - self.assertEqual(b[1], b"\xe0") + self.assertEqual(b[0], ord(b"\x01")) + self.assertEqual(b[1], ord(b"\xe0")) out = self.tempfile("temp.tif") im.save(out) diff --git a/Tests/test_file_mic.py b/Tests/test_file_mic.py index f9ea7712c..00f42fa4a 100644 --- a/Tests/test_file_mic.py +++ b/Tests/test_file_mic.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image, ImagePalette, features -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper try: from PIL import MicImagePlugin diff --git a/Tests/test_file_msp.py b/Tests/test_file_msp.py index 5d512047b..d717ade16 100644 --- a/Tests/test_file_msp.py +++ b/Tests/test_file_msp.py @@ -1,8 +1,9 @@ import os +import unittest from PIL import Image, MspImagePlugin -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper TEST_FILE = "Tests/images/hopper.msp" EXTRA_DIR = "Tests/images/picins" diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index c4f64a0a0..4b5897589 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -99,8 +99,7 @@ class TestFilePdf(PillowTestCase): # Test appending using a generator def imGenerator(ims): - for im in ims: - yield im + yield from ims im.save(outfile, save_all=True, append_images=imGenerator(ims)) @@ -163,13 +162,10 @@ class TestFilePdf(PillowTestCase): def test_pdf_append_fails_on_nonexistent_file(self): im = hopper("RGB") - temp_dir = tempfile.mkdtemp() - try: + with tempfile.TemporaryDirectory() as temp_dir: self.assertRaises( IOError, im.save, os.path.join(temp_dir, "nonexistent.pdf"), append=True ) - finally: - os.rmdir(temp_dir) def check_pdf_pages_consistency(self, pdf): pages_info = pdf.read_indirect(pdf.pages_ref) @@ -207,7 +203,7 @@ class TestFilePdf(PillowTestCase): # append some info pdf.info.Title = "abc" pdf.info.Author = "def" - pdf.info.Subject = u"ghi\uABCD" + pdf.info.Subject = "ghi\uABCD" pdf.info.Keywords = "qw)e\\r(ty" pdf.info.Creator = "hopper()" pdf.start_writing() @@ -235,7 +231,7 @@ class TestFilePdf(PillowTestCase): self.assertEqual(pdf.info.Title, "abc") self.assertEqual(pdf.info.Producer, "PdfParser") self.assertEqual(pdf.info.Keywords, "qw)e\\r(ty") - self.assertEqual(pdf.info.Subject, u"ghi\uABCD") + self.assertEqual(pdf.info.Subject, "ghi\uABCD") self.assertIn(b"CreationDate", pdf.info) self.assertIn(b"ModDate", pdf.info) self.check_pdf_pages_consistency(pdf) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index ee2a95255..c9c337e64 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -1,10 +1,10 @@ +import unittest import zlib from io import BytesIO from PIL import Image, ImageFile, PngImagePlugin -from PIL._util import py3 -from .helper import PillowLeakTestCase, PillowTestCase, hopper, is_win32, unittest +from .helper import PillowLeakTestCase, PillowTestCase, hopper, is_win32 try: from PIL import _webp @@ -448,9 +448,7 @@ class TestFilePng(PillowTestCase): self.assertIsInstance(im.info["Text"], str) def test_unicode_text(self): - # Check preservation of non-ASCII characters on Python 3 - # This cannot really be meaningfully tested on Python 2, - # since it didn't preserve charsets to begin with. + # Check preservation of non-ASCII characters def rt_text(value): im = Image.new("RGB", (32, 32)) @@ -459,17 +457,11 @@ class TestFilePng(PillowTestCase): im = roundtrip(im, pnginfo=info) self.assertEqual(im.info, {"Text": value}) - if py3: - rt_text(" Aa" + chr(0xA0) + chr(0xC4) + chr(0xFF)) # Latin1 - rt_text(chr(0x400) + chr(0x472) + chr(0x4FF)) # Cyrillic - rt_text( - chr(0x4E00) - + chr(0x66F0) - + chr(0x9FBA) # CJK - + chr(0x3042) - + chr(0xAC00) - ) - rt_text("A" + chr(0xC4) + chr(0x472) + chr(0x3042)) # Combined + rt_text(" Aa" + chr(0xA0) + chr(0xC4) + chr(0xFF)) # Latin1 + rt_text(chr(0x400) + chr(0x472) + chr(0x4FF)) # Cyrillic + # CJK: + rt_text(chr(0x4E00) + chr(0x66F0) + chr(0x9FBA) + chr(0x3042) + chr(0xAC00)) + rt_text("A" + chr(0xC4) + chr(0x472) + chr(0x3042)) # Combined def test_scary(self): # Check reading of evil PNG file. For information, see: diff --git a/Tests/test_file_sun.py b/Tests/test_file_sun.py index 84d59e0c7..5fc171054 100644 --- a/Tests/test_file_sun.py +++ b/Tests/test_file_sun.py @@ -1,8 +1,9 @@ import os +import unittest from PIL import Image, SunImagePlugin -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper EXTRA_DIR = "Tests/images/sunraster" diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 146bf1851..a4346a7b5 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -1,13 +1,13 @@ import logging import os +import unittest from io import BytesIO import pytest from PIL import Image, TiffImagePlugin -from PIL._util import py3 from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION -from .helper import PillowTestCase, hopper, is_pypy, is_win32, unittest +from .helper import PillowTestCase, hopper, is_pypy, is_win32 logger = logging.getLogger(__name__) @@ -198,12 +198,8 @@ class TestFileTiff(PillowTestCase): b = im.tobytes() # Bytes are in image native order (little endian) - if py3: - self.assertEqual(b[0], ord(b"\xe0")) - self.assertEqual(b[1], ord(b"\x01")) - else: - self.assertEqual(b[0], b"\xe0") - self.assertEqual(b[1], b"\x01") + self.assertEqual(b[0], ord(b"\xe0")) + self.assertEqual(b[1], ord(b"\x01")) def test_big_endian(self): im = Image.open("Tests/images/16bit.MM.cropped.tif") @@ -213,12 +209,8 @@ class TestFileTiff(PillowTestCase): b = im.tobytes() # Bytes are in image native order (big endian) - if py3: - self.assertEqual(b[0], ord(b"\x01")) - self.assertEqual(b[1], ord(b"\xe0")) - else: - self.assertEqual(b[0], b"\x01") - self.assertEqual(b[1], b"\xe0") + self.assertEqual(b[0], ord(b"\x01")) + self.assertEqual(b[1], ord(b"\xe0")) def test_16bit_s(self): im = Image.open("Tests/images/16bit.s.tif") @@ -545,8 +537,7 @@ class TestFileTiff(PillowTestCase): # Test appending using a generator def imGenerator(ims): - for im in ims: - yield im + yield from ims mp = BytesIO() im.save(mp, format="TIFF", save_all=True, append_images=imGenerator(ims)) diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index 09b510511..7393a147c 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -161,13 +161,13 @@ class TestFileTiffMetadata(PillowTestCase): self.assert_deep_equal( original[tag], value, - "%s didn't roundtrip, %s, %s" % (tag, original[tag], value), + "{} didn't roundtrip, {}, {}".format(tag, original[tag], value), ) else: self.assertEqual( original[tag], value, - "%s didn't roundtrip, %s, %s" % (tag, original[tag], value), + "{} didn't roundtrip, {}, {}".format(tag, original[tag], value), ) for tag, value in original.items(): diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 35ce3dba7..685f876e2 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image, WebPImagePlugin -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper try: from PIL import _webp diff --git a/Tests/test_file_webp_alpha.py b/Tests/test_file_webp_alpha.py index 9693f691f..e3c2b98b9 100644 --- a/Tests/test_file_webp_alpha.py +++ b/Tests/test_file_webp_alpha.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper try: from PIL import _webp diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py index a5d71093d..834080db8 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -91,8 +91,7 @@ class TestFileWebpAnimation(PillowTestCase): # Tests appending using a generator def imGenerator(ims): - for im in ims: - yield im + yield from ims temp_file2 = self.tempfile("temp_generator.webp") frame1.copy().save( diff --git a/Tests/test_file_webp_metadata.py b/Tests/test_file_webp_metadata.py index 6a25ea261..e3acf745d 100644 --- a/Tests/test_file_webp_metadata.py +++ b/Tests/test_file_webp_metadata.py @@ -110,9 +110,9 @@ class TestFileWebpMetadata(PillowTestCase): if not _webp.HAVE_WEBPANIM: self.skipTest("WebP animation support not available") - iccp_data = "".encode("utf-8") - exif_data = "".encode("utf-8") - xmp_data = "".encode("utf-8") + iccp_data = b"" + exif_data = b"" + xmp_data = b"" temp_file = self.tempfile("temp.webp") frame1 = Image.open("Tests/images/anim_frame1.webp") diff --git a/Tests/test_font_leaks.py b/Tests/test_font_leaks.py index 9b5fe2055..393ddb0fb 100644 --- a/Tests/test_font_leaks.py +++ b/Tests/test_font_leaks.py @@ -1,8 +1,8 @@ -from __future__ import division +import unittest from PIL import Image, ImageDraw, ImageFont, features -from .helper import PillowLeakTestCase, is_win32, unittest +from .helper import PillowLeakTestCase, is_win32 @unittest.skipIf(is_win32(), "requires Unix or macOS") diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index a2b4ef27e..e37f43207 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -1,5 +1,4 @@ from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile -from PIL._util import py3 from .helper import PillowTestCase @@ -74,6 +73,5 @@ class TestFontPcf(PillowTestCase): def test_high_characters(self): message = "".join(chr(i + 1) for i in range(140, 232)) self._test_high_characters(message) - # accept bytes instances in Py3. - if py3: - self._test_high_characters(message.encode("latin1")) + # accept bytes instances. + self._test_high_characters(message.encode("latin1")) diff --git a/Tests/test_format_hsv.py b/Tests/test_format_hsv.py index ce0524e1e..e80e16ffe 100644 --- a/Tests/test_format_hsv.py +++ b/Tests/test_format_hsv.py @@ -2,7 +2,6 @@ import colorsys import itertools from PIL import Image -from PIL._util import py3 from .helper import PillowTestCase, hopper @@ -49,27 +48,18 @@ class TestFormatHSV(PillowTestCase): (r, g, b) = im.split() - if py3: - conv_func = self.int_to_float - else: - conv_func = self.str_to_float - - if hasattr(itertools, "izip"): - iter_helper = itertools.izip - else: - iter_helper = itertools.zip_longest + conv_func = self.int_to_float converted = [ self.tuple_to_ints(func(conv_func(_r), conv_func(_g), conv_func(_b))) - for (_r, _g, _b) in iter_helper(r.tobytes(), g.tobytes(), b.tobytes()) + for (_r, _g, _b) in itertools.zip_longest( + r.tobytes(), g.tobytes(), b.tobytes() + ) ] - if py3: - new_bytes = b"".join( - bytes(chr(h) + chr(s) + chr(v), "latin-1") for (h, s, v) in converted - ) - else: - new_bytes = b"".join(chr(h) + chr(s) + chr(v) for (h, s, v) in converted) + new_bytes = b"".join( + bytes(chr(h) + chr(s) + chr(v), "latin-1") for (h, s, v) in converted + ) hsv = Image.frombytes(mode, r.size, new_bytes) diff --git a/Tests/test_image.py b/Tests/test_image.py index b494b17dc..15cf435b0 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,11 +1,11 @@ import os import shutil import tempfile +import unittest -from PIL import Image -from PIL._util import py3 +from PIL import Image, UnidentifiedImageError -from .helper import PillowTestCase, hopper, is_win32, unittest +from .helper import PillowTestCase, hopper, is_win32 class TestImage(PillowTestCase): @@ -48,6 +48,9 @@ class TestImage(PillowTestCase): Image.new(mode, (1, 1)) self.assertEqual(str(e.exception), "unrecognized image mode") + def test_exception_inheritance(self): + self.assertTrue(issubclass(UnidentifiedImageError, IOError)) + def test_sanity(self): im = Image.new("L", (100, 100)) @@ -80,20 +83,14 @@ class TestImage(PillowTestCase): im.size = (3, 4) def test_invalid_image(self): - if py3: - import io + import io - im = io.BytesIO(b"") - else: - import StringIO - - im = StringIO.StringIO("") - self.assertRaises(IOError, Image.open, im) + im = io.BytesIO(b"") + self.assertRaises(UnidentifiedImageError, Image.open, im) def test_bad_mode(self): self.assertRaises(ValueError, Image.open, "filename", "bad mode") - @unittest.skipUnless(Image.HAS_PATHLIB, "requires pathlib/pathlib2") def test_pathlib(self): from PIL.Image import Path @@ -113,7 +110,7 @@ class TestImage(PillowTestCase): def test_fp_name(self): temp_file = self.tempfile("temp.jpg") - class FP(object): + class FP: def write(a, b): pass @@ -592,11 +589,11 @@ class TestImage(PillowTestCase): try: im.load() self.assertFail() - except IOError as e: + except OSError as e: self.assertEqual(str(e), "buffer overrun when reading image file") -class MockEncoder(object): +class MockEncoder: pass diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index d7bd828e9..57bac753d 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -2,11 +2,12 @@ import ctypes import os import subprocess import sys +import unittest from distutils import ccompiler, sysconfig from PIL import Image -from .helper import PillowTestCase, hopper, is_win32, on_ci, unittest +from .helper import PillowTestCase, hopper, is_win32, on_ci # CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2 # https://github.com/eliben/pycparser/pull/198#issuecomment-317001670 @@ -125,7 +126,7 @@ class TestImageGetPixel(AccessTest): self.assertEqual( im.getpixel((0, 0)), c, - "put/getpixel roundtrip failed for mode %s, color %s" % (mode, c), + "put/getpixel roundtrip failed for mode {}, color {}".format(mode, c), ) # check putpixel negative index @@ -154,7 +155,7 @@ class TestImageGetPixel(AccessTest): self.assertEqual( im.getpixel((0, 0)), c, - "initial color failed for mode %s, color %s " % (mode, c), + "initial color failed for mode {}, color {} ".format(mode, c), ) # check initial color negative index self.assertEqual( @@ -348,12 +349,8 @@ class TestEmbeddable(unittest.TestCase): int main(int argc, char* argv[]) { char *home = "%s"; -#if PY_MAJOR_VERSION >= 3 wchar_t *whome = Py_DecodeLocale(home, NULL); Py_SetPythonHome(whome); -#else - Py_SetPythonHome(home); -#endif Py_InitializeEx(0); Py_DECREF(PyImport_ImportModule("PIL.Image")); @@ -363,9 +360,7 @@ int main(int argc, char* argv[]) Py_DECREF(PyImport_ImportModule("PIL.Image")); Py_Finalize(); -#if PY_MAJOR_VERSION >= 3 PyMem_RawFree(whome); -#endif return 0; } diff --git a/Tests/test_image_array.py b/Tests/test_image_array.py index 02e5c80f2..8277e42af 100644 --- a/Tests/test_image_array.py +++ b/Tests/test_image_array.py @@ -25,7 +25,7 @@ class TestImageArray(PillowTestCase): self.assertEqual(test("RGBX"), (3, (100, 128, 4), "|u1", 51200)) def test_fromarray(self): - class Wrapper(object): + class Wrapper: """ Class with API matching Image.fromarray """ def __init__(self, img, arr_params): diff --git a/Tests/test_image_fromqimage.py b/Tests/test_image_fromqimage.py index bf3a250f3..0d961572c 100644 --- a/Tests/test_image_fromqimage.py +++ b/Tests/test_image_fromqimage.py @@ -6,7 +6,7 @@ from .test_imageqt import PillowQtTestCase class TestFromQImage(PillowQtTestCase, PillowTestCase): def setUp(self): - super(TestFromQImage, self).setUp() + super().setUp() self.files_to_test = [ hopper(), Image.open("Tests/images/transparent.png"), diff --git a/Tests/test_image_getim.py b/Tests/test_image_getim.py index 3f0c46c46..f6908af4b 100644 --- a/Tests/test_image_getim.py +++ b/Tests/test_image_getim.py @@ -1,5 +1,3 @@ -from PIL._util import py3 - from .helper import PillowTestCase, hopper @@ -8,7 +6,5 @@ class TestImageGetIm(PillowTestCase): im = hopper() type_repr = repr(type(im.getim())) - if py3: - self.assertIn("PyCapsule", type_repr) - + self.assertIn("PyCapsule", type_repr) self.assertIsInstance(im.im.id, int) diff --git a/Tests/test_image_resample.py b/Tests/test_image_resample.py index 854a64d01..00c8fa5f2 100644 --- a/Tests/test_image_resample.py +++ b/Tests/test_image_resample.py @@ -1,10 +1,9 @@ -from __future__ import division, print_function - +import unittest from contextlib import contextmanager from PIL import Image, ImageDraw -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper class TestImagingResampleVulnerability(PillowTestCase): diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 75e658d65..50a774df2 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -1,8 +1,9 @@ import os.path +import unittest from PIL import Image, ImageColor, ImageDraw, ImageFont, features -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper BLACK = (0, 0, 0) WHITE = (255, 255, 255) diff --git a/Tests/test_imagedraw2.py b/Tests/test_imagedraw2.py index 9ce472dd0..577727664 100644 --- a/Tests/test_imagedraw2.py +++ b/Tests/test_imagedraw2.py @@ -1,8 +1,9 @@ import os.path +import unittest from PIL import Image, ImageDraw2, features -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper BLACK = (0, 0, 0) WHITE = (255, 255, 255) diff --git a/Tests/test_imageenhance.py b/Tests/test_imageenhance.py index b2235853a..d0d994eee 100644 --- a/Tests/test_imageenhance.py +++ b/Tests/test_imageenhance.py @@ -35,7 +35,7 @@ class TestImageEnhance(PillowTestCase): self.assert_image_equal( im.getchannel("A"), original.getchannel("A"), - "Diff on %s: %s" % (op, amount), + "Diff on {}: {}".format(op, amount), ) def test_alpha(self): diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index dad408e93..228bbf929 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -1,8 +1,9 @@ +import unittest from io import BytesIO from PIL import EpsImagePlugin, Image, ImageFile -from .helper import PillowTestCase, fromstring, hopper, tostring, unittest +from .helper import PillowTestCase, fromstring, hopper, tostring try: from PIL import _webp diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 6944404c1..5a15eb535 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -1,15 +1,15 @@ -# -*- coding: utf-8 -*- import copy import distutils.version import os import re import shutil import sys +import unittest from io import BytesIO from PIL import Image, ImageDraw, ImageFont, features -from .helper import PillowTestCase, is_pypy, is_win32, unittest +from .helper import PillowTestCase, is_pypy, is_win32 FONT_PATH = "Tests/fonts/FreeMono.ttf" FONT_SIZE = 20 @@ -20,7 +20,7 @@ HAS_FREETYPE = features.check("freetype2") HAS_RAQM = features.check("raqm") -class SimplePatcher(object): +class SimplePatcher: def __init__(self, parent_obj, attr_name, value): self._parent_obj = parent_obj self._attr_name = attr_name @@ -462,12 +462,12 @@ class TestImageFont(PillowTestCase): # issue #2826 font = ImageFont.load_default() with self.assertRaises(UnicodeEncodeError): - font.getsize(u"’") + font.getsize("’") - @unittest.skipIf(sys.version.startswith("2") or is_pypy(), "requires CPython 3.3+") + @unittest.skipIf(is_pypy(), "failing on PyPy") def test_unicode_extended(self): # issue #3777 - text = u"A\u278A\U0001F12B" + text = "A\u278A\U0001F12B" target = "Tests/images/unicode_extended.png" ttf = ImageFont.truetype( diff --git a/Tests/test_imagefont_bitmap.py b/Tests/test_imagefont_bitmap.py index b7be8f723..eed0c70b6 100644 --- a/Tests/test_imagefont_bitmap.py +++ b/Tests/test_imagefont_bitmap.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image, ImageDraw, ImageFont -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase image_font_installed = True try: diff --git a/Tests/test_imagefontctl.py b/Tests/test_imagefontctl.py index 5b88f94cc..71efb897f 100644 --- a/Tests/test_imagefontctl.py +++ b/Tests/test_imagefontctl.py @@ -1,7 +1,8 @@ -# -*- coding: utf-8 -*- +import unittest + from PIL import Image, ImageDraw, ImageFont, features -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase FONT_SIZE = 20 FONT_PATH = "Tests/fonts/DejaVuSans.ttf" diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py index da41b3a12..8d2b94226 100644 --- a/Tests/test_imagemath.py +++ b/Tests/test_imagemath.py @@ -1,5 +1,3 @@ -from __future__ import print_function - from PIL import Image, ImageMath from .helper import PillowTestCase @@ -7,7 +5,7 @@ from .helper import PillowTestCase def pixel(im): if hasattr(im, "im"): - return "%s %r" % (im.mode, im.getpixel((0, 0))) + return "{} {!r}".format(im.mode, im.getpixel((0, 0))) else: if isinstance(im, int): return int(im) # hack to deal with booleans diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index 2cdbbe02f..d0fd73689 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -11,7 +11,7 @@ except ImportError: class TestImageOps(PillowTestCase): - class Deformer(object): + class Deformer: def getmesh(self, im): x, y = im.size return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))] diff --git a/Tests/test_imageops_usm.py b/Tests/test_imageops_usm.py index 4ed8a83a7..71e858681 100644 --- a/Tests/test_imageops_usm.py +++ b/Tests/test_imageops_usm.py @@ -5,7 +5,7 @@ from .helper import PillowTestCase class TestImageOpsUsm(PillowTestCase): def setUp(self): - super(TestImageOpsUsm, self).setUp() + super().setUp() self.im = Image.open("Tests/images/hopper.ppm") self.addCleanup(self.im.close) self.snakes = Image.open("Tests/images/color_snakes.png") diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py index ed65d47c1..35c78cd3b 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -2,7 +2,6 @@ import array import struct from PIL import Image, ImagePath -from PIL._util import py3 from .helper import PillowTestCase @@ -75,10 +74,7 @@ class TestImagePath(PillowTestCase): # This fails due to the invalid malloc above, # and segfaults for i in range(200000): - if py3: - x[i] = b"0" * 16 - else: - x[i] = "0" * 16 + x[i] = b"0" * 16 class evil: diff --git a/Tests/test_imageqt.py b/Tests/test_imageqt.py index 5cf14adda..f69a21d2a 100644 --- a/Tests/test_imageqt.py +++ b/Tests/test_imageqt.py @@ -15,7 +15,7 @@ else: test_case.skipTest("Qt bindings are not installed") -class PillowQtTestCase(object): +class PillowQtTestCase: def setUp(self): skip_if_qt_is_not_installed(self) diff --git a/Tests/test_imageshow.py b/Tests/test_imageshow.py index 225c8a6a9..858714e57 100644 --- a/Tests/test_imageshow.py +++ b/Tests/test_imageshow.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image, ImageShow -from .helper import PillowTestCase, hopper, is_win32, on_ci, on_github_actions, unittest +from .helper import PillowTestCase, hopper, is_win32, on_ci, on_github_actions class TestImageShow(PillowTestCase): diff --git a/Tests/test_imagetk.py b/Tests/test_imagetk.py index c397c84be..048efd639 100644 --- a/Tests/test_imagetk.py +++ b/Tests/test_imagetk.py @@ -1,15 +1,14 @@ -from PIL import Image -from PIL._util import py3 +import unittest -from .helper import PillowTestCase, hopper, unittest +from PIL import Image + +from .helper import PillowTestCase, hopper try: from PIL import ImageTk - if py3: - import tkinter as tk - else: - import Tkinter as tk + import tkinter as tk + dir(ImageTk) HAS_TK = True except (OSError, ImportError): diff --git a/Tests/test_imagewin.py b/Tests/test_imagewin.py index 2b2034187..1cd8c674e 100644 --- a/Tests/test_imagewin.py +++ b/Tests/test_imagewin.py @@ -1,6 +1,8 @@ +import unittest + from PIL import ImageWin -from .helper import PillowTestCase, hopper, is_win32, unittest +from .helper import PillowTestCase, hopper, is_win32 class TestImageWin(PillowTestCase): diff --git a/Tests/test_lib_image.py b/Tests/test_lib_image.py index 68e72bc4e..240783960 100644 --- a/Tests/test_lib_image.py +++ b/Tests/test_lib_image.py @@ -1,6 +1,8 @@ +import unittest + from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase class TestLibImage(PillowTestCase): diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index 6178184bc..45958d2eb 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -18,7 +18,7 @@ class TestLibPack(PillowTestCase): if isinstance(data, int): data_len = data * len(pixels) - data = bytes(bytearray(range(1, data_len + 1))) + data = bytes(range(1, data_len + 1)) self.assertEqual(data, im.tobytes("raw", rawmode)) @@ -226,7 +226,7 @@ class TestLibUnpack(PillowTestCase): """ if isinstance(data, int): data_len = data * len(pixels) - data = bytes(bytearray(range(1, data_len + 1))) + data = bytes(range(1, data_len + 1)) im = Image.frombytes(mode, (len(pixels), 1), data, "raw", rawmode, 0, 1) diff --git a/Tests/test_locale.py b/Tests/test_locale.py index e4b2806e3..0b1f330ac 100644 --- a/Tests/test_locale.py +++ b/Tests/test_locale.py @@ -1,10 +1,9 @@ -from __future__ import print_function - import locale +import unittest from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase # ref https://github.com/python-pillow/Pillow/issues/272 # on windows, in polish locale: diff --git a/Tests/test_main.py b/Tests/test_main.py index 56e3ccadd..4f52149b6 100644 --- a/Tests/test_main.py +++ b/Tests/test_main.py @@ -1,11 +1,10 @@ -from __future__ import unicode_literals - import os import subprocess import sys +import unittest from unittest import TestCase -from .helper import is_pypy, is_win32, on_github_actions, unittest +from .helper import is_pypy, is_win32, on_github_actions class TestMain(TestCase): diff --git a/Tests/test_map.py b/Tests/test_map.py index 25e24e2fb..bdc3a7e2c 100644 --- a/Tests/test_map.py +++ b/Tests/test_map.py @@ -1,8 +1,9 @@ import sys +import unittest from PIL import Image -from .helper import PillowTestCase, is_win32, unittest +from .helper import PillowTestCase, is_win32 try: import numpy diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index 649148699..fcd45b3c1 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -20,7 +20,11 @@ class TestModeI16(PillowTestCase): self.assertEqual( p1, p2, - ("got %r from mode %s at %s, expected %r" % (p1, im1.mode, xy, p2)), + ( + "got {!r} from mode {} at {}, expected {!r}".format( + p1, im1.mode, xy, p2 + ) + ), ) def test_basic(self): diff --git a/Tests/test_numpy.py b/Tests/test_numpy.py index 872ecdbb6..7de5c3bbd 100644 --- a/Tests/test_numpy.py +++ b/Tests/test_numpy.py @@ -1,8 +1,8 @@ -from __future__ import print_function +import unittest from PIL import Image -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper try: import numpy diff --git a/Tests/test_pdfparser.py b/Tests/test_pdfparser.py index 0d4923480..d599c8264 100644 --- a/Tests/test_pdfparser.py +++ b/Tests/test_pdfparser.py @@ -22,7 +22,7 @@ class TestPdfParser(PillowTestCase): self.assertEqual(encode_text("abc"), b"\xFE\xFF\x00a\x00b\x00c") self.assertEqual(decode_text(b"\xFE\xFF\x00a\x00b\x00c"), "abc") self.assertEqual(decode_text(b"abc"), "abc") - self.assertEqual(decode_text(b"\x1B a \x1C"), u"\u02D9 a \u02DD") + self.assertEqual(decode_text(b"\x1B a \x1C"), "\u02D9 a \u02DD") def test_indirect_refs(self): self.assertEqual(IndirectReference(1, 2), IndirectReference(1, 2)) diff --git a/Tests/test_psdraw.py b/Tests/test_psdraw.py index 561df4ee6..0ef9acb06 100644 --- a/Tests/test_psdraw.py +++ b/Tests/test_psdraw.py @@ -1,5 +1,6 @@ import os import sys +from io import StringIO from PIL import Image, PSDraw @@ -47,10 +48,6 @@ class TestPsDraw(PillowTestCase): def test_stdout(self): # Temporarily redirect stdout - try: - from cStringIO import StringIO - except ImportError: - from io import StringIO old_stdout = sys.stdout sys.stdout = mystdout = StringIO() diff --git a/Tests/test_pyroma.py b/Tests/test_pyroma.py index 3455a502b..accad5451 100644 --- a/Tests/test_pyroma.py +++ b/Tests/test_pyroma.py @@ -1,6 +1,8 @@ +import unittest + from PIL import __version__ -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase try: import pyroma diff --git a/Tests/test_qt_image_toqimage.py b/Tests/test_qt_image_toqimage.py index 5115c1862..39d60d197 100644 --- a/Tests/test_qt_image_toqimage.py +++ b/Tests/test_qt_image_toqimage.py @@ -57,7 +57,7 @@ if ImageQt.qt_is_installed: class Example(QWidget): def __init__(self): - super(Example, self).__init__() + super().__init__() img = hopper().resize((1000, 1000)) diff --git a/Tests/test_util.py b/Tests/test_util.py index 5ec21a77c..6a111b5b9 100644 --- a/Tests/test_util.py +++ b/Tests/test_util.py @@ -1,29 +1,11 @@ +import unittest + from PIL import _util -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase class TestUtil(PillowTestCase): - def test_is_string_type(self): - # Arrange - color = "red" - - # Act - it_is = _util.isStringType(color) - - # Assert - self.assertTrue(it_is) - - def test_is_not_string_type(self): - # Arrange - color = (255, 0, 0) - - # Act - it_is_not = _util.isStringType(color) - - # Assert - self.assertFalse(it_is_not) - def test_is_path(self): # Arrange fp = "filename.ext" diff --git a/Tests/test_webp_leaks.py b/Tests/test_webp_leaks.py index 93a6c2db0..713fc161e 100644 --- a/Tests/test_webp_leaks.py +++ b/Tests/test_webp_leaks.py @@ -1,8 +1,9 @@ +import unittest from io import BytesIO from PIL import Image, features -from .helper import PillowLeakTestCase, unittest +from .helper import PillowLeakTestCase test_file = "Tests/images/hopper.webp" diff --git a/Tests/threaded_save.py b/Tests/threaded_save.py index 11eb86779..d47c2cf99 100644 --- a/Tests/threaded_save.py +++ b/Tests/threaded_save.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import io import queue import sys diff --git a/Tests/versions.py b/Tests/versions.py index 1ac226c9d..d6433b063 100644 --- a/Tests/versions.py +++ b/Tests/versions.py @@ -1,5 +1,3 @@ -from __future__ import print_function - from PIL import Image diff --git a/depends/alpine_Dockerfile b/depends/alpine_Dockerfile deleted file mode 100644 index 69bdf84f6..000000000 --- a/depends/alpine_Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -# This is a sample Dockerfile to build Pillow on Alpine Linux -# with all/most of the dependencies working. -# -# Tcl/Tk isn't detecting -# Freetype has different metrics so tests are failing. -# sudo and bash are required for the webp build script. - -FROM alpine -USER root - -RUN apk --no-cache add python \ - build-base \ - python-dev \ - py-pip \ - # Pillow dependencies - jpeg-dev \ - zlib-dev \ - freetype-dev \ - lcms2-dev \ - openjpeg-dev \ - tiff-dev \ - tk-dev \ - tcl-dev - -# install from pip, without webp -#RUN LIBRARY_PATH=/lib:/usr/lib /bin/sh -c "pip install Pillow" - -# install from git, run tests, including webp -RUN apk --no-cache add git \ - bash \ - sudo - -RUN git clone https://github.com/python-pillow/Pillow.git /Pillow -RUN pip install virtualenv && virtualenv /vpy && source /vpy/bin/activate && pip install nose - -RUN echo "#!/bin/bash" >> /test && \ - echo "source /vpy/bin/activate && cd /Pillow " >> test && \ - echo "pushd depends && ./install_webp.sh && ./install_imagequant.sh && popd" >> test && \ - echo "LIBRARY_PATH=/lib:/usr/lib make install && make test" >> test - -RUN chmod +x /test - -CMD ["/test"] diff --git a/depends/debian_8.2.sh b/depends/debian_8.2.sh deleted file mode 100755 index c4f72bf8e..000000000 --- a/depends/debian_8.2.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# -# Installs all of the dependencies for Pillow for Debian 8.2 -# for both system Pythons 2.7 and 3.4 -# -# Also works for Raspbian Jessie -# - -sudo apt-get -y install python-dev python-setuptools \ - python3-dev python-virtualenv cmake -sudo apt-get -y install libtiff5-dev libjpeg62-turbo-dev zlib1g-dev \ - libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev \ - python-tk python3-tk libharfbuzz-dev libfribidi-dev - -./install_openjpeg.sh -./install_imagequant.sh -./install_raqm.sh diff --git a/depends/fedora_23.sh b/depends/fedora_23.sh deleted file mode 100755 index 5bdcf7f17..000000000 --- a/depends/fedora_23.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# -# Installs all of the dependencies for Pillow for Fedora 23 -# for both system Pythons 2.7 and 3.4 -# -# note that Fedora does ship packages for Pillow as python-pillow - -# this is a workaround for -# "gcc: error: /usr/lib/rpm/redhat/redhat-hardened-cc1: No such file or directory" -# errors when compiling. -sudo dnf install redhat-rpm-config - -sudo dnf install python-devel python3-devel python-virtualenv make gcc - -sudo dnf install libtiff-devel libjpeg-devel zlib-devel freetype-devel \ - lcms2-devel libwebp-devel openjpeg2-devel tkinter python3-tkinter \ - tcl-devel tk-devel harfbuzz-devel fribidi-devel libraqm-devel \ No newline at end of file diff --git a/depends/freebsd_10.sh b/depends/freebsd_10.sh deleted file mode 100755 index 36d9c1069..000000000 --- a/depends/freebsd_10.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -# -# Installs all of the dependencies for Pillow for Freebsd 10.x -# for both system Pythons 2.7 and 3.4 -# -sudo pkg install python2 python3 py27-pip py27-virtualenv wget cmake - -# Openjpeg fails badly using the openjpeg package. -# I can't find a python3.4 version of tkinter -sudo pkg install jpeg-turbo tiff webp lcms2 freetype2 harfbuzz fribidi py27-tkinter - -./install_raqm_cmake.sh diff --git a/depends/ubuntu_12.04.sh b/depends/ubuntu_12.04.sh deleted file mode 100755 index 9bfae43b0..000000000 --- a/depends/ubuntu_12.04.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# -# Installs all of the dependencies for Pillow for Ubuntu 12.04 -# for both system Pythons 2.7 and 3.2 -# - -sudo apt-get -y install python-dev python-setuptools \ - python3-dev python-virtualenv cmake -sudo apt-get install libtiff4-dev libjpeg8-dev zlib1g-dev \ - libfreetype6-dev liblcms2-dev tcl8.5-dev \ - tk8.5-dev python-tk python3-tk - - -./install_openjpeg.sh -./install_webp.sh -./install_imagequant.sh diff --git a/depends/ubuntu_14.04.sh b/depends/ubuntu_14.04.sh deleted file mode 100755 index f7d28fba7..000000000 --- a/depends/ubuntu_14.04.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -# -# Installs all of the dependencies for Pillow for Ubuntu 14.04 -# for both system Pythons 2.7 and 3.4 -# -sudo apt-get update -sudo apt-get -y install python-dev python-setuptools \ - python3-dev python-virtualenv cmake -sudo apt-get -y install libtiff5-dev libjpeg8-dev zlib1g-dev \ - libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev \ - python-tk python3-tk libharfbuzz-dev libfribidi-dev - -./install_openjpeg.sh -./install_imagequant.sh -./install_raqm.sh diff --git a/docs/conf.py b/docs/conf.py index a9ca91de7..66effdfb2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Pillow (PIL Fork) documentation build configuration file, created by # sphinx-quickstart on Sat Apr 4 07:54:11 2015. @@ -42,9 +41,9 @@ source_suffix = ".rst" master_doc = "index" # General information about the project. -project = u"Pillow (PIL Fork)" -copyright = u"1995-2011 Fredrik Lundh, 2010-2019 Alex Clark and Contributors" -author = u"Fredrik Lundh, Alex Clark and Contributors" +project = "Pillow (PIL Fork)" +copyright = "1995-2011 Fredrik Lundh, 2010-2019 Alex Clark and Contributors" +author = "Fredrik Lundh, Alex Clark and Contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -220,8 +219,8 @@ latex_documents = [ ( master_doc, "PillowPILFork.tex", - u"Pillow (PIL Fork) Documentation", - u"Alex Clark", + "Pillow (PIL Fork) Documentation", + "Alex Clark", "manual", ) ] @@ -252,7 +251,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, "pillowpilfork", u"Pillow (PIL Fork) Documentation", [author], 1) + (master_doc, "pillowpilfork", "Pillow (PIL Fork) Documentation", [author], 1) ] # If true, show URL addresses after external links. @@ -268,7 +267,7 @@ texinfo_documents = [ ( master_doc, "PillowPILFork", - u"Pillow (PIL Fork) Documentation", + "Pillow (PIL Fork) Documentation", author, "PillowPILFork", "Pillow is the friendly PIL fork by Alex Clark and Contributors.", diff --git a/docs/deprecations.rst b/docs/deprecations.rst index 144661820..a9b534dca 100644 --- a/docs/deprecations.rst +++ b/docs/deprecations.rst @@ -22,31 +22,6 @@ Python 2.7 reaches end-of-life on 2020-01-01. Pillow 7.0.0 will be released on 2020-01-01 and will drop support for Python 2.7, making Pillow 6.x the last series to support Python 2. -PIL.*ImagePlugin.__version__ attributes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 6.0.0 - -The version constants of individual plugins have been deprecated and will be removed in -a future version. Use ``PIL.__version__`` instead. - -=============================== ================================= ================================== -Deprecated Deprecated Deprecated -=============================== ================================= ================================== -``BmpImagePlugin.__version__`` ``Jpeg2KImagePlugin.__version__`` ``PngImagePlugin.__version__`` -``CurImagePlugin.__version__`` ``JpegImagePlugin.__version__`` ``PpmImagePlugin.__version__`` -``DcxImagePlugin.__version__`` ``McIdasImagePlugin.__version__`` ``PsdImagePlugin.__version__`` -``EpsImagePlugin.__version__`` ``MicImagePlugin.__version__`` ``SgiImagePlugin.__version__`` -``FliImagePlugin.__version__`` ``MpegImagePlugin.__version__`` ``SunImagePlugin.__version__`` -``FpxImagePlugin.__version__`` ``MpoImagePlugin.__version__`` ``TgaImagePlugin.__version__`` -``GdImageFile.__version__`` ``MspImagePlugin.__version__`` ``TiffImagePlugin.__version__`` -``GifImagePlugin.__version__`` ``PalmImagePlugin.__version__`` ``WmfImagePlugin.__version__`` -``IcoImagePlugin.__version__`` ``PcdImagePlugin.__version__`` ``XbmImagePlugin.__version__`` -``ImImagePlugin.__version__`` ``PcxImagePlugin.__version__`` ``XpmImagePlugin.__version__`` -``ImtImagePlugin.__version__`` ``PdfImagePlugin.__version__`` ``XVThumbImagePlugin.__version__`` -``IptcImagePlugin.__version__`` ``PixarImagePlugin.__version__`` -=============================== ================================= ================================== - ImageCms.CmsProfile attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -103,6 +78,31 @@ PILLOW_VERSION constant ``PILLOW_VERSION`` has been removed. Use ``__version__`` instead. +PIL.*ImagePlugin.__version__ attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*Removed in version 7.0.0.* + +The version constants of individual plugins have been removed. Use ``PIL.__version__`` +instead. + +=============================== ================================= ================================== +Removed Removed Removed +=============================== ================================= ================================== +``BmpImagePlugin.__version__`` ``Jpeg2KImagePlugin.__version__`` ``PngImagePlugin.__version__`` +``CurImagePlugin.__version__`` ``JpegImagePlugin.__version__`` ``PpmImagePlugin.__version__`` +``DcxImagePlugin.__version__`` ``McIdasImagePlugin.__version__`` ``PsdImagePlugin.__version__`` +``EpsImagePlugin.__version__`` ``MicImagePlugin.__version__`` ``SgiImagePlugin.__version__`` +``FliImagePlugin.__version__`` ``MpegImagePlugin.__version__`` ``SunImagePlugin.__version__`` +``FpxImagePlugin.__version__`` ``MpoImagePlugin.__version__`` ``TgaImagePlugin.__version__`` +``GdImageFile.__version__`` ``MspImagePlugin.__version__`` ``TiffImagePlugin.__version__`` +``GifImagePlugin.__version__`` ``PalmImagePlugin.__version__`` ``WmfImagePlugin.__version__`` +``IcoImagePlugin.__version__`` ``PcdImagePlugin.__version__`` ``XbmImagePlugin.__version__`` +``ImImagePlugin.__version__`` ``PcxImagePlugin.__version__`` ``XpmImagePlugin.__version__`` +``ImtImagePlugin.__version__`` ``PdfImagePlugin.__version__`` ``XVThumbImagePlugin.__version__`` +``IptcImagePlugin.__version__`` ``PixarImagePlugin.__version__`` +=============================== ================================= ================================== + PyQt4 and PySide ~~~~~~~~~~~~~~~~ diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index be493a316..45f63f164 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -212,10 +212,10 @@ class DdsImageFile(ImageFile.ImageFile): def _open(self): magic, header_size = struct.unpack(">> from __future__ import print_function >>> print(im.format, im.size, im.mode) PPM (512, 512) RGB @@ -67,7 +66,6 @@ Convert files to JPEG :: - from __future__ import print_function import os, sys from PIL import Image @@ -89,7 +87,6 @@ Create JPEG thumbnails :: - from __future__ import print_function import os, sys from PIL import Image @@ -120,7 +117,6 @@ Identify Image Files :: - from __future__ import print_function import sys from PIL import Image diff --git a/docs/installation.rst b/docs/installation.rst index 4ccc47ae4..5ace862f0 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -125,10 +125,9 @@ External Libraries .. note:: - There are scripts to install the dependencies for some operating - systems included in the ``depends`` directory. Also see the - Dockerfiles in our `docker images repo - `_. + There are Dockerfiles in our `Docker images repo + `_ to install the + dependencies for some operating systems. Many of Pillow's features require external libraries: diff --git a/docs/releasenotes/7.0.0.rst b/docs/releasenotes/7.0.0.rst index 48660b506..386a26757 100644 --- a/docs/releasenotes/7.0.0.rst +++ b/docs/releasenotes/7.0.0.rst @@ -9,6 +9,29 @@ PILLOW_VERSION constant ``PILLOW_VERSION`` has been removed. Use ``__version__`` instead. +PIL.*ImagePlugin.__version__ attributes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The version constants of individual plugins have been removed. Use ``PIL.__version__`` +instead. + +=============================== ================================= ================================== +Removed Removed Removed +=============================== ================================= ================================== +``BmpImagePlugin.__version__`` ``Jpeg2KImagePlugin.__version__`` ``PngImagePlugin.__version__`` +``CurImagePlugin.__version__`` ``JpegImagePlugin.__version__`` ``PpmImagePlugin.__version__`` +``DcxImagePlugin.__version__`` ``McIdasImagePlugin.__version__`` ``PsdImagePlugin.__version__`` +``EpsImagePlugin.__version__`` ``MicImagePlugin.__version__`` ``SgiImagePlugin.__version__`` +``FliImagePlugin.__version__`` ``MpegImagePlugin.__version__`` ``SunImagePlugin.__version__`` +``FpxImagePlugin.__version__`` ``MpoImagePlugin.__version__`` ``TgaImagePlugin.__version__`` +``GdImageFile.__version__`` ``MspImagePlugin.__version__`` ``TiffImagePlugin.__version__`` +``GifImagePlugin.__version__`` ``PalmImagePlugin.__version__`` ``WmfImagePlugin.__version__`` +``IcoImagePlugin.__version__`` ``PcdImagePlugin.__version__`` ``XbmImagePlugin.__version__`` +``ImImagePlugin.__version__`` ``PcxImagePlugin.__version__`` ``XpmImagePlugin.__version__`` +``ImtImagePlugin.__version__`` ``PdfImagePlugin.__version__`` ``XVThumbImagePlugin.__version__`` +``IptcImagePlugin.__version__`` ``PixarImagePlugin.__version__`` +=============================== ================================= ================================== + PyQt4 and PySide ^^^^^^^^^^^^^^^^ @@ -40,11 +63,11 @@ TODO API Additions ============= -TODO -^^^^ - -TODO +Custom unidentified image error +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Pillow will now throw a custom ``UnidentifiedImageError`` when an image cannot be +identified. For backwards compatibility, this will inherit from ``IOError``. Other Changes ============= diff --git a/mp_compile.py b/mp_compile.py deleted file mode 100644 index ec73e927e..000000000 --- a/mp_compile.py +++ /dev/null @@ -1,93 +0,0 @@ -# A monkey patch of the base distutils.ccompiler to use parallel builds -# Tested on 2.7, looks to be identical to 3.3. -# Only applied on Python 2.7 because otherwise, it conflicts with Python's -# own newly-added support for parallel builds. - -from __future__ import print_function - -import os -import sys -from distutils.ccompiler import CCompiler -from multiprocessing import Pool, cpu_count - -try: - MAX_PROCS = int(os.environ.get("MAX_CONCURRENCY", min(4, cpu_count()))) -except NotImplementedError: - MAX_PROCS = None - - -# hideous monkeypatching. but. but. but. -def _mp_compile_one(tp): - (self, obj, build, cc_args, extra_postargs, pp_opts) = tp - try: - src, ext = build[obj] - except KeyError: - return - self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) - return - - -def _mp_compile( - self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - depends=None, -): - """Compile one or more source files. - - see distutils.ccompiler.CCompiler.compile for comments. - """ - # A concrete compiler class can either override this method - # entirely or implement _compile(). - - macros, objects, extra_postargs, pp_opts, build = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs - ) - cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) - - pool = Pool(MAX_PROCS) - try: - print("Building using %d processes" % pool._processes) - except Exception: - pass - arr = [(self, obj, build, cc_args, extra_postargs, pp_opts) for obj in objects] - pool.map_async(_mp_compile_one, arr) - pool.close() - pool.join() - # Return *all* object filenames, not just the ones we just built. - return objects - - -def install(): - - fl_win = sys.platform.startswith("win") - fl_cygwin = sys.platform.startswith("cygwin") - - if fl_win or fl_cygwin: - # Windows barfs on multiprocessing installs - print("Single threaded build for Windows") - return - - if MAX_PROCS != 1: - # explicitly don't enable if environment says 1 processor - try: - # bug, only enable if we can make a Pool. see issue #790 and - # https://stackoverflow.com/questions/6033599/oserror-38-errno-38-with-multiprocessing - Pool(2) - CCompiler.compile = _mp_compile - except Exception as msg: - print("Exception installing mp_compile, proceeding without: %s" % msg) - else: - print( - "Single threaded build, not installing mp_compile: %s processes" % MAX_PROCS - ) - - -# We monkeypatch Python 2.7 -if sys.version_info.major < 3: - install() diff --git a/selftest.py b/selftest.py index a8937b77e..ea52256f7 100755 --- a/selftest.py +++ b/selftest.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # minimal sanity check -from __future__ import print_function import sys diff --git a/setup.py b/setup.py index 339132ff3..f5024990f 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,6 @@ # Final rating: 10/10 # Your cheese is so fresh most people think it's a cream: Mascarpone # ------------------------------ -from __future__ import print_function import os import re @@ -20,10 +19,6 @@ from distutils.command.build_ext import build_ext from setuptools import Extension, setup -# monkey patch import hook. Even though flake8 says it's not used, it is. -# comment this out to disable multi threaded builds. -import mp_compile - def get_version(): version_file = "src/PIL/_version.py" @@ -189,10 +184,10 @@ def _find_library_dirs_ldconfig(): expr = r".* => (.*)" env = {} - null = open(os.devnull, "wb") try: - with null: - p = subprocess.Popen(args, stderr=null, stdout=subprocess.PIPE, env=env) + p = subprocess.Popen( + args, stderr=subprocess.DEVNULL, stdout=subprocess.PIPE, env=env + ) except OSError: # E.g. command not found return [] [data, _] = p.communicate() @@ -305,8 +300,7 @@ class pil_build_ext(build_ext): return getattr(self, feat) is None def __iter__(self): - for x in self.features: - yield x + yield from self.features feature = feature() @@ -334,12 +328,15 @@ class pil_build_ext(build_ext): if self.debug: global DEBUG DEBUG = True - if sys.version_info.major >= 3 and not self.parallel: - # For Python 2.7, we monkeypatch distutils to have parallel - # builds. If --parallel (or -j) wasn't specified, we want to - # reproduce the same behavior as before, that is, auto-detect the - # number of jobs. - self.parallel = mp_compile.MAX_PROCS + if not self.parallel: + # If --parallel (or -j) wasn't specified, we want to reproduce the same + # behavior as before, that is, auto-detect the number of jobs. + try: + self.parallel = int( + os.environ.get("MAX_CONCURRENCY", min(4, os.cpu_count())) + ) + except TypeError: + self.parallel = None for x in self.feature: if getattr(self, "disable_%s" % x): setattr(self.feature, x, False) @@ -347,7 +344,7 @@ class pil_build_ext(build_ext): _dbg("Disabling %s", x) if getattr(self, "enable_%s" % x): raise ValueError( - "Conflicting options: --enable-%s and --disable-%s" % (x, x) + "Conflicting options: --enable-{} and --disable-{}".format(x, x) ) if getattr(self, "enable_%s" % x): _dbg("Requiring %s", x) @@ -719,7 +716,7 @@ class pil_build_ext(build_ext): defs.append(("HAVE_LIBTIFF", None)) if sys.platform == "win32": libs.extend(["kernel32", "user32", "gdi32"]) - if struct.unpack("h", "\0\1".encode("ascii"))[0] == 1: + if struct.unpack("h", b"\0\1")[0] == 1: defs.append(("WORDS_BIGENDIAN", None)) if sys.platform == "win32" and not (PLATFORM_PYPY or PLATFORM_MINGW): @@ -800,7 +797,7 @@ class pil_build_ext(build_ext): print("-" * 68) print("version Pillow %s" % PILLOW_VERSION) v = sys.version.split("[") - print("platform %s %s" % (sys.platform, v[0].strip())) + print("platform {} {}".format(sys.platform, v[0].strip())) for v in v[1:]: print(" [%s" % v.strip()) print("-" * 68) @@ -823,7 +820,7 @@ class pil_build_ext(build_ext): version = "" if len(option) >= 3 and option[2]: version = " (%s)" % option[2] - print("--- %s support available%s" % (option[1], version)) + print("--- {} support available{}".format(option[1], version)) else: print("*** %s support not available" % option[1]) all = 0 @@ -868,13 +865,12 @@ try: classifiers=[ "Development Status :: 6 - Mature", "License :: OSI Approved :: Historical Permission Notice and Disclaimer (HPND)", # noqa: E501 - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Multimedia :: Graphics", @@ -883,7 +879,7 @@ try: "Topic :: Multimedia :: Graphics :: Graphics Conversion", "Topic :: Multimedia :: Graphics :: Viewers", ], - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", + python_requires=">=3.5", cmdclass={"build_ext": pil_build_ext}, ext_modules=[Extension("PIL._imaging", ["_imaging.c"])], include_package_data=True, diff --git a/src/PIL/BdfFontFile.py b/src/PIL/BdfFontFile.py index 53a890fb6..7a485cf80 100644 --- a/src/PIL/BdfFontFile.py +++ b/src/PIL/BdfFontFile.py @@ -17,7 +17,6 @@ # See the README file for information on usage and redistribution. # -from __future__ import print_function from . import FontFile, Image diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index dd1745158..5ccba37db 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -283,7 +283,7 @@ class _BLPBaseDecoder(ImageFile.PyDecoder): self._read_blp_header() self._load() except struct.error: - raise IOError("Truncated Blp file") + raise OSError("Truncated Blp file") return 0, 0 def _read_palette(self): diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 8426e2497..cdef77ced 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -27,10 +27,6 @@ from . import Image, ImageFile, ImagePalette from ._binary import i8, i16le as i16, i32le as i32, o8, o16le as o16, o32le as o32 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.7" - # # -------------------------------------------------------------------- # Read BMP file @@ -148,7 +144,7 @@ class BmpImageFile(ImageFile.ImageFile): file_info["a_mask"], ) else: - raise IOError("Unsupported BMP header type (%d)" % file_info["header_size"]) + raise OSError("Unsupported BMP header type (%d)" % file_info["header_size"]) # ------------------ Special case : header is reported 40, which # ---------------------- is shorter than real size for bpp >= 16 @@ -163,12 +159,12 @@ class BmpImageFile(ImageFile.ImageFile): # ------------------------------- Check abnormal values for DOS attacks if file_info["width"] * file_info["height"] > 2 ** 31: - raise IOError("Unsupported BMP Size: (%dx%d)" % self.size) + raise OSError("Unsupported BMP Size: (%dx%d)" % self.size) # ---------------------- Check bit depth for unusual unsupported values self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None)) if self.mode is None: - raise IOError("Unsupported BMP pixel depth (%d)" % file_info["bits"]) + raise OSError("Unsupported BMP pixel depth (%d)" % file_info["bits"]) # ---------------- Process BMP with Bitfields compression (not palette) if file_info["compression"] == self.BITFIELDS: @@ -206,21 +202,21 @@ class BmpImageFile(ImageFile.ImageFile): ): raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])] else: - raise IOError("Unsupported BMP bitfields layout") + raise OSError("Unsupported BMP bitfields layout") else: - raise IOError("Unsupported BMP bitfields layout") + raise OSError("Unsupported BMP bitfields layout") elif file_info["compression"] == self.RAW: if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset raw_mode, self.mode = "BGRA", "RGBA" else: - raise IOError("Unsupported BMP compression (%d)" % file_info["compression"]) + raise OSError("Unsupported BMP compression (%d)" % file_info["compression"]) # --------------- Once the header is processed, process the palette/LUT if self.mode == "P": # Paletted for 1, 4 and 8 bit images # ---------------------------------------------------- 1-bit images if not (0 < file_info["colors"] <= 65536): - raise IOError("Unsupported BMP Palette size (%d)" % file_info["colors"]) + raise OSError("Unsupported BMP Palette size (%d)" % file_info["colors"]) else: padding = file_info["palette_padding"] palette = read(padding * file_info["colors"]) @@ -309,7 +305,7 @@ def _save(im, fp, filename, bitmap_header=True): try: rawmode, bits, colors = SAVE[im.mode] except KeyError: - raise IOError("cannot write mode %s as BMP" % im.mode) + raise OSError("cannot write mode %s as BMP" % im.mode) info = im.encoderinfo diff --git a/src/PIL/BufrStubImagePlugin.py b/src/PIL/BufrStubImagePlugin.py index 56cac3bb1..48f21e1b3 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -60,7 +60,7 @@ class BufrStubImageFile(ImageFile.StubImageFile): def _save(im, fp, filename): if _handler is None or not hasattr("_handler", "save"): - raise IOError("BUFR save handler not installed") + raise OSError("BUFR save handler not installed") _handler.save(im, fp, filename) diff --git a/src/PIL/ContainerIO.py b/src/PIL/ContainerIO.py index 3cf9d82d2..9727601ab 100644 --- a/src/PIL/ContainerIO.py +++ b/src/PIL/ContainerIO.py @@ -21,7 +21,7 @@ import io -class ContainerIO(object): +class ContainerIO: def __init__(self, file, offset, length): """ Create file object. diff --git a/src/PIL/CurImagePlugin.py b/src/PIL/CurImagePlugin.py index 9e2d8c96f..3a1b6d2e5 100644 --- a/src/PIL/CurImagePlugin.py +++ b/src/PIL/CurImagePlugin.py @@ -15,16 +15,9 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - from . import BmpImagePlugin, Image from ._binary import i8, i16le as i16, i32le as i32 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - # # -------------------------------------------------------------------- diff --git a/src/PIL/DcxImagePlugin.py b/src/PIL/DcxImagePlugin.py index 57c321417..7d2aff325 100644 --- a/src/PIL/DcxImagePlugin.py +++ b/src/PIL/DcxImagePlugin.py @@ -25,10 +25,6 @@ from . import Image from ._binary import i32le as i32 from .PcxImagePlugin import PcxImageFile -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" - MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then? diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 28a582ec4..9ba6e0ff8 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -106,10 +106,10 @@ class DdsImageFile(ImageFile.ImageFile): def _open(self): magic, header_size = struct.unpack(" 2: - fp = io.TextIOWrapper(fp, encoding="latin-1") - wrapped_fp = True + fp = io.TextIOWrapper(fp, encoding="latin-1") + wrapped_fp = True try: if eps: diff --git a/src/PIL/FitsStubImagePlugin.py b/src/PIL/FitsStubImagePlugin.py index 7e6d35ee5..c2ce8651c 100644 --- a/src/PIL/FitsStubImagePlugin.py +++ b/src/PIL/FitsStubImagePlugin.py @@ -63,7 +63,7 @@ class FITSStubImageFile(ImageFile.StubImageFile): def _save(im, fp, filename): if _handler is None or not hasattr("_handler", "save"): - raise IOError("FITS save handler not installed") + raise OSError("FITS save handler not installed") _handler.save(im, fp, filename) diff --git a/src/PIL/FliImagePlugin.py b/src/PIL/FliImagePlugin.py index 82015e2fc..9bf7d74d6 100644 --- a/src/PIL/FliImagePlugin.py +++ b/src/PIL/FliImagePlugin.py @@ -19,11 +19,6 @@ from . import Image, ImageFile, ImagePalette from ._binary import i8, i16le as i16, i32le as i32, o8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" - - # # decoder diff --git a/src/PIL/FontFile.py b/src/PIL/FontFile.py index e57c2f3fd..979a1e33c 100644 --- a/src/PIL/FontFile.py +++ b/src/PIL/FontFile.py @@ -14,7 +14,6 @@ # See the README file for information on usage and redistribution. # -from __future__ import print_function import os @@ -35,7 +34,7 @@ def puti16(fp, values): # Base class for raster font file handlers. -class FontFile(object): +class FontFile: bitmap = None diff --git a/src/PIL/FpxImagePlugin.py b/src/PIL/FpxImagePlugin.py index 15ebe0e3b..3938f0f09 100644 --- a/src/PIL/FpxImagePlugin.py +++ b/src/PIL/FpxImagePlugin.py @@ -14,18 +14,11 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - import olefile from . import Image, ImageFile from ._binary import i8, i32le as i32 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - # we map from colour field tuples to (mode, rawmode) descriptors MODES = { # opacity @@ -66,7 +59,7 @@ class FpxImageFile(ImageFile.ImageFile): try: self.ole = olefile.OleFileIO(self.fp) - except IOError: + except OSError: raise SyntaxError("not an FPX file; invalid OLE file") if self.ole.root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B": @@ -145,7 +138,7 @@ class FpxImageFile(ImageFile.ImageFile): length = i32(s, 32) if size != self.size: - raise IOError("subimage mismatch") + raise OSError("subimage mismatch") # get tile descriptors fp.seek(28 + offset) @@ -218,7 +211,7 @@ class FpxImageFile(ImageFile.ImageFile): self.tile_prefix = self.jpeg[jpeg_tables] else: - raise IOError("unknown/invalid compression") + raise OSError("unknown/invalid compression") x = x + xtile if x >= xsize: diff --git a/src/PIL/GbrImagePlugin.py b/src/PIL/GbrImagePlugin.py index 2de56aadf..292de435c 100644 --- a/src/PIL/GbrImagePlugin.py +++ b/src/PIL/GbrImagePlugin.py @@ -14,7 +14,7 @@ # See the README file for information on usage and redistribution. # # -# See https://github.com/GNOME/gimp/blob/master/devel-docs/gbr.txt for +# See https://github.com/GNOME/gimp/blob/mainline/devel-docs/gbr.txt for # format documentation. # # This code Interprets version 1 and 2 .gbr files. diff --git a/src/PIL/GdImageFile.py b/src/PIL/GdImageFile.py index 2d492358c..54c88712c 100644 --- a/src/PIL/GdImageFile.py +++ b/src/PIL/GdImageFile.py @@ -23,14 +23,9 @@ # purposes only. -from . import ImageFile, ImagePalette +from . import ImageFile, ImagePalette, UnidentifiedImageError from ._binary import i8, i16be as i16, i32be as i32 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - - ## # Image plugin for the GD uncompressed format. Note that this format # is not supported by the standard Image.open function. To use @@ -87,4 +82,4 @@ def open(fp, mode="r"): try: return GdImageFile(fp) except SyntaxError: - raise IOError("cannot identify this image file") + raise UnidentifiedImageError("cannot identify this image file") diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index a92c142f0..7717fc707 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -31,11 +31,6 @@ import subprocess from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence from ._binary import i8, i16le as i16, o8, o16le as o16 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.9" - - # -------------------------------------------------------------------- # Identify/read GIF files @@ -623,20 +618,20 @@ def _save_netpbm(im, fp, filename): with open(filename, "wb") as f: if im.mode != "RGB": - with open(os.devnull, "wb") as devnull: - subprocess.check_call(["ppmtogif", tempfile], stdout=f, stderr=devnull) + subprocess.check_call( + ["ppmtogif", tempfile], stdout=f, stderr=subprocess.DEVNULL + ) else: # Pipe ppmquant output into ppmtogif # "ppmquant 256 %s | ppmtogif > %s" % (tempfile, filename) quant_cmd = ["ppmquant", "256", tempfile] togif_cmd = ["ppmtogif"] - with open(os.devnull, "wb") as devnull: - quant_proc = subprocess.Popen( - quant_cmd, stdout=subprocess.PIPE, stderr=devnull - ) - togif_proc = subprocess.Popen( - togif_cmd, stdin=quant_proc.stdout, stdout=f, stderr=devnull - ) + quant_proc = subprocess.Popen( + quant_cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL + ) + togif_proc = subprocess.Popen( + togif_cmd, stdin=quant_proc.stdout, stdout=f, stderr=subprocess.DEVNULL + ) # Allow ppmquant to receive SIGPIPE if ppmtogif exits quant_proc.stdout.close() @@ -853,7 +848,7 @@ def getdata(im, offset=(0, 0), **params): """ - class Collector(object): + class Collector: data = [] def write(self, data): diff --git a/src/PIL/GimpGradientFile.py b/src/PIL/GimpGradientFile.py index f48e7f76e..851e24d62 100644 --- a/src/PIL/GimpGradientFile.py +++ b/src/PIL/GimpGradientFile.py @@ -60,7 +60,7 @@ def sphere_decreasing(middle, pos): SEGMENTS = [linear, curved, sine, sphere_increasing, sphere_decreasing] -class GradientFile(object): +class GradientFile: gradient = None @@ -132,7 +132,7 @@ class GimpGradientFile(GradientFile): cspace = int(s[12]) if cspace != 0: - raise IOError("cannot handle HSV colour space") + raise OSError("cannot handle HSV colour space") gradient.append((x0, x1, xm, rgb0, rgb1, segment)) diff --git a/src/PIL/GimpPaletteFile.py b/src/PIL/GimpPaletteFile.py index 2994bbeab..e3060ab8a 100644 --- a/src/PIL/GimpPaletteFile.py +++ b/src/PIL/GimpPaletteFile.py @@ -22,7 +22,7 @@ from ._binary import o8 # File handler for GIMP's palette format. -class GimpPaletteFile(object): +class GimpPaletteFile: rawmode = "RGB" diff --git a/src/PIL/GribStubImagePlugin.py b/src/PIL/GribStubImagePlugin.py index 8a24a9829..515c272f7 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -61,7 +61,7 @@ class GribStubImageFile(ImageFile.StubImageFile): def _save(im, fp, filename): if _handler is None or not hasattr("_handler", "save"): - raise IOError("GRIB save handler not installed") + raise OSError("GRIB save handler not installed") _handler.save(im, fp, filename) diff --git a/src/PIL/Hdf5StubImagePlugin.py b/src/PIL/Hdf5StubImagePlugin.py index a3ea12f99..362f2d399 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -60,7 +60,7 @@ class HDF5StubImageFile(ImageFile.StubImageFile): def _save(im, fp, filename): if _handler is None or not hasattr("_handler", "save"): - raise IOError("HDF5 save handler not installed") + raise OSError("HDF5 save handler not installed") _handler.save(im, fp, filename) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 9cf7a90cd..18e8403d1 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -129,7 +129,7 @@ def read_png_or_jpeg2000(fobj, start_length, size): raise ValueError("Unsupported icon subimage format") -class IcnsFile(object): +class IcnsFile: SIZES = { (512, 512, 2): [(b"ic10", read_png_or_jpeg2000)], @@ -314,42 +314,40 @@ def _save(im, fp, filename): fp.flush() # create the temporary set of pngs - iconset = tempfile.mkdtemp(".iconset") - provided_images = {im.width: im for im in im.encoderinfo.get("append_images", [])} - last_w = None - second_path = None - for w in [16, 32, 128, 256, 512]: - prefix = "icon_{}x{}".format(w, w) + with tempfile.TemporaryDirectory(".iconset") as iconset: + provided_images = { + im.width: im for im in im.encoderinfo.get("append_images", []) + } + last_w = None + second_path = None + for w in [16, 32, 128, 256, 512]: + prefix = "icon_{}x{}".format(w, w) - first_path = os.path.join(iconset, prefix + ".png") - if last_w == w: - shutil.copyfile(second_path, first_path) - else: - im_w = provided_images.get(w, im.resize((w, w), Image.LANCZOS)) - im_w.save(first_path) + first_path = os.path.join(iconset, prefix + ".png") + if last_w == w: + shutil.copyfile(second_path, first_path) + else: + im_w = provided_images.get(w, im.resize((w, w), Image.LANCZOS)) + im_w.save(first_path) - second_path = os.path.join(iconset, prefix + "@2x.png") - im_w2 = provided_images.get(w * 2, im.resize((w * 2, w * 2), Image.LANCZOS)) - im_w2.save(second_path) - last_w = w * 2 + second_path = os.path.join(iconset, prefix + "@2x.png") + im_w2 = provided_images.get(w * 2, im.resize((w * 2, w * 2), Image.LANCZOS)) + im_w2.save(second_path) + last_w = w * 2 - # iconutil -c icns -o {} {} + # iconutil -c icns -o {} {} - convert_cmd = ["iconutil", "-c", "icns", "-o", filename, iconset] - with open(os.devnull, "wb") as devnull: + convert_cmd = ["iconutil", "-c", "icns", "-o", filename, iconset] convert_proc = subprocess.Popen( - convert_cmd, stdout=subprocess.PIPE, stderr=devnull + convert_cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL ) - convert_proc.stdout.close() + convert_proc.stdout.close() - retcode = convert_proc.wait() + retcode = convert_proc.wait() - # remove the temporary files - shutil.rmtree(iconset) - - if retcode: - raise subprocess.CalledProcessError(retcode, convert_cmd) + if retcode: + raise subprocess.CalledProcessError(retcode, convert_cmd) Image.register_open(IcnsImageFile.format, IcnsImageFile, lambda x: x[:4] == b"icns") diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index 148e604f8..19cb548a6 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -30,10 +30,6 @@ from math import ceil, log from . import BmpImagePlugin, Image, ImageFile, PngImagePlugin from ._binary import i8, i16le as i16, i32le as i32 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - # # -------------------------------------------------------------------- @@ -86,7 +82,7 @@ def _accept(prefix): return prefix[:4] == _MAGIC -class IcoFile(object): +class IcoFile: def __init__(self, buf): """ Parse image from file-like object containing ico file data diff --git a/src/PIL/ImImagePlugin.py b/src/PIL/ImImagePlugin.py index 77127fae6..12c9237f0 100644 --- a/src/PIL/ImImagePlugin.py +++ b/src/PIL/ImImagePlugin.py @@ -31,11 +31,6 @@ import re from . import Image, ImageFile, ImagePalette from ._binary import i8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.7" - - # -------------------------------------------------------------------- # Standard tags diff --git a/src/PIL/Image.py b/src/PIL/Image.py index f50b319d2..30631ef60 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -25,6 +25,7 @@ # import atexit +import builtins import io import logging import math @@ -34,29 +35,15 @@ import struct import sys import tempfile import warnings +from collections.abc import Callable, MutableMapping +from pathlib import Path # VERSION was removed in Pillow 6.0.0. # PILLOW_VERSION was removed in Pillow 7.0.0. # Use __version__ instead. -from . import ImageMode, TiffTags, __version__, _plugins +from . import ImageMode, TiffTags, UnidentifiedImageError, __version__, _plugins from ._binary import i8, i32le -from ._util import deferred_error, isPath, isStringType, py3 - -try: - import builtins -except ImportError: - import __builtin__ - - builtins = __builtin__ - - -try: - # Python 3 - from collections.abc import Callable, MutableMapping -except ImportError: - # Python 2.7 - from collections import Callable, MutableMapping - +from ._util import deferred_error, isPath logger = logging.getLogger(__name__) @@ -101,22 +88,6 @@ except ImportError as v: ) elif str(v).startswith("The _imaging extension"): warnings.warn(str(v), RuntimeWarning) - elif "Symbol not found: _PyUnicodeUCS2_" in str(v): - # should match _PyUnicodeUCS2_FromString and - # _PyUnicodeUCS2_AsLatin1String - warnings.warn( - "The _imaging extension was built for Python with UCS2 support; " - "recompile Pillow or build Python --without-wide-unicode. ", - RuntimeWarning, - ) - elif "Symbol not found: _PyUnicodeUCS4_" in str(v): - # should match _PyUnicodeUCS4_FromString and - # _PyUnicodeUCS4_AsLatin1String - warnings.warn( - "The _imaging extension was built for Python with UCS4 support; " - "recompile Pillow or build Python --with-wide-unicode. ", - RuntimeWarning, - ) # Fail here anyway. Don't let people run with a mostly broken Pillow. # see docs/porting.rst raise @@ -129,18 +100,6 @@ try: except ImportError: cffi = None -try: - from pathlib import Path - - HAS_PATHLIB = True -except ImportError: - try: - from pathlib2 import Path - - HAS_PATHLIB = True - except ImportError: - HAS_PATHLIB = False - def isImageType(t): """ @@ -447,7 +406,7 @@ def _getdecoder(mode, decoder_name, args, extra=()): decoder = getattr(core, decoder_name + "_decoder") return decoder(mode, *args + extra) except AttributeError: - raise IOError("decoder %s not available" % decoder_name) + raise OSError("decoder %s not available" % decoder_name) def _getencoder(mode, encoder_name, args, extra=()): @@ -468,7 +427,7 @@ def _getencoder(mode, encoder_name, args, extra=()): encoder = getattr(core, encoder_name + "_encoder") return encoder(mode, *args + extra) except AttributeError: - raise IOError("encoder %s not available" % encoder_name) + raise OSError("encoder %s not available" % encoder_name) # -------------------------------------------------------------------- @@ -479,7 +438,7 @@ def coerce_e(value): return value if isinstance(value, _E) else _E(value) -class _E(object): +class _E: def __init__(self, data): self.data = data @@ -520,7 +479,7 @@ def _getscaleoffset(expr): # Implementation wrapper -class Image(object): +class Image: """ This class represents an image object. To create :py:class:`~PIL.Image.Image` objects, use the appropriate factory @@ -662,10 +621,6 @@ class Image(object): and self.tobytes() == other.tobytes() ) - def __ne__(self, other): - eq = self == other - return not eq - def __repr__(self): return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % ( self.__class__.__module__, @@ -1335,10 +1290,7 @@ class Image(object): self.load() try: - if py3: - return list(self.im.getpalette()) - else: - return [i8(c) for c in self.im.getpalette()] + return list(self.im.getpalette()) except ValueError: return None # no palette @@ -1489,7 +1441,7 @@ class Image(object): raise ValueError("cannot determine region size; use 4-item box") box += (box[0] + size[0], box[1] + size[1]) - if isStringType(im): + if isinstance(im, str): from . import ImageColor im = ImageColor.getcolor(im, self.mode) @@ -1689,10 +1641,7 @@ class Image(object): palette = ImagePalette.raw(data.rawmode, data.palette) else: if not isinstance(data, bytes): - if py3: - data = bytes(data) - else: - data = "".join(chr(x) for x in data) + data = bytes(data) palette = ImagePalette.raw(rawmode, data) self.mode = "PA" if "A" in self.mode else "P" self.palette = palette @@ -2024,7 +1973,7 @@ class Image(object): if isPath(fp): filename = fp open_fp = True - elif HAS_PATHLIB and isinstance(fp, Path): + elif isinstance(fp, Path): filename = str(fp) open_fp = True if not filename and hasattr(fp, "name") and isPath(fp.name): @@ -2146,7 +2095,7 @@ class Image(object): """ self.load() - if isStringType(channel): + if isinstance(channel, str): try: channel = self.getbands().index(channel) except ValueError: @@ -2411,12 +2360,12 @@ class Image(object): # Abstract handlers. -class ImagePointHandler(object): +class ImagePointHandler: # used as a mixin by point transforms (for use with im.point) pass -class ImageTransformHandler(object): +class ImageTransformHandler: # used as a mixin by geometry transforms (for use with im.transform) pass @@ -2474,7 +2423,7 @@ def new(mode, size, color=0): # don't initialize return Image()._new(core.new(mode, size)) - if isStringType(color): + if isinstance(color, str): # css3-style specifier from . import ImageColor @@ -2736,7 +2685,7 @@ def open(fp, mode="r"): exclusive_fp = False filename = "" - if HAS_PATHLIB and isinstance(fp, Path): + if isinstance(fp, Path): filename = str(fp.resolve()) elif isPath(fp): filename = fp @@ -2794,7 +2743,9 @@ def open(fp, mode="r"): fp.close() for message in accept_warnings: warnings.warn(message) - raise IOError("cannot identify image file %r" % (filename if filename else fp)) + raise UnidentifiedImageError( + "cannot identify image file %r" % (filename if filename else fp) + ) # @@ -3300,11 +3251,6 @@ class Exif(MutableMapping): def __contains__(self, tag): return tag in self._data or (self._info is not None and tag in self._info) - if not py3: - - def has_key(self, tag): - return tag in self - def __setitem__(self, tag, value): if self._info is not None and tag in self._info: del self._info[tag] diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index ed4eefc0d..d05b3102c 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -15,12 +15,9 @@ # See the README file for information on usage and redistribution. See # below for the original description. -from __future__ import print_function - import sys from PIL import Image -from PIL._util import isStringType try: from PIL import _imagingcms @@ -152,7 +149,7 @@ for flag in FLAGS.values(): # Profile. -class ImageCmsProfile(object): +class ImageCmsProfile: def __init__(self, profile): """ :param profile: Either a string representing a filename, @@ -161,7 +158,7 @@ class ImageCmsProfile(object): """ - if isStringType(profile): + if isinstance(profile, str): self._set(core.profile_open(profile), profile) elif hasattr(profile, "read"): self._set(core.profile_frombytes(profile.read())) @@ -374,7 +371,7 @@ def profileToProfile( imOut = None else: imOut = transform.apply(im) - except (IOError, TypeError, ValueError) as v: + except (OSError, TypeError, ValueError) as v: raise PyCMSError(v) return imOut @@ -398,7 +395,7 @@ def getOpenProfile(profileFilename): try: return ImageCmsProfile(profileFilename) - except (IOError, TypeError, ValueError) as v: + except (OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -479,7 +476,7 @@ def buildTransform( return ImageCmsTransform( inputProfile, outputProfile, inMode, outMode, renderingIntent, flags=flags ) - except (IOError, TypeError, ValueError) as v: + except (OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -590,7 +587,7 @@ def buildProofTransform( proofRenderingIntent, flags, ) - except (IOError, TypeError, ValueError) as v: + except (OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -733,9 +730,9 @@ def getProfileName(profile): return (profile.profile.profile_description or "") + "\n" if not manufacturer or len(model) > 30: return model + "\n" - return "%s - %s\n" % (model, manufacturer) + return "{} - {}\n".format(model, manufacturer) - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -775,7 +772,7 @@ def getProfileInfo(profile): arr.append(elt) return "\r\n\r\n".join(arr) + "\r\n\r\n" - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -803,7 +800,7 @@ def getProfileCopyright(profile): if not isinstance(profile, ImageCmsProfile): profile = ImageCmsProfile(profile) return (profile.profile.copyright or "") + "\n" - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -831,7 +828,7 @@ def getProfileManufacturer(profile): if not isinstance(profile, ImageCmsProfile): profile = ImageCmsProfile(profile) return (profile.profile.manufacturer or "") + "\n" - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -860,7 +857,7 @@ def getProfileModel(profile): if not isinstance(profile, ImageCmsProfile): profile = ImageCmsProfile(profile) return (profile.profile.model or "") + "\n" - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -889,7 +886,7 @@ def getProfileDescription(profile): if not isinstance(profile, ImageCmsProfile): profile = ImageCmsProfile(profile) return (profile.profile.profile_description or "") + "\n" - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -928,7 +925,7 @@ def getDefaultIntent(profile): if not isinstance(profile, ImageCmsProfile): profile = ImageCmsProfile(profile) return profile.profile.rendering_intent - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -979,7 +976,7 @@ def isIntentSupported(profile, intent, direction): return 1 else: return -1 - except (AttributeError, IOError, TypeError, ValueError) as v: + except (AttributeError, OSError, TypeError, ValueError) as v: raise PyCMSError(v) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index ed3383f05..c6e12150e 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -34,7 +34,6 @@ import math import numbers from . import Image, ImageColor -from ._util import isStringType """ @@ -45,7 +44,7 @@ directly. """ -class ImageDraw(object): +class ImageDraw: def __init__(self, im, mode=None): """ Create a drawing instance. @@ -107,13 +106,13 @@ class ImageDraw(object): ink = self.ink else: if ink is not None: - if isStringType(ink): + if isinstance(ink, str): ink = ImageColor.getcolor(ink, self.mode) if self.palette and not isinstance(ink, numbers.Number): ink = self.palette.getcolor(ink) ink = self.draw.draw_ink(ink) if fill is not None: - if isStringType(fill): + if isinstance(fill, str): fill = ImageColor.getcolor(fill, self.mode) if self.palette and not isinstance(fill, numbers.Number): fill = self.palette.getcolor(fill) @@ -314,7 +313,7 @@ class ImageDraw(object): language=language, stroke_width=stroke_width, *args, - **kwargs + **kwargs, ) coord = coord[0] + offset[0], coord[1] + offset[1] except AttributeError: @@ -327,7 +326,7 @@ class ImageDraw(object): language, stroke_width, *args, - **kwargs + **kwargs, ) except TypeError: mask = font.getmask(text) diff --git a/src/PIL/ImageDraw2.py b/src/PIL/ImageDraw2.py index 324d869f0..20b5fe4c4 100644 --- a/src/PIL/ImageDraw2.py +++ b/src/PIL/ImageDraw2.py @@ -19,25 +19,25 @@ from . import Image, ImageColor, ImageDraw, ImageFont, ImagePath -class Pen(object): +class Pen: def __init__(self, color, width=1, opacity=255): self.color = ImageColor.getrgb(color) self.width = width -class Brush(object): +class Brush: def __init__(self, color, opacity=255): self.color = ImageColor.getrgb(color) -class Font(object): +class Font: def __init__(self, color, file, size=12): # FIXME: add support for bitmap fonts self.color = ImageColor.getrgb(color) self.font = ImageFont.truetype(file, size) -class Draw(object): +class Draw: def __init__(self, image, size=None, color=None): if not hasattr(image, "im"): image = Image.new(image, size, color) diff --git a/src/PIL/ImageEnhance.py b/src/PIL/ImageEnhance.py index 534eb4f16..3b79d5c46 100644 --- a/src/PIL/ImageEnhance.py +++ b/src/PIL/ImageEnhance.py @@ -21,7 +21,7 @@ from . import Image, ImageFilter, ImageStat -class _Enhance(object): +class _Enhance: def enhance(self, factor): """ Returns an enhanced image. diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 7d5229b8e..a343bd43c 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -56,7 +56,7 @@ def raise_ioerror(error): message = ERRORS.get(error) if not message: message = "decoder error %d" % error - raise IOError(message + " when reading image file") + raise OSError(message + " when reading image file") # @@ -148,7 +148,7 @@ class ImageFile(Image.Image): pixel = Image.Image.load(self) if self.tile is None: - raise IOError("cannot load this image") + raise OSError("cannot load this image") if not self.tile: return pixel @@ -206,7 +206,7 @@ class ImageFile(Image.Image): # we might need to reload the palette data. if self.palette: self.palette.dirty = 1 - except (AttributeError, EnvironmentError, ImportError): + except (AttributeError, OSError, ImportError): self.map = None self.load_prepare() @@ -241,13 +241,13 @@ class ImageFile(Image.Image): if LOAD_TRUNCATED_IMAGES: break else: - raise IOError("image file is truncated") + raise OSError("image file is truncated") if not s: # truncated jpeg if LOAD_TRUNCATED_IMAGES: break else: - raise IOError( + raise OSError( "image file is truncated " "(%d bytes not processed)" % len(b) ) @@ -325,7 +325,7 @@ class StubImageFile(ImageFile): def load(self): loader = self._load() if loader is None: - raise IOError("cannot find loader for this %s file" % self.format) + raise OSError("cannot find loader for this %s file" % self.format) image = loader.load(self) assert image is not None # become the other object (!) @@ -337,7 +337,7 @@ class StubImageFile(ImageFile): raise NotImplementedError("StubImageFile subclass must implement _load") -class Parser(object): +class Parser: """ Incremental image parser. This class implements the standard feed/close consumer interface. @@ -414,7 +414,7 @@ class Parser(object): try: with io.BytesIO(self.data) as fp: im = Image.open(fp) - except IOError: + except OSError: # traceback.print_exc() pass # not enough data else: @@ -459,9 +459,9 @@ class Parser(object): self.feed(b"") self.data = self.decoder = None if not self.finished: - raise IOError("image was incomplete") + raise OSError("image was incomplete") if not self.image: - raise IOError("cannot parse this image") + raise OSError("cannot parse this image") if self.data: # incremental parsing not possible; reopen the file # not that we have all data @@ -517,7 +517,7 @@ def _save(im, fp, tile, bufsize=0): if s: break if s < 0: - raise IOError("encoder error %d when writing image file" % s) + raise OSError("encoder error %d when writing image file" % s) e.cleanup() else: # slight speedup: compress to real file object @@ -532,7 +532,7 @@ def _save(im, fp, tile, bufsize=0): else: s = e.encode_to_file(fh, bufsize) if s < 0: - raise IOError("encoder error %d when writing image file" % s) + raise OSError("encoder error %d when writing image file" % s) e.cleanup() if hasattr(fp, "flush"): fp.flush() @@ -562,7 +562,7 @@ def _safe_read(fp, size): return b"".join(data) -class PyCodecState(object): +class PyCodecState: def __init__(self): self.xsize = 0 self.ysize = 0 @@ -573,7 +573,7 @@ class PyCodecState(object): return (self.xoff, self.yoff, self.xoff + self.xsize, self.yoff + self.ysize) -class PyDecoder(object): +class PyDecoder: """ Python implementation of a format decoder. Override this class and add the decoding logic in the `decode` method. diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index fa4162b61..6b0f5eb37 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -14,9 +14,6 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import division - import functools try: @@ -25,7 +22,7 @@ except ImportError: # pragma: no cover numpy = None -class Filter(object): +class Filter: pass @@ -498,7 +495,7 @@ class Color3DLUT(MultibandFilter): r / (size1D - 1), g / (size2D - 1), b / (size3D - 1), - *values + *values, ) else: values = callback(*values) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 2546d2aa8..619800829 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -31,13 +31,13 @@ import sys from io import BytesIO from . import Image -from ._util import isDirectory, isPath, py3 +from ._util import isDirectory, isPath LAYOUT_BASIC = 0 LAYOUT_RAQM = 1 -class _imagingft_not_installed(object): +class _imagingft_not_installed: # module placeholder def __getattr__(self, id): raise ImportError("The _imagingft C module is not installed") @@ -65,7 +65,7 @@ except ImportError: # -------------------------------------------------------------------- -class ImageFont(object): +class ImageFont: "PIL font wrapper" def _load_pilfont(self, filename): @@ -81,7 +81,7 @@ class ImageFont(object): if image and image.mode in ("1", "L"): break else: - raise IOError("cannot find glyph data file") + raise OSError("cannot find glyph data file") self.file = fullname @@ -147,7 +147,7 @@ class ImageFont(object): # truetype factory function to create font objects. -class FreeTypeFont(object): +class FreeTypeFont: "FreeType font wrapper (requires _imagingft service)" def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None): @@ -544,7 +544,7 @@ class FreeTypeFont(object): raise NotImplementedError("FreeType 2.9.1 or greater is required") -class TransposedFont(object): +class TransposedFont: "Wrapper for writing rotated or mirrored text" def __init__(self, font, orientation=None): @@ -640,7 +640,7 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): try: return freetype(font) - except IOError: + except OSError: if not isPath(font): raise ttf_filename = os.path.basename(font) @@ -697,15 +697,12 @@ def load_path(filename): for directory in sys.path: if isDirectory(directory): if not isinstance(filename, str): - if py3: - filename = filename.decode("utf-8") - else: - filename = filename.encode("utf-8") + filename = filename.decode("utf-8") try: return load(os.path.join(directory, filename)) - except IOError: + except OSError: pass - raise IOError("cannot find font file") + raise OSError("cannot find font file") def load_default(): diff --git a/src/PIL/ImageMath.py b/src/PIL/ImageMath.py index 392151c10..adbb94000 100644 --- a/src/PIL/ImageMath.py +++ b/src/PIL/ImageMath.py @@ -15,15 +15,9 @@ # See the README file for information on usage and redistribution. # +import builtins + from . import Image, _imagingmath -from ._util import py3 - -try: - import builtins -except ImportError: - import __builtin__ - - builtins = __builtin__ VERBOSE = 0 @@ -32,7 +26,7 @@ def _isconstant(v): return isinstance(v, (int, float)) -class _Operand(object): +class _Operand: """Wraps an image operand, providing standard operators""" def __init__(self, im): @@ -101,11 +95,6 @@ class _Operand(object): # an image is "true" if it contains at least one non-zero pixel return self.im.getbbox() is not None - if not py3: - # Provide __nonzero__ for pre-Py3k - __nonzero__ = __bool__ - del __bool__ - def __abs__(self): return self.apply("abs", self) @@ -152,13 +141,6 @@ class _Operand(object): def __rpow__(self, other): return self.apply("pow", other, self) - if not py3: - # Provide __div__ and __rdiv__ for pre-Py3k - __div__ = __truediv__ - __rdiv__ = __rtruediv__ - del __truediv__ - del __rtruediv__ - # bitwise def __invert__(self): return self.apply("invert", self) diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py index 596be7b9d..988288329 100644 --- a/src/PIL/ImageMode.py +++ b/src/PIL/ImageMode.py @@ -17,7 +17,7 @@ _modes = None -class ModeDescriptor(object): +class ModeDescriptor: """Wrapper for mode strings.""" def __init__(self, mode, bands, basemode, basetype): diff --git a/src/PIL/ImageMorph.py b/src/PIL/ImageMorph.py index 61199234b..d1ec09eac 100644 --- a/src/PIL/ImageMorph.py +++ b/src/PIL/ImageMorph.py @@ -5,8 +5,6 @@ # # Copyright (c) 2014 Dov Grobgeld -from __future__ import print_function - import re from . import Image, _imagingmorph @@ -27,7 +25,7 @@ MIRROR_MATRIX = [ # fmt: on -class LutBuilder(object): +class LutBuilder: """A class for building a MorphLut from a descriptive language The input patterns is a list of a strings sequences like these:: @@ -178,7 +176,7 @@ class LutBuilder(object): return self.lut -class MorphOp(object): +class MorphOp: """A class for binary morphological operators""" def __init__(self, lut=None, op_name=None, patterns=None): diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 5052cb74d..3ffe50806 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -21,7 +21,6 @@ import functools import operator from . import Image -from ._util import isStringType # # helpers @@ -39,7 +38,7 @@ def _border(border): def _color(color, mode): - if isStringType(color): + if isinstance(color, str): from . import ImageColor color = ImageColor.getcolor(color, mode) @@ -55,7 +54,7 @@ def _lut(image, lut): lut = lut + lut + lut return image.point(lut) else: - raise IOError("not supported for this image mode") + raise OSError("not supported for this image mode") # diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index 2d4f5cb6b..e0d439c98 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -21,7 +21,7 @@ import array from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile -class ImagePalette(object): +class ImagePalette: """ Color palette for palette mapped images @@ -216,6 +216,6 @@ def load(filename): # traceback.print_exc() pass else: - raise IOError("cannot load palette") + raise OSError("cannot load palette") return lut # data, rawmode diff --git a/src/PIL/ImageQt.py b/src/PIL/ImageQt.py index f49725b5f..dfe2f80bd 100644 --- a/src/PIL/ImageQt.py +++ b/src/PIL/ImageQt.py @@ -20,7 +20,7 @@ import sys from io import BytesIO from . import Image -from ._util import isPath, py3 +from ._util import isPath qt_versions = [["5", "PyQt5"], ["side2", "PySide2"]] @@ -65,11 +65,7 @@ def fromqimage(im): im.save(buffer, "ppm") b = BytesIO() - try: - b.write(buffer.data()) - except TypeError: - # workaround for Python 2 - b.write(str(buffer.data())) + b.write(buffer.data()) buffer.close() b.seek(0) @@ -125,10 +121,7 @@ def _toqclass_helper(im): # handle filename, if given instead of image name if hasattr(im, "toUtf8"): # FIXME - is this really the best way to do this? - if py3: - im = str(im.toUtf8(), "utf-8") - else: - im = unicode(im.toUtf8(), "utf-8") # noqa: F821 + im = str(im.toUtf8(), "utf-8") if isPath(im): im = Image.open(im) diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index f9be92d48..4e9f5c210 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -16,7 +16,7 @@ ## -class Iterator(object): +class Iterator: """ This class implements an iterator object that can be used to loop over an image sequence. @@ -52,9 +52,6 @@ class Iterator(object): except EOFError: raise StopIteration - def next(self): - return self.__next__() - def all_frames(im, func=None): """ diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index ca622c525..f7e809279 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -11,21 +11,15 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - import os +import shutil import subprocess import sys import tempfile +from shlex import quote from PIL import Image -if sys.version_info.major >= 3: - from shlex import quote -else: - from pipes import quote - _viewers = [] @@ -56,7 +50,7 @@ def show(image, title=None, **options): return 0 -class Viewer(object): +class Viewer: """Base class for viewers.""" # main api @@ -127,10 +121,8 @@ elif sys.platform == "darwin": # on darwin open returns immediately resulting in the temp # file removal while app is opening command = "open -a Preview.app" - command = "(%s %s; sleep 20; rm -f %s)&" % ( - command, - quote(file), - quote(file), + command = "({} {}; sleep 20; rm -f {})&".format( + command, quote(file), quote(file) ) return command @@ -154,23 +146,13 @@ else: # unixoids - def which(executable): - path = os.environ.get("PATH") - if not path: - return None - for dirname in path.split(os.pathsep): - filename = os.path.join(dirname, executable) - if os.path.isfile(filename) and os.access(filename, os.X_OK): - return filename - return None - class UnixViewer(Viewer): format = "PNG" options = {"compress_level": 1} def get_command(self, file, **options): command = self.get_command_ex(file, **options)[0] - return "(%s %s; rm -f %s)&" % (command, quote(file), quote(file)) + return "({} {}; rm -f {})&".format(command, quote(file), quote(file)) def show_file(self, file, **options): """Display given file""" @@ -192,7 +174,7 @@ else: command = executable = "display" return command, executable - if which("display"): + if shutil.which("display"): register(DisplayViewer) class EogViewer(UnixViewer): @@ -200,7 +182,7 @@ else: command = executable = "eog" return command, executable - if which("eog"): + if shutil.which("eog"): register(EogViewer) class XVViewer(UnixViewer): @@ -212,7 +194,7 @@ else: command += " -name %s" % quote(title) return command, executable - if which("xv"): + if shutil.which("xv"): register(XVViewer) if __name__ == "__main__": diff --git a/src/PIL/ImageStat.py b/src/PIL/ImageStat.py index 9ba16fd85..50bafc972 100644 --- a/src/PIL/ImageStat.py +++ b/src/PIL/ImageStat.py @@ -26,7 +26,7 @@ import math import operator -class Stat(object): +class Stat: def __init__(self, image_or_list, mask=None): try: if mask: diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index bb825f353..ee707cffb 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -25,17 +25,11 @@ # See the README file for information on usage and redistribution. # -import sys +import tkinter from io import BytesIO from . import Image -if sys.version_info.major > 2: - import tkinter -else: - import Tkinter as tkinter - - # -------------------------------------------------------------------- # Check for Tkinter interface hooks @@ -68,7 +62,7 @@ def _get_image_from_kw(kw): # PhotoImage -class PhotoImage(object): +class PhotoImage: """ A Tkinter-compatible photo image. This can be used everywhere Tkinter expects an image object. If the image is an RGBA @@ -209,7 +203,7 @@ class PhotoImage(object): # BitmapImage -class BitmapImage(object): +class BitmapImage: """ A Tkinter-compatible bitmap image. This can be used everywhere Tkinter expects an image object. @@ -299,7 +293,7 @@ def _show(image, title): super().__init__(master, image=self.image, bg="black", bd=0) if not tkinter._default_root: - raise IOError("tkinter not initialized") + raise OSError("tkinter not initialized") top = tkinter.Toplevel() if title: top.title(title) diff --git a/src/PIL/ImageWin.py b/src/PIL/ImageWin.py index c654569c5..927b1694b 100644 --- a/src/PIL/ImageWin.py +++ b/src/PIL/ImageWin.py @@ -20,7 +20,7 @@ from . import Image -class HDC(object): +class HDC: """ Wraps an HDC integer. The resulting object can be passed to the :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose` @@ -34,7 +34,7 @@ class HDC(object): return self.dc -class HWND(object): +class HWND: """ Wraps an HWND integer. The resulting object can be passed to the :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose` @@ -48,7 +48,7 @@ class HWND(object): return self.wnd -class Dib(object): +class Dib: """ A Windows bitmap with the given mode and size. The mode can be one of "1", "L", "P", or "RGB". @@ -186,7 +186,7 @@ class Dib(object): return self.image.tobytes() -class Window(object): +class Window: """Create a Window with the given title size.""" def __init__(self, title="PIL", width=None, height=None): diff --git a/src/PIL/ImtImagePlugin.py b/src/PIL/ImtImagePlugin.py index a9e991fbe..21ffd7475 100644 --- a/src/PIL/ImtImagePlugin.py +++ b/src/PIL/ImtImagePlugin.py @@ -19,11 +19,6 @@ import re from . import Image, ImageFile -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" - - # # -------------------------------------------------------------------- diff --git a/src/PIL/IptcImagePlugin.py b/src/PIL/IptcImagePlugin.py index aedf2e48c..86a7ee8cb 100644 --- a/src/PIL/IptcImagePlugin.py +++ b/src/PIL/IptcImagePlugin.py @@ -14,19 +14,12 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - import os import tempfile from . import Image, ImageFile from ._binary import i8, i16be as i16, i32be as i32, o8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.3" - COMPRESSION = {1: "raw", 5: "jpeg"} PAD = o8(0) * 4 @@ -75,7 +68,7 @@ class IptcImageFile(ImageFile.ImageFile): # field size size = i8(s[3]) if size > 132: - raise IOError("illegal field length in IPTC/NAA file") + raise OSError("illegal field length in IPTC/NAA file") elif size == 128: size = 0 elif size > 128: @@ -126,7 +119,7 @@ class IptcImageFile(ImageFile.ImageFile): try: compression = COMPRESSION[self.getint((3, 120))] except KeyError: - raise IOError("Unknown IPTC image compression") + raise OSError("Unknown IPTC image compression") # tile if tag == (8, 10): @@ -215,7 +208,7 @@ def getiptcinfo(im): return None # no properties # create an IptcImagePlugin object without initializing it - class FakeImage(object): + class FakeImage: pass im = FakeImage() diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index 37f111778..2c51d3678 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -18,10 +18,6 @@ import struct from . import Image, ImageFile -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - def _parse_codestream(fp): """Parse the JPEG 2000 codestream to extract the size and component diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index da0759129..ea2f795a7 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -31,9 +31,6 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - import array import io import os @@ -44,14 +41,8 @@ import warnings from . import Image, ImageFile, TiffImagePlugin from ._binary import i8, i16be as i16, i32be as i32, o8 -from ._util import isStringType from .JpegPresets import presets -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.6" - - # # Parser @@ -617,7 +608,7 @@ def _save(im, fp, filename): try: rawmode = RAWMODE[im.mode] except KeyError: - raise IOError("cannot write mode %s as JPEG" % im.mode) + raise OSError("cannot write mode %s as JPEG" % im.mode) info = im.encoderinfo @@ -641,7 +632,7 @@ def _save(im, fp, filename): else: if subsampling in presets: subsampling = presets[subsampling].get("subsampling", -1) - if isStringType(qtables) and qtables in presets: + if isinstance(qtables, str) and qtables in presets: qtables = presets[qtables].get("quantization") if subsampling == "4:4:4": @@ -662,7 +653,7 @@ def _save(im, fp, filename): def validate_qtables(qtables): if qtables is None: return qtables - if isStringType(qtables): + if isinstance(qtables, str): try: lines = [ int(num) diff --git a/src/PIL/JpegPresets.py b/src/PIL/JpegPresets.py index 387844f8e..012bf81b0 100644 --- a/src/PIL/JpegPresets.py +++ b/src/PIL/JpegPresets.py @@ -33,7 +33,10 @@ Possible subsampling values are 0, 1 and 2 that correspond to 4:4:4, 4:2:2 and 4:2:0. You can get the subsampling of a JPEG with the -`JpegImagePlugin.get_subsampling(im)` function. +`JpegImagePlugin.get_sampling(im)` function. + +In JPEG compressed data a JPEG marker is used instead of an EXIF tag. +(ref.: https://www.exiv2.org/tags.html) Quantization tables diff --git a/src/PIL/McIdasImagePlugin.py b/src/PIL/McIdasImagePlugin.py index bddd33abb..cd047fe9d 100644 --- a/src/PIL/McIdasImagePlugin.py +++ b/src/PIL/McIdasImagePlugin.py @@ -20,10 +20,6 @@ import struct from . import Image, ImageFile -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" - def _accept(s): return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04" diff --git a/src/PIL/MicImagePlugin.py b/src/PIL/MicImagePlugin.py index b48905bda..8610988fc 100644 --- a/src/PIL/MicImagePlugin.py +++ b/src/PIL/MicImagePlugin.py @@ -21,11 +21,6 @@ import olefile from . import Image, TiffImagePlugin -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - - # # -------------------------------------------------------------------- @@ -51,7 +46,7 @@ class MicImageFile(TiffImagePlugin.TiffImageFile): try: self.ole = olefile.OleFileIO(self.fp) - except IOError: + except OSError: raise SyntaxError("not an MIC file; invalid OLE file") # find ACI subfiles with Image members (maybe not the diff --git a/src/PIL/MpegImagePlugin.py b/src/PIL/MpegImagePlugin.py index 9c662fcc2..a358dfdce 100644 --- a/src/PIL/MpegImagePlugin.py +++ b/src/PIL/MpegImagePlugin.py @@ -17,16 +17,11 @@ from . import Image, ImageFile from ._binary import i8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - - # # Bitstream parser -class BitStream(object): +class BitStream: def __init__(self, fp): self.fp = fp self.bits = 0 diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 938f2a5a6..a63e76fe7 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -21,10 +21,6 @@ from . import Image, ImageFile, JpegImagePlugin from ._binary import i16be as i16 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - def _accept(prefix): return JpegImagePlugin._accept(prefix) diff --git a/src/PIL/MspImagePlugin.py b/src/PIL/MspImagePlugin.py index 7315ab66e..2b2937ecf 100644 --- a/src/PIL/MspImagePlugin.py +++ b/src/PIL/MspImagePlugin.py @@ -29,11 +29,6 @@ import struct from . import Image, ImageFile from ._binary import i8, i16le as i16, o16le as o16 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - - # # read MSP files @@ -122,7 +117,7 @@ class MspDecoder(ImageFile.PyDecoder): "<%dH" % (self.state.ysize), self.fd.read(self.state.ysize * 2) ) except struct.error: - raise IOError("Truncated MSP file in row map") + raise OSError("Truncated MSP file in row map") for x, rowlen in enumerate(rowmap): try: @@ -131,7 +126,7 @@ class MspDecoder(ImageFile.PyDecoder): continue row = self.fd.read(rowlen) if len(row) != rowlen: - raise IOError( + raise OSError( "Truncated MSP file, expected %d bytes on row %s", (rowlen, x) ) idx = 0 @@ -148,7 +143,7 @@ class MspDecoder(ImageFile.PyDecoder): idx += runcount except struct.error: - raise IOError("Corrupted MSP file in row %d" % x) + raise OSError("Corrupted MSP file in row %d" % x) self.set_as_raw(img.getvalue(), ("1", 0, 1)) @@ -165,7 +160,7 @@ Image.register_decoder("MSP", MspDecoder) def _save(im, fp, filename): if im.mode != "1": - raise IOError("cannot write mode %s as MSP" % im.mode) + raise OSError("cannot write mode %s as MSP" % im.mode) # create MSP header header = [0] * 16 diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index f37701ce9..90bcad036 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -18,13 +18,12 @@ import sys from . import EpsImagePlugin -from ._util import py3 ## # Simple Postscript graphics interface. -class PSDraw(object): +class PSDraw: """ Sets up printing to the given file. If **fp** is omitted, :py:attr:`sys.stdout` is assumed. @@ -36,7 +35,7 @@ class PSDraw(object): self.fp = fp def _fp_write(self, to_write): - if not py3 or self.fp == sys.stdout: + if self.fp == sys.stdout: self.fp.write(to_write) else: self.fp.write(bytes(to_write, "UTF-8")) @@ -72,7 +71,7 @@ class PSDraw(object): """ if font not in self.isofont: # reencode font - self._fp_write("/PSDraw-%s ISOLatin1Encoding /%s E\n" % (font, font)) + self._fp_write("/PSDraw-{} ISOLatin1Encoding /{} E\n".format(font, font)) self.isofont[font] = 1 # rough self._fp_write("/F0 %d /PSDraw-%s F\n" % (size, font)) @@ -133,12 +132,12 @@ class PSDraw(object): y = ymax dx = (xmax - x) / 2 + box[0] dy = (ymax - y) / 2 + box[1] - self._fp_write("gsave\n%f %f translate\n" % (dx, dy)) + self._fp_write("gsave\n{:f} {:f} translate\n".format(dx, dy)) if (x, y) != im.size: # EpsImagePlugin._save prints the image at (0,0,xsize,ysize) sx = x / im.size[0] sy = y / im.size[1] - self._fp_write("%f %f scale\n" % (sx, sy)) + self._fp_write("{:f} {:f} scale\n".format(sx, sy)) EpsImagePlugin._save(im, self.fp, None, 0) self._fp_write("\ngrestore\n") diff --git a/src/PIL/PaletteFile.py b/src/PIL/PaletteFile.py index ab22d5f0c..73f1b4b27 100644 --- a/src/PIL/PaletteFile.py +++ b/src/PIL/PaletteFile.py @@ -19,7 +19,7 @@ from ._binary import o8 # File handler for Teragon-style palette files. -class PaletteFile(object): +class PaletteFile: rawmode = "RGB" diff --git a/src/PIL/PalmImagePlugin.py b/src/PIL/PalmImagePlugin.py index dd068d794..804ece34a 100644 --- a/src/PIL/PalmImagePlugin.py +++ b/src/PIL/PalmImagePlugin.py @@ -10,10 +10,6 @@ from . import Image, ImageFile from ._binary import o8, o16be as o16b -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "1.0" - # fmt: off _Palm8BitColormapValues = ( # noqa: E131 (255, 255, 255), (255, 204, 255), (255, 153, 255), (255, 102, 255), @@ -141,7 +137,7 @@ def _save(im, fp, filename): bpp = im.info["bpp"] im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval)) else: - raise IOError("cannot write mode %s as Palm" % im.mode) + raise OSError("cannot write mode %s as Palm" % im.mode) # we ignore the palette here im.mode = "P" @@ -157,7 +153,7 @@ def _save(im, fp, filename): else: - raise IOError("cannot write mode %s as Palm" % im.mode) + raise OSError("cannot write mode %s as Palm" % im.mode) # # make sure image data is available diff --git a/src/PIL/PcdImagePlugin.py b/src/PIL/PcdImagePlugin.py index 6f01845ec..625f55646 100644 --- a/src/PIL/PcdImagePlugin.py +++ b/src/PIL/PcdImagePlugin.py @@ -18,11 +18,6 @@ from . import Image, ImageFile from ._binary import i8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - - ## # Image plugin for PhotoCD images. This plugin only reads the 768x512 # image from the file; higher resolutions are encoded in a proprietary diff --git a/src/PIL/PcfFontFile.py b/src/PIL/PcfFontFile.py index 7b3075696..605cbbdf3 100644 --- a/src/PIL/PcfFontFile.py +++ b/src/PIL/PcfFontFile.py @@ -184,7 +184,7 @@ class PcfFontFile(FontFile.FontFile): nbitmaps = i32(fp.read(4)) if nbitmaps != len(metrics): - raise IOError("Wrong number of bitmaps") + raise OSError("Wrong number of bitmaps") offsets = [] for i in range(nbitmaps): diff --git a/src/PIL/PcxImagePlugin.py b/src/PIL/PcxImagePlugin.py index 397af8c10..6cf10deb3 100644 --- a/src/PIL/PcxImagePlugin.py +++ b/src/PIL/PcxImagePlugin.py @@ -33,10 +33,6 @@ from ._binary import i8, i16le as i16, o8, o16le as o16 logger = logging.getLogger(__name__) -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.6" - def _accept(prefix): return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5] @@ -107,7 +103,7 @@ class PcxImageFile(ImageFile.ImageFile): rawmode = "RGB;L" else: - raise IOError("unknown PCX mode") + raise OSError("unknown PCX mode") self.mode = mode self._size = bbox[2] - bbox[0], bbox[3] - bbox[1] diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 1fd40f5ba..d9bbf6fab 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -24,12 +24,7 @@ import io import os import time -from . import Image, ImageFile, ImageSequence, PdfParser - -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.5" - +from . import Image, ImageFile, ImageSequence, PdfParser, __version__ # # -------------------------------------------------------------------- @@ -82,7 +77,7 @@ def _save(im, fp, filename, save_all=False): existing_pdf.start_writing() existing_pdf.write_header() - existing_pdf.write_comment("created by PIL PDF driver " + __version__) + existing_pdf.write_comment("created by Pillow {} PDF driver".format(__version__)) # # pages diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 0ec6bba14..3267ee491 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -7,24 +7,9 @@ import re import time import zlib -from ._util import py3 -try: - from UserDict import UserDict # Python 2.x -except ImportError: - UserDict = collections.UserDict # Python 3.x - - -if py3: # Python 3.x - - def make_bytes(s): - return s.encode("us-ascii") - - -else: # Python 2.x - - def make_bytes(s): # pragma: no cover - return s # pragma: no cover +def make_bytes(s): + return s.encode("us-ascii") # see 7.9.2.2 Text String Type on page 86 and D.3 PDFDocEncoding Character Set @@ -34,57 +19,55 @@ def encode_text(s): PDFDocEncoding = { - 0x16: u"\u0017", - 0x18: u"\u02D8", - 0x19: u"\u02C7", - 0x1A: u"\u02C6", - 0x1B: u"\u02D9", - 0x1C: u"\u02DD", - 0x1D: u"\u02DB", - 0x1E: u"\u02DA", - 0x1F: u"\u02DC", - 0x80: u"\u2022", - 0x81: u"\u2020", - 0x82: u"\u2021", - 0x83: u"\u2026", - 0x84: u"\u2014", - 0x85: u"\u2013", - 0x86: u"\u0192", - 0x87: u"\u2044", - 0x88: u"\u2039", - 0x89: u"\u203A", - 0x8A: u"\u2212", - 0x8B: u"\u2030", - 0x8C: u"\u201E", - 0x8D: u"\u201C", - 0x8E: u"\u201D", - 0x8F: u"\u2018", - 0x90: u"\u2019", - 0x91: u"\u201A", - 0x92: u"\u2122", - 0x93: u"\uFB01", - 0x94: u"\uFB02", - 0x95: u"\u0141", - 0x96: u"\u0152", - 0x97: u"\u0160", - 0x98: u"\u0178", - 0x99: u"\u017D", - 0x9A: u"\u0131", - 0x9B: u"\u0142", - 0x9C: u"\u0153", - 0x9D: u"\u0161", - 0x9E: u"\u017E", - 0xA0: u"\u20AC", + 0x16: "\u0017", + 0x18: "\u02D8", + 0x19: "\u02C7", + 0x1A: "\u02C6", + 0x1B: "\u02D9", + 0x1C: "\u02DD", + 0x1D: "\u02DB", + 0x1E: "\u02DA", + 0x1F: "\u02DC", + 0x80: "\u2022", + 0x81: "\u2020", + 0x82: "\u2021", + 0x83: "\u2026", + 0x84: "\u2014", + 0x85: "\u2013", + 0x86: "\u0192", + 0x87: "\u2044", + 0x88: "\u2039", + 0x89: "\u203A", + 0x8A: "\u2212", + 0x8B: "\u2030", + 0x8C: "\u201E", + 0x8D: "\u201C", + 0x8E: "\u201D", + 0x8F: "\u2018", + 0x90: "\u2019", + 0x91: "\u201A", + 0x92: "\u2122", + 0x93: "\uFB01", + 0x94: "\uFB02", + 0x95: "\u0141", + 0x96: "\u0152", + 0x97: "\u0160", + 0x98: "\u0178", + 0x99: "\u017D", + 0x9A: "\u0131", + 0x9B: "\u0142", + 0x9C: "\u0153", + 0x9D: "\u0161", + 0x9E: "\u017E", + 0xA0: "\u20AC", } def decode_text(b): if b[: len(codecs.BOM_UTF16_BE)] == codecs.BOM_UTF16_BE: return b[len(codecs.BOM_UTF16_BE) :].decode("utf_16_be") - elif py3: # Python 3.x + else: return "".join(PDFDocEncoding.get(byte, chr(byte)) for byte in b) - else: # Python 2.x - return u"".join(PDFDocEncoding.get(ord(byte), byte) for byte in b) class PdfFormatError(RuntimeError): @@ -247,21 +230,15 @@ class PdfName: def from_pdf_stream(cls, data): return cls(PdfParser.interpret_name(data)) - allowed_chars = set(range(33, 127)) - set(ord(c) for c in "#%/()<>[]{}") + allowed_chars = set(range(33, 127)) - {ord(c) for c in "#%/()<>[]{}"} def __bytes__(self): result = bytearray(b"/") for b in self.name: - if py3: # Python 3.x - if b in self.allowed_chars: - result.append(b) - else: - result.extend(make_bytes("#%02X" % b)) - else: # Python 2.x - if ord(b) in self.allowed_chars: - result.append(b) - else: - result.extend(b"#%02X" % ord(b)) + if b in self.allowed_chars: + result.append(b) + else: + result.extend(make_bytes("#%02X" % b)) return bytes(result) __str__ = __bytes__ @@ -274,13 +251,10 @@ class PdfArray(list): __str__ = __bytes__ -class PdfDict(UserDict): +class PdfDict(collections.UserDict): def __setattr__(self, key, value): if key == "data": - if hasattr(UserDict, "__setattr__"): - UserDict.__setattr__(self, key, value) - else: - self.__dict__[key] = value + collections.UserDict.__setattr__(self, key, value) else: self[key.encode("us-ascii")] = value @@ -324,23 +298,13 @@ class PdfDict(UserDict): out.extend(b"\n>>") return bytes(out) - if not py3: - __str__ = __bytes__ - class PdfBinary: def __init__(self, data): self.data = data - if py3: # Python 3.x - - def __bytes__(self): - return make_bytes("<%s>" % "".join("%02X" % b for b in self.data)) - - else: # Python 2.x - - def __str__(self): - return "<%s>" % "".join("%02X" % ord(b) for b in self.data) + def __bytes__(self): + return make_bytes("<%s>" % "".join("%02X" % b for b in self.data)) class PdfStream: @@ -382,9 +346,7 @@ def pdf_repr(x): return bytes(PdfDict(x)) elif isinstance(x, list): return bytes(PdfArray(x)) - elif (py3 and isinstance(x, str)) or ( - not py3 and isinstance(x, unicode) # noqa: F821 - ): + elif isinstance(x, str): return pdf_repr(encode_text(x)) elif isinstance(x, bytes): # XXX escape more chars? handle binary garbage @@ -471,7 +433,7 @@ class PdfParser: self.f.write(b"%PDF-1.4\n") def write_comment(self, s): - self.f.write(("%% %s\n" % (s,)).encode("utf-8")) + self.f.write(("% {}\n".format(s)).encode("utf-8")) def write_catalog(self): self.del_root() diff --git a/src/PIL/PixarImagePlugin.py b/src/PIL/PixarImagePlugin.py index dc71ca17a..5ea32ba89 100644 --- a/src/PIL/PixarImagePlugin.py +++ b/src/PIL/PixarImagePlugin.py @@ -22,11 +22,6 @@ from . import Image, ImageFile from ._binary import i16le as i16 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - - # # helpers diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 84317ceb7..9f98cd3d7 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -38,11 +38,6 @@ import zlib from . import Image, ImageFile, ImagePalette from ._binary import i8, i16be as i16, i32be as i32, o16be as o16, o32be as o32 -from ._util import py3 - -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.9" logger = logging.getLogger(__name__) @@ -102,7 +97,7 @@ def _crc32(data, seed=0): # Support classes. Suitable for PNG and related formats like MNG etc. -class ChunkStream(object): +class ChunkStream: def __init__(self, fp): self.fp = fp @@ -180,7 +175,7 @@ class ChunkStream(object): try: cid, pos, length = self.read() except struct.error: - raise IOError("truncated PNG file") + raise OSError("truncated PNG file") if cid == endchunk: break @@ -212,7 +207,7 @@ class iTXt(str): return self -class PngInfo(object): +class PngInfo: """ PNG chunk container (for use with save(pnginfo=)) @@ -449,9 +444,8 @@ class PngStream(ChunkStream): k = s v = b"" if k: - if py3: - k = k.decode("latin-1", "strict") - v = v.decode("latin-1", "replace") + k = k.decode("latin-1", "strict") + v = v.decode("latin-1", "replace") self.im_info[k] = self.im_text[k] = v self.check_text_memory(len(v)) @@ -486,9 +480,8 @@ class PngStream(ChunkStream): v = b"" if k: - if py3: - k = k.decode("latin-1", "strict") - v = v.decode("latin-1", "replace") + k = k.decode("latin-1", "strict") + v = v.decode("latin-1", "replace") self.im_info[k] = self.im_text[k] = v self.check_text_memory(len(v)) @@ -523,14 +516,13 @@ class PngStream(ChunkStream): return s else: return s - if py3: - try: - k = k.decode("latin-1", "strict") - lang = lang.decode("utf-8", "strict") - tk = tk.decode("utf-8", "strict") - v = v.decode("utf-8", "strict") - except UnicodeError: - return s + try: + k = k.decode("latin-1", "strict") + lang = lang.decode("utf-8", "strict") + tk = tk.decode("utf-8", "strict") + v = v.decode("utf-8", "strict") + except UnicodeError: + return s self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk) self.check_text_memory(len(v)) @@ -745,7 +737,7 @@ def putchunk(fp, cid, *data): fp.write(o32(crc)) -class _idat(object): +class _idat: # wrap output from the encoder in IDAT chunks def __init__(self, fp, chunk): @@ -798,7 +790,7 @@ def _save(im, fp, filename, chunk=putchunk): try: rawmode, mode = _OUTMODES[mode] except KeyError: - raise IOError("cannot write mode %s as PNG" % mode) + raise OSError("cannot write mode %s as PNG" % mode) # # write minimal PNG file @@ -873,7 +865,7 @@ def _save(im, fp, filename, chunk=putchunk): if "transparency" in im.encoderinfo: # don't bother with transparency if it's an RGBA # and it's in the info dict. It's probably just stale. - raise IOError("cannot use transparency for this mode") + raise OSError("cannot use transparency for this mode") else: if im.mode == "P" and im.im.getpalettemode() == "RGBA": alpha = im.im.getpalette("RGBA", "A") @@ -921,7 +913,7 @@ def _save(im, fp, filename, chunk=putchunk): def getchunks(im, **params): """Return a list of PNG chunks representing this image.""" - class collector(object): + class collector: data = [] def write(self, data): diff --git a/src/PIL/PpmImagePlugin.py b/src/PIL/PpmImagePlugin.py index c3e9eed6d..35a77bafb 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -17,10 +17,6 @@ from . import Image, ImageFile -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" - # # -------------------------------------------------------------------- @@ -139,7 +135,7 @@ def _save(im, fp, filename): elif im.mode == "RGBA": rawmode, head = "RGB", b"P6" else: - raise IOError("cannot write mode %s as PPM" % im.mode) + raise OSError("cannot write mode %s as PPM" % im.mode) fp.write(head + ("\n%d %d\n" % im.size).encode("ascii")) if head == b"P6": fp.write(b"255\n") diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index f72ad5f44..cceb85c5b 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -16,10 +16,6 @@ # See the README file for information on usage and redistribution. # -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.4" - import io from . import Image, ImageFile, ImagePalette @@ -75,7 +71,7 @@ class PsdImageFile(ImageFile.ImageFile): mode, channels = MODES[(psd_mode, psd_bits)] if channels > psd_channels: - raise IOError("not enough channels") + raise OSError("not enough channels") self.mode = mode self._size = i32(s[18:]), i32(s[14:]) diff --git a/src/PIL/PyAccess.py b/src/PIL/PyAccess.py index 2ab06f93f..359a94919 100644 --- a/src/PIL/PyAccess.py +++ b/src/PIL/PyAccess.py @@ -40,7 +40,7 @@ ffi = FFI() ffi.cdef(defs) -class PyAccess(object): +class PyAccess: def __init__(self, img, readonly=False): vals = dict(img.im.unsafe_ptrs) self.readonly = readonly diff --git a/src/PIL/SgiImagePlugin.py b/src/PIL/SgiImagePlugin.py index 99408fdc3..ddd3de379 100644 --- a/src/PIL/SgiImagePlugin.py +++ b/src/PIL/SgiImagePlugin.py @@ -27,11 +27,6 @@ import struct from . import Image, ImageFile from ._binary import i8, i16be as i16, o8 -from ._util import py3 - -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.3" def _accept(prefix): @@ -164,7 +159,9 @@ def _save(im, fp, filename): # assert we've got the right number of bands. if len(im.getbands()) != z: raise ValueError( - "incorrect number of bands in SGI write: %s vs %s" % (z, len(im.getbands())) + "incorrect number of bands in SGI write: {} vs {}".format( + z, len(im.getbands()) + ) ) # Minimum Byte value @@ -173,8 +170,7 @@ def _save(im, fp, filename): pinmax = 255 # Image name (79 characters max, truncated below in write) imgName = os.path.splitext(os.path.basename(filename))[0] - if py3: - imgName = imgName.encode("ascii", "ignore") + imgName = imgName.encode("ascii", "ignore") # Standard representation of pixel in the file colormap = 0 fp.write(struct.pack(">h", magicNumber)) diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index c7b6fa5f8..dd0620c14 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -32,9 +32,6 @@ # Details about the Spider image format: # https://spider.wadsworth.org/spider_doc/spider/docs/image_doc.html # - -from __future__ import print_function - import os import struct import sys @@ -274,7 +271,7 @@ def _save(im, fp, filename): hdr = makeSpiderHeader(im) if len(hdr) < 256: - raise IOError("Error creating Spider header") + raise OSError("Error creating Spider header") # write the SPIDER header fp.writelines(hdr) diff --git a/src/PIL/SunImagePlugin.py b/src/PIL/SunImagePlugin.py index 74fa5f7bd..fd7ca8a40 100644 --- a/src/PIL/SunImagePlugin.py +++ b/src/PIL/SunImagePlugin.py @@ -20,10 +20,6 @@ from . import Image, ImageFile, ImagePalette from ._binary import i32be as i32 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.3" - def _accept(prefix): return len(prefix) >= 4 and i32(prefix) == 0x59A66A95 diff --git a/src/PIL/TarIO.py b/src/PIL/TarIO.py index dc479b905..ede646453 100644 --- a/src/PIL/TarIO.py +++ b/src/PIL/TarIO.py @@ -37,12 +37,12 @@ class TarIO(ContainerIO.ContainerIO): s = self.fh.read(512) if len(s) != 512: - raise IOError("unexpected end of tar file") + raise OSError("unexpected end of tar file") name = s[:100].decode("utf-8") i = name.find("\0") if i == 0: - raise IOError("cannot find subfile") + raise OSError("cannot find subfile") if i > 0: name = name[:i] diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index b1b351396..fd71e545d 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -22,11 +22,6 @@ import warnings from . import Image, ImageFile, ImagePalette from ._binary import i8, i16le as i16, o8, o16le as o16 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.3" - - # # -------------------------------------------------------------------- # Read RGA file @@ -173,7 +168,7 @@ def _save(im, fp, filename): try: rawmode, bits, colormaptype, imagetype = SAVE[im.mode] except KeyError: - raise IOError("cannot write mode %s as TGA" % im.mode) + raise OSError("cannot write mode %s as TGA" % im.mode) if "rle" in im.encoderinfo: rle = im.encoderinfo["rle"] diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index a685009e8..47b69a003 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -38,35 +38,20 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import division, print_function - import distutils.version import io import itertools import os import struct -import sys import warnings +from collections.abc import MutableMapping from fractions import Fraction from numbers import Number, Rational from . import Image, ImageFile, ImagePalette, TiffTags from ._binary import i8, o8 -from ._util import py3 from .TiffTags import TYPES -try: - # Python 3 - from collections.abc import MutableMapping -except ImportError: - # Python 2.7 - from collections import MutableMapping - - -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "1.3.5" DEBUG = False # Needs to be merged with the new logging approach. # Set these to true to force use of libtiff for reading or writing. @@ -366,10 +351,10 @@ class IFDRational(Rational): return delegate - """ a = ['add','radd', 'sub', 'rsub','div', 'rdiv', 'mul', 'rmul', - 'truediv', 'rtruediv', 'floordiv', - 'rfloordiv','mod','rmod', 'pow','rpow', 'pos', 'neg', - 'abs', 'trunc', 'lt', 'gt', 'le', 'ge', 'nonzero', + """ a = ['add','radd', 'sub', 'rsub', 'mul', 'rmul', + 'truediv', 'rtruediv', 'floordiv', 'rfloordiv', + 'mod','rmod', 'pow','rpow', 'pos', 'neg', + 'abs', 'trunc', 'lt', 'gt', 'le', 'ge', 'bool', 'ceil', 'floor', 'round'] print("\n".join("__%s__ = _delegate('__%s__')" % (s,s) for s in a)) """ @@ -378,8 +363,6 @@ class IFDRational(Rational): __radd__ = _delegate("__radd__") __sub__ = _delegate("__sub__") __rsub__ = _delegate("__rsub__") - __div__ = _delegate("__div__") - __rdiv__ = _delegate("__rdiv__") __mul__ = _delegate("__mul__") __rmul__ = _delegate("__rmul__") __truediv__ = _delegate("__truediv__") @@ -398,7 +381,7 @@ class IFDRational(Rational): __gt__ = _delegate("__gt__") __le__ = _delegate("__le__") __ge__ = _delegate("__ge__") - __nonzero__ = _delegate("__nonzero__") + __bool__ = _delegate("__bool__") __ceil__ = _delegate("__ceil__") __floor__ = _delegate("__floor__") __round__ = _delegate("__round__") @@ -527,18 +510,11 @@ class ImageFileDirectory_v2(MutableMapping): def __contains__(self, tag): return tag in self._tags_v2 or tag in self._tagdata - if not py3: - - def has_key(self, tag): - return tag in self - def __setitem__(self, tag, value): self._setitem(tag, value, self.legacy_api) def _setitem(self, tag, value, legacy_api): basetypes = (Number, bytes, str) - if not py3: - basetypes += (unicode,) # noqa: F821 info = TiffTags.lookup(tag) values = [value] if isinstance(value, basetypes) else value @@ -558,14 +534,10 @@ class ImageFileDirectory_v2(MutableMapping): elif all(isinstance(v, float) for v in values): self.tagtype[tag] = TiffTags.DOUBLE else: - if py3: - if all(isinstance(v, str) for v in values): - self.tagtype[tag] = TiffTags.ASCII - else: - # Never treat data as binary by default on Python 2. + if all(isinstance(v, str) for v in values): self.tagtype[tag] = TiffTags.ASCII - if self.tagtype[tag] == TiffTags.UNDEFINED and py3: + if self.tagtype[tag] == TiffTags.UNDEFINED: values = [ value.encode("ascii", "replace") if isinstance(value, str) else value ] @@ -685,8 +657,6 @@ class ImageFileDirectory_v2(MutableMapping): @_register_writer(2) def write_string(self, value): # remerge of https://github.com/python-pillow/Pillow/pull/1416 - if sys.version_info.major == 2: - value = value.decode("ascii", "replace") return b"" + value.encode("ascii", "replace") + b"\0" @_register_loader(5, 8) @@ -730,7 +700,7 @@ class ImageFileDirectory_v2(MutableMapping): def _ensure_read(self, fp, size): ret = fp.read(size) if len(ret) != size: - raise IOError( + raise OSError( "Corrupt EXIF data. " + "Expecting to read %d bytes but only got %d. " % (size, len(ret)) ) @@ -764,7 +734,7 @@ class ImageFileDirectory_v2(MutableMapping): (offset,) = self._unpack("L", data) if DEBUG: print( - "Tag Location: %s - Data Location: %s" % (here, offset), + "Tag Location: {} - Data Location: {}".format(here, offset), end=" ", ) fp.seek(offset) @@ -794,7 +764,7 @@ class ImageFileDirectory_v2(MutableMapping): print("- value:", self[tag]) (self.next,) = self._unpack("L", self._ensure_read(fp, 4)) - except IOError as msg: + except OSError as msg: warnings.warn(str(msg)) return @@ -813,7 +783,7 @@ class ImageFileDirectory_v2(MutableMapping): stripoffsets = len(entries) typ = self.tagtype.get(tag) if DEBUG: - print("Tag %s, Type: %s, Value: %s" % (tag, typ, value)) + print("Tag {}, Type: {}, Value: {}".format(tag, typ, value)) values = value if isinstance(value, tuple) else (value,) data = self._write_dispatch[typ](self, *values) if DEBUG: @@ -1050,7 +1020,7 @@ class TiffImageFile(ImageFile.ImageFile): "Seeking to frame %s, on frame %s, __next %s, location: %s" % (frame, self.__frame, self.__next, self.fp.tell()) ) - # reset python3 buffered io handle in case fp + # reset buffered io handle in case fp # was passed to libtiff, invalidating the buffer self.fp.tell() self.fp.seek(self.__next) @@ -1078,7 +1048,7 @@ class TiffImageFile(ImageFile.ImageFile): def load(self): if self.use_load_libtiff: return self._load_libtiff() - return super(TiffImageFile, self).load() + return super().load() def load_end(self): if self._tile_orientation: @@ -1107,14 +1077,14 @@ class TiffImageFile(ImageFile.ImageFile): pixel = Image.Image.load(self) if self.tile is None: - raise IOError("cannot load this image") + raise OSError("cannot load this image") if not self.tile: return pixel self.load_prepare() if not len(self.tile) == 1: - raise IOError("Not exactly one tile") + raise OSError("Not exactly one tile") # (self._compression, (extents tuple), # 0, (rawmode, self._compression, fp)) @@ -1128,11 +1098,11 @@ class TiffImageFile(ImageFile.ImageFile): try: fp = hasattr(self.fp, "fileno") and os.dup(self.fp.fileno()) # flush the file descriptor, prevents error on pypy 2.4+ - # should also eliminate the need for fp.tell for py3 + # should also eliminate the need for fp.tell # in _seek if hasattr(self.fp, "flush"): self.fp.flush() - except IOError: + except OSError: # io.BytesIO have a fileno, but returns an IOError if # it doesn't use a file descriptor. fp = False @@ -1146,7 +1116,7 @@ class TiffImageFile(ImageFile.ImageFile): try: decoder.setimage(self.im, extents) except ValueError: - raise IOError("Couldn't set the image") + raise OSError("Couldn't set the image") close_self_fp = self._exclusive_fp and not self._is_animated if hasattr(self.fp, "getvalue"): @@ -1189,7 +1159,7 @@ class TiffImageFile(ImageFile.ImageFile): self.fp = None # might be shared if err < 0: - raise IOError(err) + raise OSError(err) return Image.Image.load(self) @@ -1197,7 +1167,7 @@ class TiffImageFile(ImageFile.ImageFile): """Setup this image object based on current tags""" if 0xBC01 in self.tag_v2: - raise IOError("Windows Media Photo files not yet supported") + raise OSError("Windows Media Photo files not yet supported") # extract relevant tags self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)] @@ -1439,7 +1409,7 @@ def _save(im, fp, filename): try: rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode] except KeyError: - raise IOError("cannot write mode %s as TIFF" % im.mode) + raise OSError("cannot write mode %s as TIFF" % im.mode) ifd = ImageFileDirectory_v2(prefix=prefix) @@ -1598,13 +1568,10 @@ def _save(im, fp, filename): if tag in ifd.tagtype: types[tag] = ifd.tagtype[tag] - elif not ( - isinstance(value, (int, float, str, bytes)) - or (not py3 and isinstance(value, unicode)) # noqa: F821 - ): + elif not (isinstance(value, (int, float, str, bytes))): continue if tag not in atts and tag not in blocklist: - if isinstance(value, str if py3 else unicode): # noqa: F821 + if isinstance(value, str): atts[tag] = value.encode("ascii", "replace") + b"\0" elif isinstance(value, IFDRational): atts[tag] = float(value) @@ -1637,7 +1604,7 @@ def _save(im, fp, filename): if s: break if s < 0: - raise IOError("encoder error %d when writing image file" % s) + raise OSError("encoder error %d when writing image file" % s) else: offset = ifd.save(fp) @@ -1685,9 +1652,9 @@ class AppendingTiffWriter: self.name = fn self.close_fp = True try: - self.f = io.open(fn, "w+b" if new else "r+b") - except IOError: - self.f = io.open(fn, "w+b") + self.f = open(fn, "w+b" if new else "r+b") + except OSError: + self.f = open(fn, "w+b") self.beginning = self.f.tell() self.setup() @@ -1768,7 +1735,7 @@ class AppendingTiffWriter: # pad to 16 byte boundary padBytes = 16 - pos % 16 if 0 < padBytes < 16: - self.f.write(bytes(bytearray(padBytes))) + self.f.write(bytes(padBytes)) self.offsetOfNewPage = self.f.tell() def setEndian(self, endian): diff --git a/src/PIL/TiffTags.py b/src/PIL/TiffTags.py index c047f42b6..6cc9ff7f3 100644 --- a/src/PIL/TiffTags.py +++ b/src/PIL/TiffTags.py @@ -24,7 +24,7 @@ class TagInfo(namedtuple("_TagInfo", "value name type length enum")): __slots__ = [] def __new__(cls, value=None, name="unknown", type=None, length=None, enum=None): - return super(TagInfo, cls).__new__(cls, value, name, type, length, enum or {}) + return super().__new__(cls, value, name, type, length, enum or {}) def cvt_enum(self, value): # Using get will call hash(value), which can be expensive diff --git a/src/PIL/WalImageFile.py b/src/PIL/WalImageFile.py index e2e1cd4f5..d5a5c8e67 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -1,4 +1,3 @@ -# encoding: utf-8 # # The Python Imaging Library. # $Id$ @@ -21,16 +20,11 @@ # https://www.flipcode.com/archives/Quake_2_BSP_File_Format.shtml # and has been tested with a few sample files found using google. +import builtins + from . import Image from ._binary import i32le as i32 -try: - import builtins -except ImportError: - import __builtin__ - - builtins = __builtin__ - def open(filename): """ diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index 18eda6d18..eda685508 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -105,7 +105,7 @@ class WebPImageFile(ImageFile.ImageFile): def seek(self, frame): if not _webp.HAVE_WEBPANIM: - return super(WebPImageFile, self).seek(frame) + return super().seek(frame) # Perform some simple checks first if frame >= self._n_frames: @@ -168,11 +168,11 @@ class WebPImageFile(ImageFile.ImageFile): self.fp = BytesIO(data) self.tile = [("raw", (0, 0) + self.size, 0, self.rawmode)] - return super(WebPImageFile, self).load() + return super().load() def tell(self): if not _webp.HAVE_WEBPANIM: - return super(WebPImageFile, self).tell() + return super().tell() return self.__logical_frame @@ -233,7 +233,7 @@ def _save_all(im, fp, filename): or len(background) != 4 or not all(v >= 0 and v < 256 for v in background) ): - raise IOError( + raise OSError( "Background color is not an RGBA tuple clamped to (0-255): %s" % str(background) ) @@ -312,7 +312,7 @@ def _save_all(im, fp, filename): # Get the final output from the encoder data = enc.assemble(icc_profile, exif, xmp) if data is None: - raise IOError("cannot write file as WebP (encoder returned None)") + raise OSError("cannot write file as WebP (encoder returned None)") fp.write(data) @@ -346,7 +346,7 @@ def _save(im, fp, filename): xmp, ) if data is None: - raise IOError("cannot write file as WebP (encoder returned None)") + raise OSError("cannot write file as WebP (encoder returned None)") fp.write(data) diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index 416af6fd7..7695a68e7 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -19,21 +19,11 @@ # http://wvware.sourceforge.net/caolan/index.html # http://wvware.sourceforge.net/caolan/ora-wmf.html -from __future__ import print_function - from . import Image, ImageFile from ._binary import i16le as word, i32le as dword, si16le as short, si32le as _long -from ._util import py3 - -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" _handler = None -if py3: - long = int - def register_handler(handler): """ @@ -48,7 +38,7 @@ def register_handler(handler): if hasattr(Image.core, "drawwmf"): # install default handler (windows only) - class WmfHandler(object): + class WmfHandler: def open(self, im): im.mode = "RGB" self.bbox = im.info["wmf_bbox"] @@ -158,7 +148,7 @@ class WmfStubImageFile(ImageFile.StubImageFile): def _save(im, fp, filename): if _handler is None or not hasattr(_handler, "save"): - raise IOError("WMF save handler not installed") + raise OSError("WMF save handler not installed") _handler.save(im, fp, filename) diff --git a/src/PIL/XVThumbImagePlugin.py b/src/PIL/XVThumbImagePlugin.py index aa3536d85..c0d8db09a 100644 --- a/src/PIL/XVThumbImagePlugin.py +++ b/src/PIL/XVThumbImagePlugin.py @@ -20,10 +20,6 @@ from . import Image, ImageFile, ImagePalette from ._binary import i8, o8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.1" - _MAGIC = b"P7 332" # standard color palette for thumbnails (RGB332) diff --git a/src/PIL/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index bc825c3f3..ead9722c8 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -23,10 +23,6 @@ import re from . import Image, ImageFile -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.6" - # XBM header xbm_head = re.compile( br"\s*#define[ \t]+.*_width[ \t]+(?P[0-9]+)[\r\n]+" @@ -73,7 +69,7 @@ class XbmImageFile(ImageFile.ImageFile): def _save(im, fp, filename): if im.mode != "1": - raise IOError("cannot write mode %s as XBM" % im.mode) + raise OSError("cannot write mode %s as XBM" % im.mode) fp.write(("#define im_width %d\n" % im.size[0]).encode("ascii")) fp.write(("#define im_height %d\n" % im.size[1]).encode("ascii")) diff --git a/src/PIL/XpmImagePlugin.py b/src/PIL/XpmImagePlugin.py index 275148827..d8bd00a1b 100644 --- a/src/PIL/XpmImagePlugin.py +++ b/src/PIL/XpmImagePlugin.py @@ -20,10 +20,6 @@ import re from . import Image, ImageFile, ImagePalette from ._binary import i8, o8 -# __version__ is deprecated and will be removed in a future version. Use -# PIL.__version__ instead. -__version__ = "0.2" - # XPM header xpm_head = re.compile(b'"([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)') diff --git a/src/PIL/__init__.py b/src/PIL/__init__.py index fd02b40d9..e7f26488d 100644 --- a/src/PIL/__init__.py +++ b/src/PIL/__init__.py @@ -70,3 +70,7 @@ _plugins = [ "XpmImagePlugin", "XVThumbImagePlugin", ] + + +class UnidentifiedImageError(IOError): + pass diff --git a/src/PIL/_binary.py b/src/PIL/_binary.py index 53b1ca956..529b8c94b 100644 --- a/src/PIL/_binary.py +++ b/src/PIL/_binary.py @@ -13,24 +13,13 @@ from struct import pack, unpack_from -from ._util import py3 -if py3: - - def i8(c): - return c if c.__class__ is int else c[0] - - def o8(i): - return bytes((i & 255,)) +def i8(c): + return c if c.__class__ is int else c[0] -else: - - def i8(c): - return ord(c) - - def o8(i): - return chr(i & 255) +def o8(i): + return bytes((i & 255,)) # Input, le = little endian, be = big endian diff --git a/src/PIL/_tkinter_finder.py b/src/PIL/_tkinter_finder.py index d4f34196e..30493066a 100644 --- a/src/PIL/_tkinter_finder.py +++ b/src/PIL/_tkinter_finder.py @@ -1,11 +1,7 @@ """ Find compiled module linking to Tcl / Tk libraries """ import sys - -if sys.version_info.major > 2: - from tkinter import _tkinter as tk -else: - from Tkinter import tkinter as tk +from tkinter import _tkinter as tk if hasattr(sys, "pypy_find_executable"): # Tested with packages at https://bitbucket.org/pypy/pypy/downloads. diff --git a/src/PIL/_util.py b/src/PIL/_util.py index 59964c7ef..755b4b272 100644 --- a/src/PIL/_util.py +++ b/src/PIL/_util.py @@ -1,33 +1,20 @@ import os import sys -py3 = sys.version_info.major >= 3 py36 = sys.version_info[0:2] >= (3, 6) -if py3: - def isStringType(t): - return isinstance(t, str) +if py36: + from pathlib import Path - if py36: - from pathlib import Path - - def isPath(f): - return isinstance(f, (bytes, str, Path)) - - else: - - def isPath(f): - return isinstance(f, (bytes, str)) + def isPath(f): + return isinstance(f, (bytes, str, Path)) else: - def isStringType(t): - return isinstance(t, basestring) # noqa: F821 - def isPath(f): - return isinstance(f, basestring) # noqa: F821 + return isinstance(f, (bytes, str)) # Checks if an object is a string, and that it points to a directory. @@ -35,7 +22,7 @@ def isDirectory(f): return isPath(f) and os.path.isdir(f) -class deferred_error(object): +class deferred_error: def __init__(self, ex): self.ex = ex diff --git a/src/PIL/features.py b/src/PIL/features.py index 7b007dc56..5822febab 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -1,5 +1,3 @@ -from __future__ import print_function, unicode_literals - import collections import os import sys diff --git a/src/Tk/tkImaging.c b/src/Tk/tkImaging.c index bb0fd33a3..59801f58e 100644 --- a/src/Tk/tkImaging.c +++ b/src/Tk/tkImaging.c @@ -225,11 +225,7 @@ TkImaging_Init(Tcl_Interp* interp) #include /* Must be linked with 'psapi' library */ -#if PY_VERSION_HEX >= 0x03000000 #define TKINTER_PKG "tkinter" -#else -#define TKINTER_PKG "Tkinter" -#endif FARPROC _dfunc(HMODULE lib_handle, const char *func_name) { @@ -354,7 +350,6 @@ int load_tkinter_funcs(void) */ /* From module __file__ attribute to char *string for dlopen. */ -#if PY_VERSION_HEX >= 0x03000000 char *fname2char(PyObject *fname) { PyObject* bytes; @@ -364,9 +359,6 @@ char *fname2char(PyObject *fname) } return PyBytes_AsString(bytes); } -#else -#define fname2char(s) (PyString_AsString(s)) -#endif #include diff --git a/src/_imaging.c b/src/_imaging.c index 81de38e2f..b0cbfc665 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -84,8 +84,6 @@ #include "Imaging.h" -#include "py3.h" - #define _USE_MATH_DEFINES #include @@ -237,45 +235,13 @@ void ImagingSectionLeave(ImagingSectionCookie* cookie) int PyImaging_CheckBuffer(PyObject* buffer) { -#if PY_VERSION_HEX >= 0x03000000 return PyObject_CheckBuffer(buffer); -#else - return PyObject_CheckBuffer(buffer) || PyObject_CheckReadBuffer(buffer); -#endif } int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view) { /* must call check_buffer first! */ -#if PY_VERSION_HEX >= 0x03000000 return PyObject_GetBuffer(buffer, view, PyBUF_SIMPLE); -#else - /* Use new buffer protocol if available - (mmap doesn't support this in 2.7, go figure) */ - if (PyObject_CheckBuffer(buffer)) { - int success = PyObject_GetBuffer(buffer, view, PyBUF_SIMPLE); - if (!success) { return success; } - PyErr_Clear(); - } - - /* Pretend we support the new protocol; PyBuffer_Release happily ignores - calling bf_releasebuffer on objects that don't support it */ - view->buf = NULL; - view->len = 0; - view->readonly = 1; - view->format = NULL; - view->ndim = 0; - view->shape = NULL; - view->strides = NULL; - view->suboffsets = NULL; - view->itemsize = 0; - view->internal = NULL; - - Py_INCREF(buffer); - view->obj = buffer; - - return PyObject_AsReadBuffer(buffer, (void *) &view->buf, &view->len); -#endif } /* -------------------------------------------------------------------- */ @@ -416,11 +382,11 @@ getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type) // on this switch. And 3 fewer loops to copy/paste. switch (type) { case TYPE_UINT8: - itemp = PyInt_AsLong(op); + itemp = PyLong_AsLong(op); list[i] = CLIP8(itemp); break; case TYPE_INT32: - itemp = PyInt_AsLong(op); + itemp = PyLong_AsLong(op); memcpy(list + i * sizeof(INT32), &itemp, sizeof(itemp)); break; case TYPE_FLOAT32: @@ -499,7 +465,7 @@ getpixel(Imaging im, ImagingAccess access, int x, int y) case IMAGING_TYPE_UINT8: switch (im->bands) { case 1: - return PyInt_FromLong(pixel.b[0]); + return PyLong_FromLong(pixel.b[0]); case 2: return Py_BuildValue("BB", pixel.b[0], pixel.b[1]); case 3: @@ -509,12 +475,12 @@ getpixel(Imaging im, ImagingAccess access, int x, int y) } break; case IMAGING_TYPE_INT32: - return PyInt_FromLong(pixel.i); + return PyLong_FromLong(pixel.i); case IMAGING_TYPE_FLOAT32: return PyFloat_FromDouble(pixel.f); case IMAGING_TYPE_SPECIAL: if (strncmp(im->mode, "I;16", 4) == 0) - return PyInt_FromLong(pixel.h); + return PyLong_FromLong(pixel.h); break; } @@ -543,16 +509,8 @@ getink(PyObject* color, Imaging im, char* ink) if (im->type == IMAGING_TYPE_UINT8 || im->type == IMAGING_TYPE_INT32 || im->type == IMAGING_TYPE_SPECIAL) { -#if PY_VERSION_HEX >= 0x03000000 if (PyLong_Check(color)) { r = PyLong_AsLongLong(color); -#else - if (PyInt_Check(color) || PyLong_Check(color)) { - if (PyInt_Check(color)) - r = PyInt_AS_LONG(color); - else - r = PyLong_AsLongLong(color); -#endif rIsInt = 1; } if (r == -1 && PyErr_Occurred()) { @@ -1129,16 +1087,16 @@ _getxy(PyObject* xy, int* x, int *y) goto badarg; value = PyTuple_GET_ITEM(xy, 0); - if (PyInt_Check(value)) - *x = PyInt_AS_LONG(value); + if (PyLong_Check(value)) + *x = PyLong_AS_LONG(value); else if (PyFloat_Check(value)) *x = (int) PyFloat_AS_DOUBLE(value); else goto badval; value = PyTuple_GET_ITEM(xy, 1); - if (PyInt_Check(value)) - *y = PyInt_AS_LONG(value); + if (PyLong_Check(value)) + *y = PyLong_AS_LONG(value); else if (PyFloat_Check(value)) *y = (int) PyFloat_AS_DOUBLE(value); else @@ -1255,7 +1213,7 @@ _histogram(ImagingObject* self, PyObject* args) list = PyList_New(h->bands * 256); for (i = 0; i < h->bands * 256; i++) { PyObject* item; - item = PyInt_FromLong(h->histogram[i]); + item = PyLong_FromLong(h->histogram[i]); if (item == NULL) { Py_DECREF(list); list = NULL; @@ -1524,7 +1482,7 @@ _putdata(ImagingObject* self, PyObject* args) /* Clipped data */ for (i = x = y = 0; i < n; i++) { op = PySequence_Fast_GET_ITEM(seq, i); - image->image8[y][x] = (UINT8) CLIP8(PyInt_AsLong(op)); + image->image8[y][x] = (UINT8) CLIP8(PyLong_AsLong(op)); if (++x >= (int) image->xsize){ x = 0, y++; } @@ -1635,7 +1593,7 @@ _putpalette(ImagingObject* self, PyObject* args) char* rawmode; UINT8* palette; Py_ssize_t palettesize; - if (!PyArg_ParseTuple(args, "s"PY_ARG_BYTES_LENGTH, &rawmode, &palette, &palettesize)) + if (!PyArg_ParseTuple(args, "sy#", &rawmode, &palette, &palettesize)) return NULL; if (strcmp(self->image->mode, "L") && strcmp(self->image->mode, "LA") && @@ -1698,7 +1656,7 @@ _putpalettealphas(ImagingObject* self, PyObject* args) int i; UINT8 *values; Py_ssize_t length; - if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH, &values, &length)) + if (!PyArg_ParseTuple(args, "y#", &values, &length)) return NULL; if (!self->image->palette) { @@ -2136,7 +2094,7 @@ _getprojection(ImagingObject* self, PyObject* args) ImagingGetProjection(self->image, (unsigned char *)xprofile, (unsigned char *)yprofile); - result = Py_BuildValue(PY_ARG_BYTES_LENGTH PY_ARG_BYTES_LENGTH, + result = Py_BuildValue("y#y#", xprofile, (Py_ssize_t)self->image->xsize, yprofile, (Py_ssize_t)self->image->ysize); @@ -2414,7 +2372,7 @@ _font_new(PyObject* self_, PyObject* args) ImagingObject* imagep; unsigned char* glyphdata; Py_ssize_t glyphdata_length; - if (!PyArg_ParseTuple(args, "O!"PY_ARG_BYTES_LENGTH, + if (!PyArg_ParseTuple(args, "O!y#", &Imaging_Type, &imagep, &glyphdata, &glyphdata_length)) return NULL; @@ -2648,7 +2606,7 @@ _draw_ink(ImagingDrawObject* self, PyObject* args) if (!getink(color, self->image->image, (char*) &ink)) return NULL; - return PyInt_FromLong((int) ink); + return PyLong_FromLong((int) ink); } static PyObject* @@ -3356,13 +3314,13 @@ _getattr_size(ImagingObject* self, void* closure) static PyObject* _getattr_bands(ImagingObject* self, void* closure) { - return PyInt_FromLong(self->image->bands); + return PyLong_FromLong(self->image->bands); } static PyObject* _getattr_id(ImagingObject* self, void* closure) { - return PyInt_FromSsize_t((Py_ssize_t) self->image); + return PyLong_FromSsize_t((Py_ssize_t) self->image); } static PyObject* @@ -3575,17 +3533,17 @@ _get_stats(PyObject* self, PyObject* args) if ( ! d) return NULL; PyDict_SetItemString(d, "new_count", - PyInt_FromLong(arena->stats_new_count)); + PyLong_FromLong(arena->stats_new_count)); PyDict_SetItemString(d, "allocated_blocks", - PyInt_FromLong(arena->stats_allocated_blocks)); + PyLong_FromLong(arena->stats_allocated_blocks)); PyDict_SetItemString(d, "reused_blocks", - PyInt_FromLong(arena->stats_reused_blocks)); + PyLong_FromLong(arena->stats_reused_blocks)); PyDict_SetItemString(d, "reallocated_blocks", - PyInt_FromLong(arena->stats_reallocated_blocks)); + PyLong_FromLong(arena->stats_reallocated_blocks)); PyDict_SetItemString(d, "freed_blocks", - PyInt_FromLong(arena->stats_freed_blocks)); + PyLong_FromLong(arena->stats_freed_blocks)); PyDict_SetItemString(d, "blocks_cached", - PyInt_FromLong(arena->blocks_cached)); + PyLong_FromLong(arena->blocks_cached)); return d; } @@ -3613,7 +3571,7 @@ _get_alignment(PyObject* self, PyObject* args) if (!PyArg_ParseTuple(args, ":get_alignment")) return NULL; - return PyInt_FromLong(ImagingDefaultArena.alignment); + return PyLong_FromLong(ImagingDefaultArena.alignment); } static PyObject* @@ -3622,7 +3580,7 @@ _get_block_size(PyObject* self, PyObject* args) if (!PyArg_ParseTuple(args, ":get_block_size")) return NULL; - return PyInt_FromLong(ImagingDefaultArena.block_size); + return PyLong_FromLong(ImagingDefaultArena.block_size); } static PyObject* @@ -3631,7 +3589,7 @@ _get_blocks_max(PyObject* self, PyObject* args) if (!PyArg_ParseTuple(args, ":get_blocks_max")) return NULL; - return PyInt_FromLong(ImagingDefaultArena.blocks_max); + return PyLong_FromLong(ImagingDefaultArena.blocks_max); } static PyObject* @@ -3965,7 +3923,6 @@ setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imaging(void) { PyObject* m; @@ -3985,11 +3942,3 @@ PyInit__imaging(void) { return m; } -#else -PyMODINIT_FUNC -init_imaging(void) -{ - PyObject* m = Py_InitModule("_imaging", functions); - setup_module(m); -} -#endif diff --git a/src/_imagingcms.c b/src/_imagingcms.c index 2c9f3aa68..0b22ab695 100644 --- a/src/_imagingcms.c +++ b/src/_imagingcms.c @@ -32,7 +32,6 @@ http://www.cazabon.com\n\ #include "lcms2.h" #include "Imaging.h" -#include "py3.h" #define PYCMSVERSION "1.0.0 pil" @@ -122,13 +121,8 @@ cms_profile_fromstring(PyObject* self, PyObject* args) char* pProfile; Py_ssize_t nProfile; -#if PY_VERSION_HEX >= 0x03000000 if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile)) return NULL; -#else - if (!PyArg_ParseTuple(args, "s#:profile_fromstring", &pProfile, &nProfile)) - return NULL; -#endif hProfile = cmsOpenProfileFromMem(pProfile, nProfile); if (!hProfile) { @@ -172,11 +166,7 @@ cms_profile_tobytes(PyObject* self, PyObject* args) return NULL; } -#if PY_VERSION_HEX >= 0x03000000 ret = PyBytes_FromStringAndSize(pProfile, (Py_ssize_t)nProfile); -#else - ret = PyString_FromStringAndSize(pProfile, (Py_ssize_t)nProfile); -#endif free(pProfile); return ret; @@ -592,7 +582,7 @@ cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args) /* printf("cmsIsIntentSupported(%p, %d, %d) => %d\n", self->profile, intent, direction, result); */ - return PyInt_FromLong(result != 0); + return PyLong_FromLong(result != 0); } #ifdef _WIN32 @@ -691,11 +681,7 @@ _profile_read_int_as_string(cmsUInt32Number nr) buf[3] = (char) (nr & 0xff); buf[4] = 0; -#if PY_VERSION_HEX >= 0x03000000 ret = PyUnicode_DecodeASCII(buf, 4, NULL); -#else - ret = PyString_FromStringAndSize(buf, 4); -#endif return ret; } @@ -898,7 +884,7 @@ _is_intent_supported(CmsProfileObject* self, int clut) || intent == INTENT_SATURATION || intent == INTENT_ABSOLUTE_COLORIMETRIC)) continue; - id = PyInt_FromLong((long) intent); + id = PyLong_FromLong((long) intent); entry = Py_BuildValue("(OOO)", _check_intent(clut, self->profile, intent, LCMS_USED_AS_INPUT) ? Py_True : Py_False, _check_intent(clut, self->profile, intent, LCMS_USED_AS_OUTPUT) ? Py_True : Py_False, @@ -1010,7 +996,7 @@ cms_profile_getattr_product_copyright(CmsProfileObject* self, void* closure) static PyObject* cms_profile_getattr_rendering_intent(CmsProfileObject* self, void* closure) { - return PyInt_FromLong(cmsGetHeaderRenderingIntent(self->profile)); + return PyLong_FromLong(cmsGetHeaderRenderingIntent(self->profile)); } static PyObject* @@ -1098,7 +1084,7 @@ cms_profile_getattr_version(CmsProfileObject* self, void* closure) static PyObject* cms_profile_getattr_icc_version(CmsProfileObject* self, void* closure) { - return PyInt_FromLong((long) cmsGetEncodedICCversion(self->profile)); + return PyLong_FromLong((long) cmsGetEncodedICCversion(self->profile)); } static PyObject* @@ -1115,7 +1101,7 @@ static PyObject* cms_profile_getattr_header_flags(CmsProfileObject* self, void* closure) { cmsUInt32Number flags = cmsGetHeaderFlags(self->profile); - return PyInt_FromLong(flags); + return PyLong_FromLong(flags); } static PyObject* @@ -1611,7 +1597,6 @@ setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingcms(void) { PyObject* m; @@ -1633,12 +1618,3 @@ PyInit__imagingcms(void) { return m; } -#else -PyMODINIT_FUNC -init_imagingcms(void) -{ - PyObject *m = Py_InitModule("_imagingcms", pyCMSdll_methods); - setup_module(m); - PyDateTime_IMPORT; -} -#endif diff --git a/src/_imagingft.c b/src/_imagingft.c index 146df095b..62a4c283e 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -30,7 +30,6 @@ #include FT_SFNT_NAMES_H #define KEEP_PY_UNICODE -#include "py3.h" #if !defined(_MSC_VER) #include @@ -266,8 +265,7 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kw, "etn|ns"PY_ARG_BYTES_LENGTH"n", - kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kw, "etn|nsy#n", kwlist, Py_FileSystemDefaultEncoding, &filename, &size, &index, &encoding, &font_bytes, &font_bytes_size, &layout_engine)) { @@ -328,34 +326,12 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) static int font_getchar(PyObject* string, int index, FT_ULong* char_out) { -#if (PY_VERSION_HEX < 0x03030000) || (defined(PYPY_VERSION_NUM)) - if (PyUnicode_Check(string)) { - Py_UNICODE* p = PyUnicode_AS_UNICODE(string); - int size = PyUnicode_GET_SIZE(string); - if (index >= size) - return 0; - *char_out = p[index]; - return 1; - } -#if PY_VERSION_HEX < 0x03000000 - if (PyString_Check(string)) { - unsigned char* p = (unsigned char*) PyString_AS_STRING(string); - int size = PyString_GET_SIZE(string); - if (index >= size) - return 0; - *char_out = (unsigned char) p[index]; - return 1; - } -#endif -#else if (PyUnicode_Check(string)) { if (index >= PyUnicode_GET_LENGTH(string)) return 0; *char_out = PyUnicode_READ_CHAR(string, index); return 1; } -#endif - return 0; } @@ -375,7 +351,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * goto failed; } -#if (PY_VERSION_HEX < 0x03030000) || (defined(PYPY_VERSION_NUM)) +#if (defined(PYPY_VERSION_NUM) && (PYPY_VERSION_NUM < 0x07020000)) if (PyUnicode_Check(string)) { Py_UNICODE *text = PyUnicode_AS_UNICODE(string); Py_ssize_t size = PyUnicode_GET_SIZE(string); @@ -395,25 +371,6 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * } } } -#if PY_VERSION_HEX < 0x03000000 - else if (PyString_Check(string)) { - char *text = PyString_AS_STRING(string); - int size = PyString_GET_SIZE(string); - if (! size) { - goto failed; - } - if (!(*p_raqm.set_text_utf8)(rq, text, size)) { - PyErr_SetString(PyExc_ValueError, "raqm_set_text_utf8() failed"); - goto failed; - } - if (lang) { - if (!(*p_raqm.set_language)(rq, lang, start, size)) { - PyErr_SetString(PyExc_ValueError, "raqm_set_language() failed"); - goto failed; - } - } - } -#endif #else if (PyUnicode_Check(string)) { Py_UCS4 *text = PyUnicode_AsUCS4Copy(string); @@ -423,7 +380,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * and raqm fails with empty strings */ goto failed; } - int set_text = (*p_raqm.set_text)(rq, (const uint32_t *)(text), size); + int set_text = (*p_raqm.set_text)(rq, text, size); PyMem_Free(text); if (!set_text) { PyErr_SetString(PyExc_ValueError, "raqm_set_text() failed"); @@ -479,11 +436,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * Py_ssize_t size = 0; PyObject *bytes; -#if PY_VERSION_HEX >= 0x03000000 if (!PyUnicode_Check(item)) { -#else - if (!PyUnicode_Check(item) && !PyString_Check(item)) { -#endif PyErr_SetString(PyExc_TypeError, "expected a string"); goto failed; } @@ -495,12 +448,6 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * feature = PyBytes_AS_STRING(bytes); size = PyBytes_GET_SIZE(bytes); } -#if PY_VERSION_HEX < 0x03000000 - else { - feature = PyString_AsString(item); - size = PyString_GET_SIZE(item); - } -#endif if (!(*p_raqm.add_font_feature)(rq, feature, size)) { PyErr_SetString(PyExc_ValueError, "raqm_add_font_feature() failed"); goto failed; @@ -581,11 +528,7 @@ text_layout_fallback(PyObject* string, FontObject* self, const char* dir, PyObje if (features != Py_None || dir != NULL || lang != NULL) { PyErr_SetString(PyExc_KeyError, "setting text direction, language or font features is not supported without libraqm"); } -#if PY_VERSION_HEX >= 0x03000000 if (!PyUnicode_Check(string)) { -#else - if (!PyUnicode_Check(string) && !PyString_Check(string)) { -#endif PyErr_SetString(PyExc_TypeError, "expected string"); return 0; } @@ -991,8 +934,7 @@ font_render(FontObject* self, PyObject* args) continue; if (master->namedstyle[j].strid == name.name_id) { - list_name = Py_BuildValue(PY_ARG_BYTES_LENGTH, - name.string, name.string_len); + list_name = Py_BuildValue("y#", name.string, name.string_len); PyList_SetItem(list_names, j, list_name); break; } @@ -1026,11 +968,11 @@ font_render(FontObject* self, PyObject* args) list_axis = PyDict_New(); PyDict_SetItemString(list_axis, "minimum", - PyInt_FromLong(axis.minimum / 65536)); + PyLong_FromLong(axis.minimum / 65536)); PyDict_SetItemString(list_axis, "default", - PyInt_FromLong(axis.def / 65536)); + PyLong_FromLong(axis.def / 65536)); PyDict_SetItemString(list_axis, "maximum", - PyInt_FromLong(axis.maximum / 65536)); + PyLong_FromLong(axis.maximum / 65536)); for (j = 0; j < name_count; j++) { error = FT_Get_Sfnt_Name(self->face, j, &name); @@ -1038,8 +980,7 @@ font_render(FontObject* self, PyObject* args) return geterror(error); if (name.name_id == axis.strid) { - axis_name = Py_BuildValue(PY_ARG_BYTES_LENGTH, - name.string, name.string_len); + axis_name = Py_BuildValue("y#", name.string, name.string_len); PyDict_SetItemString(list_axis, "name", axis_name); break; } @@ -1096,8 +1037,8 @@ font_render(FontObject* self, PyObject* args) item = PyList_GET_ITEM(axes, i); if (PyFloat_Check(item)) coord = PyFloat_AS_DOUBLE(item); - else if (PyInt_Check(item)) - coord = (float) PyInt_AS_LONG(item); + else if (PyLong_Check(item)) + coord = (float) PyLong_AS_LONG(item); else if (PyNumber_Check(item)) coord = PyFloat_AsDouble(item); else { @@ -1147,64 +1088,54 @@ static PyMethodDef font_methods[] = { static PyObject* font_getattr_family(FontObject* self, void* closure) { -#if PY_VERSION_HEX >= 0x03000000 if (self->face->family_name) return PyUnicode_FromString(self->face->family_name); -#else - if (self->face->family_name) - return PyString_FromString(self->face->family_name); -#endif Py_RETURN_NONE; } static PyObject* font_getattr_style(FontObject* self, void* closure) { -#if PY_VERSION_HEX >= 0x03000000 if (self->face->style_name) return PyUnicode_FromString(self->face->style_name); -#else - if (self->face->style_name) - return PyString_FromString(self->face->style_name); -#endif Py_RETURN_NONE; } static PyObject* font_getattr_ascent(FontObject* self, void* closure) { - return PyInt_FromLong(PIXEL(self->face->size->metrics.ascender)); + return PyLong_FromLong(PIXEL(self->face->size->metrics.ascender)); } static PyObject* font_getattr_descent(FontObject* self, void* closure) { - return PyInt_FromLong(-PIXEL(self->face->size->metrics.descender)); + return PyLong_FromLong(-PIXEL(self->face->size->metrics.descender)); } static PyObject* font_getattr_height(FontObject* self, void* closure) { - return PyInt_FromLong(PIXEL(self->face->size->metrics.height)); + return PyLong_FromLong(PIXEL(self->face->size->metrics.height)); } static PyObject* font_getattr_x_ppem(FontObject* self, void* closure) { - return PyInt_FromLong(self->face->size->metrics.x_ppem); + return PyLong_FromLong(self->face->size->metrics.x_ppem); } static PyObject* font_getattr_y_ppem(FontObject* self, void* closure) { - return PyInt_FromLong(self->face->size->metrics.y_ppem); + return PyLong_FromLong(self->face->size->metrics.y_ppem); } static PyObject* font_getattr_glyphs(FontObject* self, void* closure) { - return PyInt_FromLong(self->face->num_glyphs); + return PyLong_FromLong(self->face->num_glyphs); } static struct PyGetSetDef font_getsetters[] = { @@ -1272,11 +1203,7 @@ setup_module(PyObject* m) { FT_Library_Version(library, &major, &minor, &patch); -#if PY_VERSION_HEX >= 0x03000000 v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch); -#else - v = PyString_FromFormat("%d.%d.%d", major, minor, patch); -#endif PyDict_SetItemString(d, "freetype2_version", v); @@ -1287,7 +1214,6 @@ setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingft(void) { PyObject* m; @@ -1307,12 +1233,3 @@ PyInit__imagingft(void) { return m; } -#else -PyMODINIT_FUNC -init_imagingft(void) -{ - PyObject* m = Py_InitModule("_imagingft", _functions); - setup_module(m); -} -#endif - diff --git a/src/_imagingmath.c b/src/_imagingmath.c index ea9f103c6..bc66a581a 100644 --- a/src/_imagingmath.c +++ b/src/_imagingmath.c @@ -16,7 +16,6 @@ #include "Python.h" #include "Imaging.h" -#include "py3.h" #include "math.h" #include "float.h" @@ -215,7 +214,7 @@ static PyMethodDef _functions[] = { static void install(PyObject *d, char* name, void* value) { - PyObject *v = PyInt_FromSsize_t((Py_ssize_t) value); + PyObject *v = PyLong_FromSsize_t((Py_ssize_t) value); if (!v || PyDict_SetItemString(d, name, v)) PyErr_Clear(); Py_XDECREF(v); @@ -273,7 +272,6 @@ setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingmath(void) { PyObject* m; @@ -293,12 +291,3 @@ PyInit__imagingmath(void) { return m; } -#else -PyMODINIT_FUNC -init_imagingmath(void) -{ - PyObject* m = Py_InitModule("_imagingmath", _functions); - setup_module(m); -} -#endif - diff --git a/src/_imagingmorph.c b/src/_imagingmorph.c index fc8f246cc..050ae9f02 100644 --- a/src/_imagingmorph.c +++ b/src/_imagingmorph.c @@ -13,7 +13,6 @@ #include "Python.h" #include "Imaging.h" -#include "py3.h" #define LUT_SIZE (1<<9) @@ -273,7 +272,6 @@ static PyMethodDef functions[] = { {NULL, NULL, 0, NULL} }; -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingmorph(void) { PyObject* m; @@ -293,12 +291,3 @@ PyInit__imagingmorph(void) { return m; } -#else -PyMODINIT_FUNC -init_imagingmorph(void) -{ - PyObject* m = Py_InitModule("_imagingmorph", functions); - setup_module(m); -} -#endif - diff --git a/src/_imagingtk.c b/src/_imagingtk.c index d0295f317..bdf5e68d1 100644 --- a/src/_imagingtk.c +++ b/src/_imagingtk.c @@ -64,7 +64,6 @@ static PyMethodDef functions[] = { {NULL, NULL} /* sentinel */ }; -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingtk(void) { static PyModuleDef module_def = { @@ -78,12 +77,3 @@ PyInit__imagingtk(void) { m = PyModule_Create(&module_def); return (load_tkinter_funcs() == 0) ? m : NULL; } -#else -PyMODINIT_FUNC -init_imagingtk(void) -{ - Py_InitModule("_imagingtk", functions); - load_tkinter_funcs(); -} -#endif - diff --git a/src/_webp.c b/src/_webp.c index 66b6d3268..4581ef89d 100644 --- a/src/_webp.c +++ b/src/_webp.c @@ -1,7 +1,6 @@ #define PY_SSIZE_T_CLEAN #include #include "Imaging.h" -#include "py3.h" #include #include #include @@ -557,7 +556,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) Py_ssize_t xmp_size; size_t ret_size; - if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH"iiifss#s#s#", + if (!PyArg_ParseTuple(args, "y#iiifss#s#s#", (char**)&rgb, &size, &width, &height, &lossless, &quality_factor, &mode, &icc_bytes, &icc_size, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) { return NULL; @@ -754,11 +753,7 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) config.output.u.YUVA.y_size); } -#if PY_VERSION_HEX >= 0x03000000 pymode = PyUnicode_FromString(mode); -#else - pymode = PyString_FromString(mode); -#endif ret = Py_BuildValue("SiiSSS", bytes, config.output.width, config.output.height, pymode, NULL == icc_profile ? Py_None : icc_profile, @@ -848,7 +843,6 @@ static int setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__webp(void) { PyObject* m; @@ -867,11 +861,3 @@ PyInit__webp(void) { return m; } -#else -PyMODINIT_FUNC -init_webp(void) -{ - PyObject* m = Py_InitModule("_webp", webpMethods); - setup_module(m); -} -#endif diff --git a/src/decode.c b/src/decode.c index 79133f48f..5ab6ca9d1 100644 --- a/src/decode.c +++ b/src/decode.c @@ -33,7 +33,6 @@ #include "Python.h" #include "Imaging.h" -#include "py3.h" #include "Gif.h" #include "Raw.h" @@ -122,7 +121,7 @@ _decode(ImagingDecoderObject* decoder, PyObject* args) int status; ImagingSectionCookie cookie; - if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH, &buffer, &bufsize)) + if (!PyArg_ParseTuple(args, "y#", &buffer, &bufsize)) return NULL; if (!decoder->pulls_fd) { diff --git a/src/display.c b/src/display.c index efabf1c86..4c2faf9e0 100644 --- a/src/display.c +++ b/src/display.c @@ -26,7 +26,6 @@ #include "Python.h" #include "Imaging.h" -#include "py3.h" /* -------------------------------------------------------------------- */ /* Windows DIB support */ @@ -187,13 +186,8 @@ _frombytes(ImagingDisplayObject* display, PyObject* args) char* ptr; int bytes; -#if PY_VERSION_HEX >= 0x03000000 if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes)) return NULL; -#else - if (!PyArg_ParseTuple(args, "s#:fromstring", &ptr, &bytes)) - return NULL; -#endif if (display->dib->ysize * display->dib->linesize != bytes) { PyErr_SetString(PyExc_ValueError, "wrong size"); @@ -209,13 +203,8 @@ _frombytes(ImagingDisplayObject* display, PyObject* args) static PyObject* _tobytes(ImagingDisplayObject* display, PyObject* args) { -#if PY_VERSION_HEX >= 0x03000000 if (!PyArg_ParseTuple(args, ":tobytes")) return NULL; -#else - if (!PyArg_ParseTuple(args, ":tostring")) - return NULL; -#endif return PyBytes_FromStringAndSize( display->dib->bits, display->dib->ysize * display->dib->linesize @@ -741,7 +730,7 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args) int datasize; int width, height; int x0, y0, x1, y1; - if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH"(ii)(iiii):_load", &data, &datasize, + if (!PyArg_ParseTuple(args, "y#(ii)(iiii):_load", &data, &datasize, &width, &height, &x0, &x1, &y0, &y1)) return NULL; diff --git a/src/encode.c b/src/encode.c index 7dc1035c4..41ba124c4 100644 --- a/src/encode.c +++ b/src/encode.c @@ -26,7 +26,6 @@ #include "Python.h" #include "Imaging.h" -#include "py3.h" #include "Gif.h" #ifdef HAVE_UNISTD_H @@ -567,7 +566,7 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) Py_ssize_t compress_type = -1; char* dictionary = NULL; Py_ssize_t dictionary_size = 0; - if (!PyArg_ParseTuple(args, "ss|nnn"PY_ARG_BYTES_LENGTH, &mode, &rawmode, + if (!PyArg_ParseTuple(args, "ss|nnny#", &mode, &rawmode, &optimize, &compress_level, &compress_type, &dictionary, &dictionary_size)) @@ -693,7 +692,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) item = PyList_GetItem(tags, pos); // We already checked that tags is a 2-tuple list. key = PyTuple_GetItem(item, 0); - key_int = (int)PyInt_AsLong(key); + key_int = (int)PyLong_AsLong(key); value = PyTuple_GetItem(item, 1); status = 0; is_core_tag = 0; @@ -710,7 +709,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) if (!is_core_tag) { PyObject *tag_type = PyDict_GetItem(types, key); if (tag_type) { - int type_int = PyInt_AsLong(tag_type); + int type_int = PyLong_AsLong(tag_type); if (type_int >= TIFF_BYTE && type_int <= TIFF_DOUBLE) { type = (TIFFDataType)type_int; } @@ -721,7 +720,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) if (type == TIFF_NOTYPE) { // Autodetect type. Types should not be changed for backwards // compatibility. - if (PyInt_Check(value)) { + if (PyLong_Check(value)) { type = TIFF_LONG; } else if (PyFloat_Check(value)) { type = TIFF_DOUBLE; @@ -749,7 +748,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) if (type == TIFF_NOTYPE) { // Autodetect type based on first item. Types should not be // changed for backwards compatibility. - if (PyInt_Check(PyTuple_GetItem(value,0))) { + if (PyLong_Check(PyTuple_GetItem(value,0))) { type = TIFF_LONG; } else if (PyFloat_Check(PyTuple_GetItem(value,0))) { type = TIFF_FLOAT; @@ -775,7 +774,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) av = calloc(len, sizeof(UINT8)); if (av) { for (i=0;istate, (ttag_t) key_int, len, av); free(av); @@ -786,7 +785,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) av = calloc(len, sizeof(UINT16)); if (av) { for (i=0;istate, (ttag_t) key_int, len, av); free(av); @@ -797,7 +796,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) av = calloc(len, sizeof(UINT32)); if (av) { for (i=0;istate, (ttag_t) key_int, len, av); free(av); @@ -808,7 +807,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) av = calloc(len, sizeof(INT8)); if (av) { for (i=0;istate, (ttag_t) key_int, len, av); free(av); @@ -819,7 +818,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) av = calloc(len, sizeof(INT16)); if (av) { for (i=0;istate, (ttag_t) key_int, len, av); free(av); @@ -830,7 +829,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) av = calloc(len, sizeof(INT32)); if (av) { for (i=0;istate, (ttag_t) key_int, len, av); free(av); @@ -862,19 +861,19 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) if (type == TIFF_SHORT) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, - (UINT16)PyInt_AsLong(value)); + (UINT16)PyLong_AsLong(value)); } else if (type == TIFF_LONG) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, - (UINT32)PyInt_AsLong(value)); + (UINT32)PyLong_AsLong(value)); } else if (type == TIFF_SSHORT) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, - (INT16)PyInt_AsLong(value)); + (INT16)PyLong_AsLong(value)); } else if (type == TIFF_SLONG) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, - (INT32)PyInt_AsLong(value)); + (INT32)PyLong_AsLong(value)); } else if (type == TIFF_FLOAT) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, @@ -886,11 +885,11 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) } else if (type == TIFF_BYTE) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, - (UINT8)PyInt_AsLong(value)); + (UINT8)PyLong_AsLong(value)); } else if (type == TIFF_SBYTE) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, - (INT8)PyInt_AsLong(value)); + (INT8)PyLong_AsLong(value)); } else if (type == TIFF_ASCII) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, @@ -984,7 +983,7 @@ static unsigned int* get_qtables_arrays(PyObject* qtables, int* qtablesLen) { } table_data = PySequence_Fast(table, "expected a sequence"); for (j = 0; j < DCTSIZE2; j++) { - qarrays[i * DCTSIZE2 + j] = PyInt_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j)); + qarrays[i * DCTSIZE2 + j] = PyLong_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j)); } Py_DECREF(table_data); } @@ -1024,7 +1023,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) char* rawExif = NULL; Py_ssize_t rawExifLen = 0; - if (!PyArg_ParseTuple(args, "ss|nnnnnnnnO"PY_ARG_BYTES_LENGTH""PY_ARG_BYTES_LENGTH, + if (!PyArg_ParseTuple(args, "ss|nnnnnnnnOy#y#", &mode, &rawmode, &quality, &progressive, &smooth, &optimize, &streamtype, &xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size, @@ -1109,8 +1108,8 @@ j2k_decode_coord_tuple(PyObject *tuple, int *x, int *y) *x = *y = 0; if (tuple && PyTuple_Check(tuple) && PyTuple_GET_SIZE(tuple) == 2) { - *x = (int)PyInt_AsLong(PyTuple_GET_ITEM(tuple, 0)); - *y = (int)PyInt_AsLong(PyTuple_GET_ITEM(tuple, 1)); + *x = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0)); + *y = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1)); if (*x < 0) *x = 0; diff --git a/src/libImaging/codec_fd.c b/src/libImaging/codec_fd.c index 7bd4dadf8..5cde31cdc 100644 --- a/src/libImaging/codec_fd.c +++ b/src/libImaging/codec_fd.c @@ -1,6 +1,5 @@ #include "Python.h" #include "Imaging.h" -#include "../py3.h" Py_ssize_t @@ -72,7 +71,7 @@ _imaging_tell_pyFd(PyObject *fd) Py_ssize_t location; result = PyObject_CallMethod(fd, "tell", NULL); - location = PyInt_AsSsize_t(result); + location = PyLong_AsSsize_t(result); Py_DECREF(result); return location; diff --git a/src/map.c b/src/map.c index 099bb4b3e..a8fb69c6e 100644 --- a/src/map.c +++ b/src/map.c @@ -22,8 +22,6 @@ #include "Imaging.h" -#include "py3.h" - /* compatibility wrappers (defined in _imaging.c) */ extern int PyImaging_CheckBuffer(PyObject* buffer); extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view); diff --git a/src/path.c b/src/path.c index 5f0541b0b..f69755d16 100644 --- a/src/path.c +++ b/src/path.c @@ -31,8 +31,6 @@ #include -#include "py3.h" - /* compatibility wrappers (defined in _imaging.c) */ extern int PyImaging_CheckBuffer(PyObject* buffer); extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view); @@ -170,8 +168,8 @@ PyPath_Flatten(PyObject* data, double **pxy) PyObject *op = PyList_GET_ITEM(data, i); if (PyFloat_Check(op)) xy[j++] = PyFloat_AS_DOUBLE(op); - else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); + else if (PyLong_Check(op)) + xy[j++] = (float) PyLong_AS_LONG(op); else if (PyNumber_Check(op)) xy[j++] = PyFloat_AsDouble(op); else if (PyArg_ParseTuple(op, "dd", &x, &y)) { @@ -188,8 +186,8 @@ PyPath_Flatten(PyObject* data, double **pxy) PyObject *op = PyTuple_GET_ITEM(data, i); if (PyFloat_Check(op)) xy[j++] = PyFloat_AS_DOUBLE(op); - else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); + else if (PyLong_Check(op)) + xy[j++] = (float) PyLong_AS_LONG(op); else if (PyNumber_Check(op)) xy[j++] = PyFloat_AsDouble(op); else if (PyArg_ParseTuple(op, "dd", &x, &y)) { @@ -217,8 +215,8 @@ PyPath_Flatten(PyObject* data, double **pxy) } if (PyFloat_Check(op)) xy[j++] = PyFloat_AS_DOUBLE(op); - else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); + else if (PyLong_Check(op)) + xy[j++] = (float) PyLong_AS_LONG(op); else if (PyNumber_Check(op)) xy[j++] = PyFloat_AsDouble(op); else if (PyArg_ParseTuple(op, "dd", &x, &y)) { @@ -552,13 +550,8 @@ path_subscript(PyPathObject* self, PyObject* item) { int len = 4; Py_ssize_t start, stop, step, slicelength; -#if PY_VERSION_HEX >= 0x03020000 if (PySlice_GetIndicesEx(item, len, &start, &stop, &step, &slicelength) < 0) return NULL; -#else - if (PySlice_GetIndicesEx((PySliceObject*)item, len, &start, &stop, &step, &slicelength) < 0) - return NULL; -#endif if (slicelength <= 0) { double *xy = alloc_array(0); diff --git a/src/py3.h b/src/py3.h deleted file mode 100644 index 310583845..000000000 --- a/src/py3.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Python3 definition file to consistently map the code to Python 2 or - Python 3. - - PyInt and PyLong were merged into PyLong in Python 3, so all PyInt functions - are mapped to PyLong. - - PyString, on the other hand, was split into PyBytes and PyUnicode. We map - both back onto PyString, so use PyBytes or PyUnicode where appropriate. The - only exception to this is _imagingft.c, where PyUnicode is left alone. -*/ - -#if PY_VERSION_HEX >= 0x03000000 -#define PY_ARG_BYTES_LENGTH "y#" - -/* Map PyInt -> PyLong */ -#define PyInt_AsLong PyLong_AsLong -#define PyInt_Check PyLong_Check -#define PyInt_FromLong PyLong_FromLong -#define PyInt_AS_LONG PyLong_AS_LONG -#define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_AsSsize_t PyLong_AsSsize_t - -#else /* PY_VERSION_HEX < 0x03000000 */ -#define PY_ARG_BYTES_LENGTH "s#" - -#if !defined(KEEP_PY_UNICODE) -/* Map PyUnicode -> PyString */ -#undef PyUnicode_AsString -#undef PyUnicode_AS_STRING -#undef PyUnicode_Check -#undef PyUnicode_FromStringAndSize -#undef PyUnicode_FromString -#undef PyUnicode_FromFormat -#undef PyUnicode_DecodeFSDefault - -#define PyUnicode_AsString PyString_AsString -#define PyUnicode_AS_STRING PyString_AS_STRING -#define PyUnicode_Check PyString_Check -#define PyUnicode_FromStringAndSize PyString_FromStringAndSize -#define PyUnicode_FromString PyString_FromString -#define PyUnicode_FromFormat PyString_FromFormat -#define PyUnicode_DecodeFSDefault PyString_FromString -#endif - -/* Map PyBytes -> PyString */ -#define PyBytesObject PyStringObject -#define PyBytes_AsString PyString_AsString -#define PyBytes_AS_STRING PyString_AS_STRING -#define PyBytes_Check PyString_Check -#define PyBytes_AsStringAndSize PyString_AsStringAndSize -#define PyBytes_FromStringAndSize PyString_FromStringAndSize -#define PyBytes_FromString PyString_FromString -#define _PyBytes_Resize _PyString_Resize - -#endif /* PY_VERSION_HEX < 0x03000000 */ diff --git a/tox.ini b/tox.ini index 3da68ba7b..07d75be64 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,7 @@ [tox] envlist = lint - py{27,35,36,37,38,py3} + py{35,36,37,38,py3} minversion = 1.9 [testenv] @@ -24,7 +24,7 @@ deps = [testenv:lint] commands = - black --check --diff . + black --target-version py35 --check --diff . flake8 --statistics --count isort --check-only --diff check-manifest diff --git a/winbuild/appveyor_install_msys2_deps.sh b/winbuild/appveyor_install_msys2_deps.sh index 02b75e210..4cc01082d 100644 --- a/winbuild/appveyor_install_msys2_deps.sh +++ b/winbuild/appveyor_install_msys2_deps.sh @@ -2,15 +2,11 @@ mkdir /var/cache/pacman/pkg pacman -S --noconfirm mingw32/mingw-w64-i686-python3-pip \ - mingw32/mingw-w64-i686-python3-setuptools \ - mingw32/mingw-w64-i686-python3-pytest \ - mingw32/mingw-w64-i686-python3-pytest-cov \ - mingw32/mingw-w64-i686-python2-pip \ - mingw32/mingw-w64-i686-python2-setuptools \ - mingw32/mingw-w64-i686-python2-pytest \ - mingw32/mingw-w64-i686-python2-pytest-cov \ - mingw-w64-i686-libjpeg-turbo \ - mingw-w64-i686-libimagequant + mingw32/mingw-w64-i686-python3-setuptools \ + mingw32/mingw-w64-i686-python3-pytest \ + mingw32/mingw-w64-i686-python3-pytest-cov \ + mingw-w64-i686-libjpeg-turbo \ + mingw-w64-i686-libimagequant C:/msys64/mingw32/bin/python3 -m pip install --upgrade pip diff --git a/winbuild/appveyor_install_pypy2.cmd b/winbuild/appveyor_install_pypy2.cmd deleted file mode 100644 index fc56d0e56..000000000 --- a/winbuild/appveyor_install_pypy2.cmd +++ /dev/null @@ -1,3 +0,0 @@ -curl -fsSL -o pypy2.zip https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.1.1-win32.zip -7z x pypy2.zip -oc:\ -c:\Python37\Scripts\virtualenv.exe -p c:\pypy2.7-v7.1.1-win32\pypy.exe c:\vp\pypy2 diff --git a/winbuild/build.py b/winbuild/build.py index e66df2f03..e565226bd 100755 --- a/winbuild/build.py +++ b/winbuild/build.py @@ -53,10 +53,10 @@ def run_script(params): print(stderr.decode()) print("-- stdout --") print(trace.decode()) - print("Done with %s: %s" % (version, status)) + print("Done with {}: {}".format(version, status)) return (version, status, trace, stderr) except Exception as msg: - print("Error with %s: %s" % (version, str(msg))) + print("Error with {}: {}".format(version, str(msg))) return (version, -1, "", str(msg)) @@ -98,17 +98,14 @@ def build_one(py_ver, compiler, bit): if "PYTHON" in os.environ: args["python_path"] = "%PYTHON%" else: - args["python_path"] = "%s%s\\Scripts" % (VIRT_BASE, py_ver) + args["python_path"] = "{}{}\\Scripts".format(VIRT_BASE, py_ver) args["executable"] = "python.exe" if "EXECUTABLE" in os.environ: args["executable"] = "%EXECUTABLE%" args["py_ver"] = py_ver - if "27" in py_ver: - args["tcl_ver"] = "85" - else: - args["tcl_ver"] = "86" + args["tcl_ver"] = "86" if compiler["vc_version"] == "2015": args["imaging_libs"] = " build_ext --add-imaging-libs=msvcrt" @@ -160,7 +157,7 @@ def main(op): scripts.append( ( - "%s%s" % (py_version, X64_EXT), + "{}{}".format(py_version, X64_EXT), "\n".join( [ header(op), @@ -174,7 +171,7 @@ def main(op): results = map(run_script, scripts) for (version, status, trace, err) in results: - print("Compiled %s: %s" % (version, status and "ERR" or "OK")) + print("Compiled {}: {}".format(version, status and "ERR" or "OK")) def run_one(op): diff --git a/winbuild/build_dep.py b/winbuild/build_dep.py index 0062ad0c9..5762de5e5 100644 --- a/winbuild/build_dep.py +++ b/winbuild/build_dep.py @@ -101,7 +101,7 @@ set CMAKE="cmake.exe" set INCLIB=%~dp0\depends set BUILD=%~dp0\build """ + "\n".join( - r"set %s=%%BUILD%%\%s" % (k.upper(), v["dir"]) + r"set {}=%BUILD%\{}".format(k.upper(), v["dir"]) for (k, v) in libs.items() if v["dir"] ) @@ -300,33 +300,6 @@ endlocal ) -def build_ghostscript(compiler, bit): - script = ( - r""" -rem Build gs -setlocal -""" - + vc_setup(compiler, bit) - + r""" -set MSVC_VERSION=""" - + {"2010": "90", "2015": "14"}[compiler["vc_version"]] - + r""" -set RCOMP="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\RC.Exe" -cd /D %%GHOSTSCRIPT%% -""" - ) - if bit == 64: - script += r""" -set WIN64="" -""" - script += r""" -nmake -nologo -f psi/msvc.mak -copy /Y /B bin\ C:\Python27\ -endlocal -""" - return script % compiler - - def add_compiler(compiler, bit): script.append(setup_compiler(compiler)) script.append(nmake_libs(compiler, bit)) @@ -336,7 +309,6 @@ def add_compiler(compiler, bit): script.append(msbuild_freetype(compiler, bit)) script.append(build_lcms2(compiler)) script.append(nmake_openjpeg(compiler, bit)) - script.append(build_ghostscript(compiler, bit)) script.append(end_compiler()) diff --git a/winbuild/config.py b/winbuild/config.py index c76d9d5bf..b68fb6936 100644 --- a/winbuild/config.py +++ b/winbuild/config.py @@ -3,18 +3,17 @@ import os SF_MIRROR = "https://iweb.dl.sourceforge.net" pythons = { + "pypy3": {"compiler": 7.1, "vc": 2015}, # for AppVeyor - "27": {"compiler": 7, "vc": 2010}, - "pypy2": {"compiler": 7, "vc": 2010}, "35": {"compiler": 7.1, "vc": 2015}, "36": {"compiler": 7.1, "vc": 2015}, - "pypy3": {"compiler": 7.1, "vc": 2015}, "37": {"compiler": 7.1, "vc": 2015}, "38": {"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}, + "3.8": {"compiler": 7.1, "vc": 2015}, } VIRT_BASE = "c:/vp/" @@ -55,11 +54,6 @@ libs = { "filename": "lcms2-2.8.zip", "dir": "lcms2-2.8", }, - "ghostscript": { - "url": "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs927/ghostscript-9.27.tar.gz", # noqa: E501 - "filename": "ghostscript-9.27.tar.gz", - "dir": "ghostscript-9.27", - }, "tcl-8.5": { "url": SF_MIRROR + "/project/tcl/Tcl/8.5.19/tcl8519-src.zip", "filename": "tcl8519-src.zip", @@ -72,15 +66,15 @@ libs = { "version": "8.5.19", }, "tcl-8.6": { - "url": SF_MIRROR + "/project/tcl/Tcl/8.6.9/tcl869-src.zip", - "filename": "tcl869-src.zip", + "url": SF_MIRROR + "/project/tcl/Tcl/8.6.10/tcl8610-src.zip", + "filename": "tcl8610-src.zip", "dir": "", }, "tk-8.6": { - "url": SF_MIRROR + "/project/tcl/Tcl/8.6.9/tk869-src.zip", - "filename": "tk869-src.zip", + "url": SF_MIRROR + "/project/tcl/Tcl/8.6.10/tk8610-src.zip", + "filename": "tk8610-src.zip", "dir": "", - "version": "8.6.9", + "version": "8.6.10", }, "webp": { "url": "http://downloads.webmproject.org/releases/webp/libwebp-1.0.3.tar.gz", @@ -167,14 +161,14 @@ compilers = { def pyversion_from_env(): py = os.environ["PYTHON"] - py_version = "27" + py_version = "35" for k in pythons: if k in py: py_version = k break if "64" in py: - py_version = "%s%s" % (py_version, X64_EXT) + py_version = "{}{}".format(py_version, X64_EXT) return py_version diff --git a/winbuild/get_pythons.py b/winbuild/get_pythons.py index e24bb65f7..a853fc6f7 100644 --- a/winbuild/get_pythons.py +++ b/winbuild/get_pythons.py @@ -3,7 +3,7 @@ import os from fetch import fetch if __name__ == "__main__": - for version in ["2.7.15", "3.4.4"]: + for version in ["3.4.4"]: for platform in ["", ".amd64"]: for extension in ["", ".asc"]: fetch( diff --git a/winbuild/test.py b/winbuild/test.py index 559ecdec1..a05a20b18 100755 --- a/winbuild/test.py +++ b/winbuild/test.py @@ -13,7 +13,7 @@ def test_one(params): try: print("Running: %s, %s" % params) command = [ - r"%s\%s%s\Scripts\python.exe" % (VIRT_BASE, python, architecture), + r"{}\{}{}\Scripts\python.exe".format(VIRT_BASE, python, architecture), "test-installed.py", "--processes=-0", "--process-timeout=30", @@ -22,10 +22,10 @@ def test_one(params): proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (trace, stderr) = proc.communicate() status = proc.returncode - print("Done with %s, %s -- %s" % (python, architecture, status)) + print("Done with {}, {} -- {}".format(python, architecture, status)) return (python, architecture, status, trace) except Exception as msg: - print("Error with %s, %s: %s" % (python, architecture, msg)) + print("Error with {}, {}: {}".format(python, architecture, msg)) return (python, architecture, -1, str(msg)) @@ -39,7 +39,7 @@ if __name__ == "__main__": results = map(test_one, matrix) for (python, architecture, status, trace) in results: - print("%s%s: %s" % (python, architecture, status and "ERR" or "PASS")) + print("{}{}: {}".format(python, architecture, status and "ERR" or "PASS")) res = all(status for (python, architecture, status, trace) in results) sys.exit(res)