From af770a6c555013c87d7c208fb610886fef59d5b8 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 26 Sep 2019 15:12:28 +0300 Subject: [PATCH 01/18] Drop support for EOL Python 2.7 --- .appveyor.yml | 11 --- .github/CONTRIBUTING.md | 4 +- .travis.yml | 8 +- .travis/after_success.sh | 10 +-- .travis/install.sh | 4 +- .travis/script.sh | 2 +- Makefile | 36 ++++---- Tests/helper.py | 6 -- Tests/test_file_iptc.py | 9 +- Tests/test_file_libtiff.py | 17 +--- Tests/test_file_png.py | 12 ++- Tests/test_file_tiff.py | 17 +--- Tests/test_font_pcf.py | 6 +- Tests/test_format_hsv.py | 24 ++---- Tests/test_image.py | 11 +-- Tests/test_image_access.py | 6 -- Tests/test_image_getim.py | 6 +- Tests/test_imagepath.py | 6 +- Tests/test_imagetk.py | 7 +- Tests/test_psdraw.py | 5 +- mp_compile.py | 93 --------------------- setup.py | 15 +--- src/PIL/EpsImagePlugin.py | 14 +--- src/PIL/Image.py | 58 +++---------- src/PIL/ImageFont.py | 7 +- src/PIL/ImageMath.py | 22 +---- src/PIL/ImageQt.py | 7 +- src/PIL/ImageShow.py | 6 +- src/PIL/ImageTk.py | 8 +- src/PIL/PSDraw.py | 3 +- src/PIL/PdfParser.py | 50 +++-------- src/PIL/PngImagePlugin.py | 26 +++--- src/PIL/SgiImagePlugin.py | 4 +- src/PIL/TarIO.py | 7 +- src/PIL/TiffImagePlugin.py | 37 ++------- src/PIL/WalImageFile.py | 9 +- src/PIL/WmfImagePlugin.py | 4 - src/PIL/_binary.py | 19 +---- src/PIL/_tkinter_finder.py | 6 +- src/PIL/_util.py | 23 ++---- src/Tk/tkImaging.c | 8 -- src/_imaging.c | 105 ++++++------------------ src/_imagingcms.c | 34 ++------ src/_imagingft.c | 103 ++++------------------- src/_imagingmath.c | 13 +-- src/_imagingmorph.c | 11 --- src/_imagingtk.c | 10 --- src/_webp.c | 16 +--- src/decode.c | 3 +- src/display.c | 13 +-- src/encode.c | 43 +++++----- src/libImaging/codec_fd.c | 3 +- src/map.c | 2 - src/path.c | 19 ++--- src/py3.h | 56 ------------- tox.ini | 2 +- winbuild/appveyor_install_msys2_deps.sh | 14 ++-- winbuild/appveyor_install_pypy2.cmd | 3 - winbuild/build.py | 5 +- winbuild/config.py | 4 +- winbuild/get_pythons.py | 2 +- 61 files changed, 217 insertions(+), 877 deletions(-) delete mode 100644 mp_compile.py delete mode 100644 src/py3.h delete mode 100644 winbuild/appveyor_install_pypy2.cmd diff --git a/.appveyor.yml b/.appveyor.yml index f299794b6a2..27c7d7597bf 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -13,13 +13,7 @@ environment: TEST_OPTIONS: DEPLOY: YES matrix: - - PYTHON: C:/vp/pypy2 - EXECUTABLE: bin/pypy.exe - PIP_DIR: bin - VENV: YES - - PYTHON: C:/Python27-x64 - PYTHON: C:/Python37 - - PYTHON: C:/Python27 - PYTHON: C:/Python37-x64 - PYTHON: C:/Python36 - PYTHON: C:/Python36-x64 @@ -44,11 +38,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") { diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b3d45665969..3d27b5d88c6 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/.travis.yml b/.travis.yml index 286f828f2f1..23268897155 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: @@ -16,15 +16,11 @@ matrix: - python: "3.6" name: "Lint" env: LINT="true" - - python: "pypy" - name: "PyPy2 Xenial" - python: "pypy3" name: "PyPy3 Xenial" - python: '3.7' name: "3.7 Xenial" services: xvfb - - python: '2.7' - name: "2.7 Xenial" - python: '3.6' name: "3.6 Xenial PYTHONOPTIMIZE=1" env: PYTHONOPTIMIZE=1 diff --git a/.travis/after_success.sh b/.travis/after_success.sh index 1dca2ccb930..721a469b698 100755 --- a/.travis/after_success.sh +++ b/.travis/after_success.sh @@ -11,16 +11,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 6ad89402e16..747acb4486b 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/script.sh b/.travis/script.sh index af56cc6ab92..c2b9036016e 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -9,4 +9,4 @@ make install-coverage 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/Makefile b/Makefile index 1803e617d15..fdde3416bd3 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/helper.py b/Tests/helper.py index 78a2f520f92..87f0344492b 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -10,7 +10,6 @@ import unittest from PIL import Image, ImageMath -from PIL._util import py3 logger = logging.getLogger(__name__) @@ -277,11 +276,6 @@ def _test_leak(self, core): # helpers -if not py3: - # Remove DeprecationWarning in Python 3 - PillowTestCase.assertRaisesRegex = PillowTestCase.assertRaisesRegexp - PillowTestCase.assertRegex = PillowTestCase.assertRegexpMatches - def fromstring(data): from io import BytesIO diff --git a/Tests/test_file_iptc.py b/Tests/test_file_iptc.py index 800563af1bb..c1c6ecbad0f 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 @@ def test_dump(self): # 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 ea73a7ad50a..c1cce193639 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -9,7 +9,6 @@ from ctypes import c_float from PIL import Image, TiffImagePlugin, TiffTags, features -from PIL._util import py3 from .helper import PillowTestCase, hopper @@ -361,12 +360,8 @@ def test_little_endian(self): 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 +382,8 @@ def test_big_endian(self): 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_png.py b/Tests/test_file_png.py index 6d76a6caa7c..3f5f003aca3 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -3,7 +3,6 @@ from io import BytesIO from PIL import Image, ImageFile, PngImagePlugin -from PIL._util import py3 from .helper import PillowLeakTestCase, PillowTestCase, hopper, unittest @@ -460,12 +459,11 @@ def rt_text(value): 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 - # CJK: - rt_text(chr(0x4E00) + chr(0x66F0) + chr(0x9FBA) + 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_tiff.py b/Tests/test_file_tiff.py index 048539f86ed..9919bacf870 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -3,7 +3,6 @@ from io import BytesIO 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, unittest @@ -176,12 +175,8 @@ def test_little_endian(self): 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") @@ -191,12 +186,8 @@ def test_big_endian(self): 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") diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index a2b4ef27e8d..e37f43207d8 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 @@ def _test_high_characters(self, message): 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 ce0524e1e22..e80e16ffec2 100644 --- a/Tests/test_format_hsv.py +++ b/Tests/test_format_hsv.py @@ -2,7 +2,6 @@ import itertools from PIL import Image -from PIL._util import py3 from .helper import PillowTestCase, hopper @@ -49,27 +48,18 @@ def to_xxx_colorsys(self, im, func, mode): (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 47196a1394a..53f0199de36 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -3,7 +3,6 @@ import sys from PIL import Image -from PIL._util import py3 from .helper import PillowTestCase, hopper, unittest @@ -80,20 +79,14 @@ def test_width_height(self): 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("") + im = io.BytesIO(b"") self.assertRaises(IOError, 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 diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index b06814cb944..4004ca5df86 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -349,12 +349,8 @@ def test_embeddable(self): 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")); @@ -364,9 +360,7 @@ def test_embeddable(self): 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_getim.py b/Tests/test_image_getim.py index 3f0c46c46d3..f6908af4b48 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 @@ def test_sanity(self): 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_imagepath.py b/Tests/test_imagepath.py index ed65d47c1ce..35c78cd3b8d 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -2,7 +2,6 @@ import struct from PIL import Image, ImagePath -from PIL._util import py3 from .helper import PillowTestCase @@ -75,10 +74,7 @@ def test_overflow_segfault(self): # 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_imagetk.py b/Tests/test_imagetk.py index c397c84beb9..808ebd3927d 100644 --- a/Tests/test_imagetk.py +++ b/Tests/test_imagetk.py @@ -1,15 +1,12 @@ from PIL import Image -from PIL._util import py3 from .helper import PillowTestCase, hopper, unittest 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_psdraw.py b/Tests/test_psdraw.py index 561df4ee602..0ef9acb06da 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 @@ def test_draw_postscript(self): 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/mp_compile.py b/mp_compile.py deleted file mode 100644 index ec73e927e28..00000000000 --- 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/setup.py b/setup.py index 76bdfb159fb..547034f5015 100755 --- a/setup.py +++ b/setup.py @@ -20,10 +20,6 @@ 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 - if sys.platform == "win32" and sys.version_info >= (3, 8): warnings.warn( "Pillow does not yet support Python {}.{} and does not yet provide " @@ -332,12 +328,6 @@ def finalize_options(self): 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 for x in self.feature: if getattr(self, "disable_%s" % x): setattr(self.feature, x, False) @@ -861,12 +851,11 @@ def debug_build(): 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 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Multimedia :: Graphics", @@ -875,7 +864,7 @@ def debug_build(): "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/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index 219f2dbb898..6d8828951a5 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -42,15 +42,8 @@ if sys.platform.startswith("win"): import shutil - if hasattr(shutil, "which"): - which = shutil.which - else: - # Python 2 - import distutils.spawn - - which = distutils.spawn.find_executable for binary in ("gswin32c", "gswin64c", "gs"): - if which(binary) is not None: + if shutil.which(binary) is not None: gs_windows_binary = binary break else: @@ -378,9 +371,8 @@ def _save(im, fp, filename, eps=1): base_fp = fp wrapped_fp = False if fp != sys.stdout: - if sys.version_info.major > 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/Image.py b/src/PIL/Image.py index cca9c8a912c..c73cb5eb822 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 @@ -33,29 +34,15 @@ import struct import sys 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 ._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, isStringType logger = logging.getLogger(__name__) @@ -134,18 +121,6 @@ def __getattr__(self, id): 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): """ @@ -621,10 +596,8 @@ def close(self): # object is gone. self.im = deferred_error(ValueError("Operation on closed image")) - if sys.version_info.major >= 3: - - def __del__(self): - self.__exit__() + def __del__(self): + self.__exit__() def _copy(self): self.load() @@ -1347,10 +1320,7 @@ def getpalette(self): 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 @@ -1701,10 +1671,7 @@ def putpalette(self, data, rawmode="RGB"): 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 @@ -2036,7 +2003,7 @@ def save(self, fp, format=None, **params): 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): @@ -2747,7 +2714,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 @@ -3311,11 +3278,6 @@ def __getitem__(self, tag): 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/ImageFont.py b/src/PIL/ImageFont.py index 5cce9af8e43..1453a290c31 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -29,7 +29,7 @@ import sys from . import Image -from ._util import isDirectory, isPath, py3 +from ._util import isDirectory, isPath LAYOUT_BASIC = 0 LAYOUT_RAQM = 1 @@ -695,10 +695,7 @@ 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: diff --git a/src/PIL/ImageMath.py b/src/PIL/ImageMath.py index 392151c10f8..d7598b93295 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. # -from . import Image, _imagingmath -from ._util import py3 - -try: - import builtins -except ImportError: - import __builtin__ +import builtins - builtins = __builtin__ +from . import Image, _imagingmath VERBOSE = 0 @@ -101,11 +95,6 @@ def __bool__(self): # 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 @@ def __pow__(self, other): 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/ImageQt.py b/src/PIL/ImageQt.py index da60cacd084..ce34b0a043a 100644 --- a/src/PIL/ImageQt.py +++ b/src/PIL/ImageQt.py @@ -20,7 +20,7 @@ from io import BytesIO from . import Image -from ._util import isPath, py3 +from ._util import isPath qt_versions = [["5", "PyQt5"], ["side2", "PySide2"]] @@ -125,10 +125,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/ImageShow.py b/src/PIL/ImageShow.py index ca622c52506..6d3ca52d8e6 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -18,14 +18,10 @@ 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 = [] diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index fd480007ad4..769fae66236 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 diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index f37701ce979..baad510e156 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -18,7 +18,6 @@ import sys from . import EpsImagePlugin -from ._util import py3 ## # Simple Postscript graphics interface. @@ -36,7 +35,7 @@ def __init__(self, fp=None): 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")) diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 0ec6bba14d6..14079f6b195 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -7,24 +7,14 @@ 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 @@ -81,10 +71,8 @@ def encode_text(s): 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): @@ -252,16 +240,10 @@ def from_pdf_stream(cls, data): 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__ @@ -324,23 +306,13 @@ def __bytes__(self): 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 +354,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 diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index be237b3eeb3..c3a5dd627c1 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -38,7 +38,6 @@ 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. @@ -450,9 +449,8 @@ def chunk_tEXt(self, pos, length): 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)) @@ -487,9 +485,8 @@ def chunk_zTXt(self, pos, length): 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)) @@ -524,14 +521,13 @@ def chunk_iTXt(self, pos, length): 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)) diff --git a/src/PIL/SgiImagePlugin.py b/src/PIL/SgiImagePlugin.py index 99408fdc344..7de62c11764 100644 --- a/src/PIL/SgiImagePlugin.py +++ b/src/PIL/SgiImagePlugin.py @@ -27,7 +27,6 @@ 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. @@ -173,8 +172,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/TarIO.py b/src/PIL/TarIO.py index e180b802ccb..457d75d039e 100644 --- a/src/PIL/TarIO.py +++ b/src/PIL/TarIO.py @@ -15,7 +15,6 @@ # import io -import sys from . import ContainerIO @@ -64,10 +63,8 @@ def __enter__(self): def __exit__(self, *args): self.close() - if sys.version_info.major >= 3: - - def __del__(self): - self.close() + def __del__(self): + self.close() def close(self): self.fh.close() diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index b0d465fe2eb..6d56df2174f 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -46,24 +46,15 @@ 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" @@ -531,18 +522,11 @@ def __getitem__(self, tag): 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 @@ -562,14 +546,10 @@ def _setitem(self, tag, value, legacy_api): 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 ] @@ -689,8 +669,6 @@ def load_string(self, data, legacy_api=True): @_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) @@ -1132,7 +1110,7 @@ def _load_libtiff(self): 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() @@ -1602,13 +1580,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) diff --git a/src/PIL/WalImageFile.py b/src/PIL/WalImageFile.py index e2e1cd4f57a..daa806a8b5d 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -21,16 +21,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/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index 416af6fd745..be07a747bb2 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -23,7 +23,6 @@ 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. @@ -31,9 +30,6 @@ _handler = None -if py3: - long = int - def register_handler(handler): """ diff --git a/src/PIL/_binary.py b/src/PIL/_binary.py index 53b1ca95629..529b8c94b78 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 i8(c): - return c if c.__class__ is int else c[0] - def o8(i): - return bytes((i & 255,)) - - -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 d4f34196ebb..30493066af5 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 59964c7efae..127e94d824b 100644 --- a/src/PIL/_util.py +++ b/src/PIL/_util.py @@ -1,33 +1,24 @@ 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) +def isStringType(t): + return isinstance(t, str) - if py36: - from pathlib import Path - def isPath(f): - return isinstance(f, (bytes, str, Path)) +if py36: + from pathlib import 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. diff --git a/src/Tk/tkImaging.c b/src/Tk/tkImaging.c index bb0fd33a378..59801f58eb9 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 04520b1a1fd..a12fdfb1563 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* @@ -3959,7 +3917,6 @@ setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imaging(void) { PyObject* m; @@ -3979,11 +3936,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 2c9f3aa68f4..0b22ab69547 100644 --- a/src/_imagingcms.c +++ b/src/_imagingcms.c @@ -32,7 +32,6 @@ kevin@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 7776e43f1b7..fb6a46d1771 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,7 +326,7 @@ 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 (defined(PYPY_VERSION_NUM)) if (PyUnicode_Check(string)) { Py_UNICODE* p = PyUnicode_AS_UNICODE(string); int size = PyUnicode_GET_SIZE(string); @@ -337,16 +335,6 @@ font_getchar(PyObject* string, int index, FT_ULong* char_out) *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)) @@ -375,7 +363,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)) if (PyUnicode_Check(string)) { Py_UNICODE *text = PyUnicode_AS_UNICODE(string); Py_ssize_t size = PyUnicode_GET_SIZE(string); @@ -395,25 +383,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); @@ -479,11 +448,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 +460,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 +540,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; } @@ -990,8 +945,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; } @@ -1025,11 +979,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); @@ -1037,8 +991,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; } @@ -1095,8 +1048,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 { @@ -1146,64 +1099,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[] = { @@ -1271,11 +1214,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); @@ -1286,7 +1225,6 @@ setup_module(PyObject* m) { return 0; } -#if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingft(void) { PyObject* m; @@ -1306,12 +1244,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 ea9f103c683..bc66a581a22 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 fc8f246cc86..050ae9f0287 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 d0295f317f9..bdf5e68d192 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 66b6d3268ac..4581ef89dca 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 79133f48fcf..5ab6ca9d156 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 efabf1c86af..4c2faf9e059 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 7dc1035c499..41ba124c4ee 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 7bd4dadf868..5cde31cdc5d 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 099bb4b3ef3..a8fb69c6eb9 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 5f0541b0beb..f69755d1685 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 310583845f7..00000000000 --- 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 2dc92037148..11bcec50058 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,7 @@ [tox] envlist = lint - py{27,35,36,37} + py{35,36,37} minversion = 1.9 [testenv] diff --git a/winbuild/appveyor_install_msys2_deps.sh b/winbuild/appveyor_install_msys2_deps.sh index 02b75e210e2..4cc01082d98 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 fc56d0e56ab..00000000000 --- 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 0617022dcf9..f4561d933b8 100755 --- a/winbuild/build.py +++ b/winbuild/build.py @@ -105,10 +105,7 @@ def build_one(py_ver, compiler, bit): 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" diff --git a/winbuild/config.py b/winbuild/config.py index 16a1d9cadf0..46c9f9b2b13 100644 --- a/winbuild/config.py +++ b/winbuild/config.py @@ -4,8 +4,6 @@ PILLOW_DEPENDS_DIR = "C:\\pillow-depends\\" pythons = { - "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}, @@ -131,7 +129,7 @@ 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 diff --git a/winbuild/get_pythons.py b/winbuild/get_pythons.py index e24bb65f78e..a853fc6f7ea 100644 --- a/winbuild/get_pythons.py +++ b/winbuild/get_pythons.py @@ -3,7 +3,7 @@ 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( From 538d9e2e5d252bea23e12da08495945d776aed78 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 30 Sep 2019 17:56:31 +0300 Subject: [PATCH 02/18] Upgrade Python syntax with pyupgrade --py3-plus --- Tests/check_imaging_leaks.py | 3 -- Tests/createfontdatachunk.py | 2 - Tests/helper.py | 30 ++++++----- Tests/import_all.py | 2 - Tests/make_hash.py | 2 - Tests/test_bmp_reference.py | 4 +- Tests/test_color_lut.py | 2 - Tests/test_core_resources.py | 2 - Tests/test_features.py | 2 - Tests/test_file_eps.py | 2 +- Tests/test_file_gif.py | 3 +- Tests/test_file_libtiff.py | 4 +- Tests/test_file_pdf.py | 7 ++- Tests/test_file_tiff.py | 3 +- Tests/test_file_tiff_metadata.py | 4 +- Tests/test_file_webp_animated.py | 3 +- Tests/test_file_webp_metadata.py | 6 +-- Tests/test_font_leaks.py | 2 - Tests/test_image.py | 6 +-- Tests/test_image_access.py | 4 +- Tests/test_image_array.py | 2 +- Tests/test_image_resample.py | 2 - Tests/test_imageenhance.py | 2 +- Tests/test_imagefont.py | 7 ++- Tests/test_imagefontctl.py | 1 - Tests/test_imagemath.py | 4 +- Tests/test_imageops.py | 2 +- Tests/test_imageqt.py | 2 +- Tests/test_locale.py | 2 - Tests/test_main.py | 2 - Tests/test_mode_i16.py | 6 ++- Tests/test_numpy.py | 2 - Tests/test_pdfparser.py | 2 +- Tests/test_qt_image_toqimage.py | 2 +- Tests/threaded_save.py | 2 - Tests/versions.py | 2 - docs/conf.py | 15 +++--- docs/example/DdsImagePlugin.py | 8 +-- selftest.py | 1 - setup.py | 12 ++--- src/PIL/BdfFontFile.py | 1 - src/PIL/BlpImagePlugin.py | 2 +- src/PIL/BmpImagePlugin.py | 16 +++--- src/PIL/BufrStubImagePlugin.py | 2 +- src/PIL/ContainerIO.py | 2 +- src/PIL/CurImagePlugin.py | 3 -- src/PIL/DdsImagePlugin.py | 4 +- src/PIL/EpsImagePlugin.py | 8 +-- src/PIL/FitsStubImagePlugin.py | 2 +- src/PIL/FontFile.py | 3 +- src/PIL/FpxImagePlugin.py | 9 ++-- src/PIL/GdImageFile.py | 2 +- src/PIL/GifImagePlugin.py | 2 +- src/PIL/GimpGradientFile.py | 4 +- src/PIL/GimpPaletteFile.py | 2 +- src/PIL/GribStubImagePlugin.py | 2 +- src/PIL/Hdf5StubImagePlugin.py | 2 +- src/PIL/IcnsImagePlugin.py | 2 +- src/PIL/IcoImagePlugin.py | 2 +- src/PIL/Image.py | 16 +++--- src/PIL/ImageCms.py | 30 ++++++----- src/PIL/ImageDraw.py | 2 +- src/PIL/ImageDraw2.py | 8 +-- src/PIL/ImageEnhance.py | 2 +- src/PIL/ImageFile.py | 28 +++++------ src/PIL/ImageFilter.py | 5 +- src/PIL/ImageFont.py | 16 +++--- src/PIL/ImageMath.py | 2 +- src/PIL/ImageMode.py | 2 +- src/PIL/ImageMorph.py | 6 +-- src/PIL/ImageOps.py | 2 +- src/PIL/ImagePalette.py | 4 +- src/PIL/ImageSequence.py | 2 +- src/PIL/ImageShow.py | 13 ++--- src/PIL/ImageStat.py | 2 +- src/PIL/ImageTk.py | 6 +-- src/PIL/ImageWin.py | 8 +-- src/PIL/IptcImagePlugin.py | 9 ++-- src/PIL/JpegImagePlugin.py | 5 +- src/PIL/MicImagePlugin.py | 2 +- src/PIL/MpegImagePlugin.py | 2 +- src/PIL/MspImagePlugin.py | 8 +-- src/PIL/PSDraw.py | 8 +-- src/PIL/PaletteFile.py | 2 +- src/PIL/PalmImagePlugin.py | 4 +- src/PIL/PcfFontFile.py | 2 +- src/PIL/PcxImagePlugin.py | 2 +- src/PIL/PdfParser.py | 86 ++++++++++++++++---------------- src/PIL/PngImagePlugin.py | 14 +++--- src/PIL/PpmImagePlugin.py | 2 +- src/PIL/PsdImagePlugin.py | 2 +- src/PIL/PyAccess.py | 2 +- src/PIL/SgiImagePlugin.py | 4 +- src/PIL/SpiderImagePlugin.py | 5 +- src/PIL/TarIO.py | 4 +- src/PIL/TgaImagePlugin.py | 2 +- src/PIL/TiffImagePlugin.py | 35 ++++++------- src/PIL/TiffTags.py | 2 +- src/PIL/WalImageFile.py | 1 - src/PIL/WebPImagePlugin.py | 12 ++--- src/PIL/WmfImagePlugin.py | 6 +-- src/PIL/XbmImagePlugin.py | 2 +- src/PIL/_util.py | 2 +- src/PIL/features.py | 2 - winbuild/build.py | 10 ++-- winbuild/build_dep.py | 2 +- winbuild/config.py | 2 +- winbuild/test.py | 8 +-- 108 files changed, 287 insertions(+), 357 deletions(-) diff --git a/Tests/check_imaging_leaks.py b/Tests/check_imaging_leaks.py index 2b9a9605be4..35157d1c707 100755 --- a/Tests/check_imaging_leaks.py +++ b/Tests/check_imaging_leaks.py @@ -1,7 +1,4 @@ #!/usr/bin/env python - -from __future__ import division - import sys from PIL import Image diff --git a/Tests/createfontdatachunk.py b/Tests/createfontdatachunk.py index 4d189dbad90..c7055995e37 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 87f0344492b..282482940ac 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -1,7 +1,6 @@ """ Helper functions. """ -from __future__ import print_function import logging import os @@ -77,10 +76,13 @@ def delete_tempfile(self, path): 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) @@ -88,20 +90,24 @@ def assert_deep_equal(self, a, b, msg=None): 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: @@ -122,10 +128,10 @@ def assert_image_equal_tofile(self, a, filename, msg=None, mode=None): 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) @@ -228,12 +234,12 @@ def tempfile(self, template): 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") @@ -371,7 +377,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 4dfacb2911e..33b07f9a25d 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 bacb391faad..7199f8c7f85 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 e6a75e2c370..2038ac54013 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 @@ def get_compare(f): 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 ca82209c248..301a99a3f8b 100644 --- a/Tests/test_color_lut.py +++ b/Tests/test_color_lut.py @@ -1,5 +1,3 @@ -from __future__ import division - from array import array from PIL import Image, ImageFilter diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py index eefb1a0efab..8f3cf710537 100644 --- a/Tests/test_core_resources.py +++ b/Tests/test_core_resources.py @@ -1,5 +1,3 @@ -from __future__ import division, print_function - import sys from PIL import Image diff --git a/Tests/test_features.py b/Tests/test_features.py index 64b0302caa5..b8e02edea95 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import io from PIL import features diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py index 3459310dfad..08d58b3ba10 100644 --- a/Tests/test_file_eps.py +++ b/Tests/test_file_eps.py @@ -92,7 +92,7 @@ def test_file_object(self): def test_iobase_object(self): # issue 479 image1 = Image.open(file1) - 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_gif.py b/Tests/test_file_gif.py index 4ff9727e1e9..8be614412a3 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -610,8 +610,7 @@ def test_append_images(self): # 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)) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index c1cce193639..881d9096cc1 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import distutils.version import io import itertools @@ -262,7 +260,7 @@ def test_custom_metadata(self): 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("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), diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 25c2f6bf6a6..0158807f7f5 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -99,8 +99,7 @@ def test_save_all(self): # 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)) @@ -207,7 +206,7 @@ def test_pdf_append(self): # 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 +234,7 @@ def test_pdf_append(self): 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_tiff.py b/Tests/test_file_tiff.py index 9919bacf870..d3e39e8c6d2 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -518,8 +518,7 @@ def test_tiff_save_all(self): # Test appending using a generator def imGenerator(ims): - for im in ims: - yield im + yield from ims mp = io.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 170cac71ed5..c30d055ae2d 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -157,13 +157,13 @@ def test_write_metadata(self): 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_animated.py b/Tests/test_file_webp_animated.py index dec74d0d044..11ccbc32903 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -91,8 +91,7 @@ def check(temp_file): # 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 ae528e3bf16..39d6f30c433 100644 --- a/Tests/test_file_webp_metadata.py +++ b/Tests/test_file_webp_metadata.py @@ -114,9 +114,9 @@ def test_write_animated_metadata(self): 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 14b36858523..9f172c2121b 100644 --- a/Tests/test_font_leaks.py +++ b/Tests/test_font_leaks.py @@ -1,5 +1,3 @@ -from __future__ import division - import sys from PIL import Image, ImageDraw, ImageFont, features diff --git a/Tests/test_image.py b/Tests/test_image.py index 53f0199de36..75b5e778a17 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -106,7 +106,7 @@ def test_pathlib(self): def test_fp_name(self): temp_file = self.tempfile("temp.jpg") - class FP(object): + class FP: def write(a, b): pass @@ -588,11 +588,11 @@ def test_overrun(self): 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 4004ca5df86..a15a8b75ea3 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -122,7 +122,7 @@ def check(self, mode, c=None): 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 @@ -151,7 +151,7 @@ def check(self, mode, c=None): 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( diff --git a/Tests/test_image_array.py b/Tests/test_image_array.py index 02e5c80f2a0..8277e42af3c 100644 --- a/Tests/test_image_array.py +++ b/Tests/test_image_array.py @@ -25,7 +25,7 @@ def test(mode): 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_resample.py b/Tests/test_image_resample.py index 7d1dc009db2..b831b3e4a04 100644 --- a/Tests/test_image_resample.py +++ b/Tests/test_image_resample.py @@ -1,5 +1,3 @@ -from __future__ import division, print_function - from contextlib import contextmanager from PIL import Image, ImageDraw diff --git a/Tests/test_imageenhance.py b/Tests/test_imageenhance.py index b2235853a63..d0d994eee1a 100644 --- a/Tests/test_imageenhance.py +++ b/Tests/test_imageenhance.py @@ -35,7 +35,7 @@ def _check_alpha(self, im, original, op, amount): 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_imagefont.py b/Tests/test_imagefont.py index 6a2d572a954..6daac701baf 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import copy import distutils.version import os @@ -20,7 +19,7 @@ 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,7 +461,7 @@ def test_unicode_pilfont(self): # issue #2826 font = ImageFont.load_default() with self.assertRaises(UnicodeEncodeError): - font.getsize(u"’") + font.getsize("’") @unittest.skipIf( sys.version.startswith("2") or hasattr(sys, "pypy_translation_info"), @@ -470,7 +469,7 @@ def test_unicode_pilfont(self): ) 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_imagefontctl.py b/Tests/test_imagefontctl.py index 5b88f94cced..84bf1c58fff 100644 --- a/Tests/test_imagefontctl.py +++ b/Tests/test_imagefontctl.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from PIL import Image, ImageDraw, ImageFont, features from .helper import PillowTestCase, unittest diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py index da41b3a1274..8d2b9422605 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 @@ 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 2cdbbe02f85..d0fd736899b 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -11,7 +11,7 @@ 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_imageqt.py b/Tests/test_imageqt.py index 9248291c394..8134dcbc475 100644 --- a/Tests/test_imageqt.py +++ b/Tests/test_imageqt.py @@ -15,7 +15,7 @@ def skip_if_qt_is_not_installed(test_case): 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_locale.py b/Tests/test_locale.py index cbec8b965ea..14b2317ab32 100644 --- a/Tests/test_locale.py +++ b/Tests/test_locale.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import locale from PIL import Image diff --git a/Tests/test_main.py b/Tests/test_main.py index 847def83423..9f3758256e3 100644 --- a/Tests/test_main.py +++ b/Tests/test_main.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import os import subprocess import sys diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index b1cf2a23395..5b2ace01059 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -20,7 +20,11 @@ def verify(self, im1): 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 872ecdbb600..358180f3f67 100644 --- a/Tests/test_numpy.py +++ b/Tests/test_numpy.py @@ -1,5 +1,3 @@ -from __future__ import print_function - from PIL import Image from .helper import PillowTestCase, hopper, unittest diff --git a/Tests/test_pdfparser.py b/Tests/test_pdfparser.py index 0d492348084..d599c826411 100644 --- a/Tests/test_pdfparser.py +++ b/Tests/test_pdfparser.py @@ -22,7 +22,7 @@ def test_text_encode_decode(self): 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_qt_image_toqimage.py b/Tests/test_qt_image_toqimage.py index 5115c1862b8..39d60d1979c 100644 --- a/Tests/test_qt_image_toqimage.py +++ b/Tests/test_qt_image_toqimage.py @@ -57,7 +57,7 @@ def test_segfault(self): class Example(QWidget): def __init__(self): - super(Example, self).__init__() + super().__init__() img = hopper().resize((1000, 1000)) diff --git a/Tests/threaded_save.py b/Tests/threaded_save.py index 11eb8677929..d47c2cf9994 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 1ac226c9d15..d6433b0631b 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/docs/conf.py b/docs/conf.py index a9ca91de71c..66effdfb27c 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 @@ 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 @@ ( master_doc, "PillowPILFork.tex", - u"Pillow (PIL Fork) Documentation", - u"Alex Clark", + "Pillow (PIL Fork) Documentation", + "Alex Clark", "manual", ) ] @@ -252,7 +251,7 @@ # 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 @@ ( 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/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index be493a3160a..45f63f1647d 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("= 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 diff --git a/src/PIL/BdfFontFile.py b/src/PIL/BdfFontFile.py index fdf2c097e1e..13c79b46025 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 7b97964a852..8a9d656debb 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -283,7 +283,7 @@ def decode(self, buffer): 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 8426e2497b6..2b46c97a86a 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -148,7 +148,7 @@ def _bitmap(self, header=0, offset=0): 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 +163,12 @@ def _bitmap(self, header=0, offset=0): # ------------------------------- 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 +206,21 @@ def _bitmap(self, header=0, offset=0): ): 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 +309,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 56cac3bb144..48f21e1b3b4 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -60,7 +60,7 @@ def _load(self): 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 3cf9d82d2c7..9727601abc3 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 9e2d8c96f7c..054b00d2733 100644 --- a/src/PIL/CurImagePlugin.py +++ b/src/PIL/CurImagePlugin.py @@ -15,9 +15,6 @@ # # 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 diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index b2d508942d8..57769af78de 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("= xsize: diff --git a/src/PIL/GdImageFile.py b/src/PIL/GdImageFile.py index 2d492358c11..d6113f8d70c 100644 --- a/src/PIL/GdImageFile.py +++ b/src/PIL/GdImageFile.py @@ -87,4 +87,4 @@ def open(fp, mode="r"): try: return GdImageFile(fp) except SyntaxError: - raise IOError("cannot identify this image file") + raise OSError("cannot identify this image file") diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 9d8e96feeeb..69ff2f66ae5 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -853,7 +853,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 f48e7f76ef3..851e24d6205 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 @@ def __init__(self, fp): 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 2994bbeab84..e3060ab8a8f 100644 --- a/src/PIL/GimpPaletteFile.py +++ b/src/PIL/GimpPaletteFile.py @@ -22,7 +22,7 @@ # 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 8a24a9829f4..515c272f727 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -61,7 +61,7 @@ def _load(self): 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 a3ea12f999c..362f2d3994d 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -60,7 +60,7 @@ def _load(self): 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 75ea18b6b5f..03484cf0e26 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -128,7 +128,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)], diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index 148e604f895..ff1d37d7d67 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -86,7 +86,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/Image.py b/src/PIL/Image.py index c73cb5eb822..026b04491a1 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -55,7 +55,7 @@ class DecompressionBombError(Exception): pass -class _imaging_not_installed(object): +class _imaging_not_installed: # module placeholder def __getattr__(self, id): raise ImportError("The _imaging C module is not installed") @@ -427,7 +427,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=()): @@ -448,7 +448,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) # -------------------------------------------------------------------- @@ -459,7 +459,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 @@ -500,7 +500,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 @@ -2389,12 +2389,12 @@ def toqpixmap(self): # 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 @@ -2772,7 +2772,7 @@ def _open_core(fp, filename, prefix): fp.close() for message in accept_warnings: warnings.warn(message) - raise IOError("cannot identify image file %r" % (filename if filename else fp)) + raise OSError("cannot identify image file %r" % (filename if filename else fp)) # diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index ed4eefc0d0e..89a4426fa78 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -15,8 +15,6 @@ # 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 @@ -152,7 +150,7 @@ # Profile. -class ImageCmsProfile(object): +class ImageCmsProfile: def __init__(self, profile): """ :param profile: Either a string representing a filename, @@ -374,7 +372,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 +396,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 +477,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 +588,7 @@ def buildProofTransform( proofRenderingIntent, flags, ) - except (IOError, TypeError, ValueError) as v: + except (OSError, TypeError, ValueError) as v: raise PyCMSError(v) @@ -733,9 +731,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 +773,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 +801,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 +829,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 +858,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 +887,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 +926,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 +977,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 ed3383f0531..65e4d7ac97f 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -45,7 +45,7 @@ """ -class ImageDraw(object): +class ImageDraw: def __init__(self, im, mode=None): """ Create a drawing instance. diff --git a/src/PIL/ImageDraw2.py b/src/PIL/ImageDraw2.py index 324d869f032..20b5fe4c499 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 534eb4f16a0..3b79d5c46a1 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 836e6318c5f..354159703d8 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") # @@ -145,7 +145,7 @@ def load(self): 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 @@ -203,7 +203,7 @@ def load(self): # 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() @@ -238,13 +238,13 @@ def load(self): 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) ) @@ -322,7 +322,7 @@ def _open(self): 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 (!) @@ -334,7 +334,7 @@ def _load(self): raise NotImplementedError("StubImageFile subclass must implement _load") -class Parser(object): +class Parser: """ Incremental image parser. This class implements the standard feed/close consumer interface. @@ -411,7 +411,7 @@ def feed(self, data): try: with io.BytesIO(self.data) as fp: im = Image.open(fp) - except IOError: + except OSError: # traceback.print_exc() pass # not enough data else: @@ -456,9 +456,9 @@ def close(self): 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 @@ -514,7 +514,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 @@ -529,7 +529,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() @@ -559,7 +559,7 @@ def _safe_read(fp, size): return b"".join(data) -class PyCodecState(object): +class PyCodecState: def __init__(self): self.xsize = 0 self.ysize = 0 @@ -570,7 +570,7 @@ def extents(self): 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 fa4162b6114..9cb62ad2748 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 @@ numpy = None -class Filter(object): +class Filter: pass diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 1453a290c31..f1bd6242aaa 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -35,7 +35,7 @@ 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") @@ -63,7 +63,7 @@ def __getattr__(self, id): # -------------------------------------------------------------------- -class ImageFont(object): +class ImageFont: "PIL font wrapper" def _load_pilfont(self, filename): @@ -79,7 +79,7 @@ def _load_pilfont(self, filename): 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 @@ -145,7 +145,7 @@ def getmask(self, text, mode="", *args, **kwargs): # 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): @@ -542,7 +542,7 @@ def set_variation_by_axes(self, axes): 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): @@ -638,7 +638,7 @@ def freetype(font): try: return freetype(font) - except IOError: + except OSError: if not isPath(font): raise ttf_filename = os.path.basename(font) @@ -698,9 +698,9 @@ def load_path(filename): 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 d7598b93295..adbb940000e 100644 --- a/src/PIL/ImageMath.py +++ b/src/PIL/ImageMath.py @@ -26,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): diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py index 596be7b9d7e..988288329b8 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 61199234bc5..d1ec09eace4 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 @@ # 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 @@ def build_lut(self): 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 5052cb74d4b..5a06adaf3a6 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -55,7 +55,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 2d4f5cb6b50..e0d439c9841 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -21,7 +21,7 @@ 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/ImageSequence.py b/src/PIL/ImageSequence.py index f9be92d4838..28a54c7b056 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. diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index 6d3ca52d8e6..2999d20876c 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -11,9 +11,6 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - import os import subprocess import sys @@ -52,7 +49,7 @@ def show(image, title=None, **options): return 0 -class Viewer(object): +class Viewer: """Base class for viewers.""" # main api @@ -123,10 +120,8 @@ def get_command(self, file, **options): # 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 @@ -166,7 +161,7 @@ class UnixViewer(Viewer): 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""" diff --git a/src/PIL/ImageStat.py b/src/PIL/ImageStat.py index 9ba16fd851d..50bafc97294 100644 --- a/src/PIL/ImageStat.py +++ b/src/PIL/ImageStat.py @@ -26,7 +26,7 @@ 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 769fae66236..31615b8383b 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -62,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 @@ -203,7 +203,7 @@ def paste(self, im, box=None): # BitmapImage -class BitmapImage(object): +class BitmapImage: """ A Tkinter-compatible bitmap image. This can be used everywhere Tkinter expects an image object. @@ -293,7 +293,7 @@ def __init__(self, master, im): tkinter.Label.__init__(self, 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 ed2c18ec425..c04e70eb538 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 @@ def __int__(self): 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 @@ def __int__(self): 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 @@ def tobytes(self): 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/IptcImagePlugin.py b/src/PIL/IptcImagePlugin.py index aedf2e48ccb..042e96740be 100644 --- a/src/PIL/IptcImagePlugin.py +++ b/src/PIL/IptcImagePlugin.py @@ -14,9 +14,6 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import print_function - import os import tempfile @@ -75,7 +72,7 @@ def field(self): # 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 +123,7 @@ def _open(self): 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 +212,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/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index 020b952192f..8c88a94c420 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 struct @@ -618,7 +615,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 diff --git a/src/PIL/MicImagePlugin.py b/src/PIL/MicImagePlugin.py index b48905bda00..add344f243b 100644 --- a/src/PIL/MicImagePlugin.py +++ b/src/PIL/MicImagePlugin.py @@ -51,7 +51,7 @@ def _open(self): 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 9c662fcc288..34d0922abef 100644 --- a/src/PIL/MpegImagePlugin.py +++ b/src/PIL/MpegImagePlugin.py @@ -26,7 +26,7 @@ # Bitstream parser -class BitStream(object): +class BitStream: def __init__(self, fp): self.fp = fp self.bits = 0 diff --git a/src/PIL/MspImagePlugin.py b/src/PIL/MspImagePlugin.py index 7315ab66ed6..5aa5f797471 100644 --- a/src/PIL/MspImagePlugin.py +++ b/src/PIL/MspImagePlugin.py @@ -122,7 +122,7 @@ def decode(self, buffer): "<%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 +131,7 @@ def decode(self, buffer): 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 +148,7 @@ def decode(self, buffer): 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 +165,7 @@ def decode(self, buffer): 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 baad510e156..90bcad03630 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -23,7 +23,7 @@ # 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. @@ -71,7 +71,7 @@ def setfont(self, font, size): """ 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)) @@ -132,12 +132,12 @@ def image(self, box, im, dpi=None): 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 ab22d5f0c1f..73f1b4b27c4 100644 --- a/src/PIL/PaletteFile.py +++ b/src/PIL/PaletteFile.py @@ -19,7 +19,7 @@ # 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 dd068d79412..0f42d72d27f 100644 --- a/src/PIL/PalmImagePlugin.py +++ b/src/PIL/PalmImagePlugin.py @@ -141,7 +141,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 +157,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/PcfFontFile.py b/src/PIL/PcfFontFile.py index 074124612d2..63735cecb5c 100644 --- a/src/PIL/PcfFontFile.py +++ b/src/PIL/PcfFontFile.py @@ -184,7 +184,7 @@ def _load_bitmaps(self, metrics): 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 397af8c1067..f7995d6b204 100644 --- a/src/PIL/PcxImagePlugin.py +++ b/src/PIL/PcxImagePlugin.py @@ -107,7 +107,7 @@ def _open(self): 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/PdfParser.py b/src/PIL/PdfParser.py index 14079f6b195..6e054af0899 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -24,47 +24,47 @@ 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", } @@ -235,7 +235,7 @@ def __repr__(self): 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"/") @@ -441,7 +441,7 @@ def write_header(self): 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/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index c3a5dd627c1..49e0c358ffe 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -101,7 +101,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 @@ -179,7 +179,7 @@ def verify(self, endchunk=b"IEND"): try: cid, pos, length = self.read() except struct.error: - raise IOError("truncated PNG file") + raise OSError("truncated PNG file") if cid == endchunk: break @@ -211,7 +211,7 @@ def __new__(cls, text, lang=None, tkey=None): return self -class PngInfo(object): +class PngInfo: """ PNG chunk container (for use with save(pnginfo=)) @@ -742,7 +742,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): @@ -795,7 +795,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 @@ -870,7 +870,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") @@ -918,7 +918,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 c3e9eed6dac..1ba46255b13 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -139,7 +139,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 f72ad5f4433..f2171bf6ee1 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -75,7 +75,7 @@ def _open(self): 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 2ab06f93ffe..359a9491975 100644 --- a/src/PIL/PyAccess.py +++ b/src/PIL/PyAccess.py @@ -40,7 +40,7 @@ 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 7de62c11764..aa5e54386d5 100644 --- a/src/PIL/SgiImagePlugin.py +++ b/src/PIL/SgiImagePlugin.py @@ -163,7 +163,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 diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index f1cae4d9f02..68559729c35 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 @@ -273,7 +270,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/TarIO.py b/src/PIL/TarIO.py index 457d75d039e..06769846ecc 100644 --- a/src/PIL/TarIO.py +++ b/src/PIL/TarIO.py @@ -37,12 +37,12 @@ def __init__(self, tarfile, file): 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 b1b35139602..72cd2d61e6f 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -173,7 +173,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 6d56df2174f..0fffbfb147f 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -38,9 +38,6 @@ # # See the README file for information on usage and redistribution. # - -from __future__ import division, print_function - import distutils.version import io import itertools @@ -712,7 +709,7 @@ def write_signed_rational(self, *values): 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)) ) @@ -746,7 +743,7 @@ def load(self, fp): 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) @@ -776,7 +773,7 @@ def load(self, fp): 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 @@ -795,7 +792,7 @@ def tobytes(self, offset=0): 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: @@ -1060,7 +1057,7 @@ def tell(self): 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: @@ -1089,14 +1086,14 @@ def _load_libtiff(self): 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)) @@ -1114,7 +1111,7 @@ def _load_libtiff(self): # 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 @@ -1128,7 +1125,7 @@ def _load_libtiff(self): 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"): @@ -1171,7 +1168,7 @@ def _load_libtiff(self): self.fp = None # might be shared if err < 0: - raise IOError(err) + raise OSError(err) return Image.Image.load(self) @@ -1179,7 +1176,7 @@ def _setup(self): """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)] @@ -1421,7 +1418,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) @@ -1616,7 +1613,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) @@ -1664,9 +1661,9 @@ def __init__(self, fn, new=False): 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() diff --git a/src/PIL/TiffTags.py b/src/PIL/TiffTags.py index c047f42b6eb..6cc9ff7f349 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 daa806a8b5d..d5a5c8e67bb 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -1,4 +1,3 @@ -# encoding: utf-8 # # The Python Imaging Library. # $Id$ diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index 18eda6d1848..eda6855087d 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -105,7 +105,7 @@ def is_animated(self): 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 @@ def load(self): 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 be07a747bb2..4818c00b0c2 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -19,8 +19,6 @@ # 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 @@ -44,7 +42,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"] @@ -154,7 +152,7 @@ def _load(self): 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/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index bc825c3f312..22b8fe34e72 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -73,7 +73,7 @@ def _open(self): 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/_util.py b/src/PIL/_util.py index 127e94d824b..95bb457af11 100644 --- a/src/PIL/_util.py +++ b/src/PIL/_util.py @@ -26,7 +26,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 9fd52236807..a5ab108de84 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/winbuild/build.py b/winbuild/build.py index f4561d933b8..caa63c43744 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,7 +98,7 @@ 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: @@ -157,7 +157,7 @@ def main(op): scripts.append( ( - "%s%s" % (py_version, X64_EXT), + "{}{}".format(py_version, X64_EXT), "\n".join( [ header(op), @@ -171,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 487329db8b5..b5ece5f068b 100644 --- a/winbuild/build_dep.py +++ b/winbuild/build_dep.py @@ -103,7 +103,7 @@ def header(): 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"] ) diff --git a/winbuild/config.py b/winbuild/config.py index 46c9f9b2b13..e1f18121024 100644 --- a/winbuild/config.py +++ b/winbuild/config.py @@ -136,7 +136,7 @@ def pyversion_from_env(): 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/test.py b/winbuild/test.py index 559ecdec10d..a05a20b1892 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 @@ def test_one(params): 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) From 74d2767c575779cfd4c6bb9685d7adde953c9a5a Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 2 Oct 2019 14:16:04 +0300 Subject: [PATCH 03/18] Remove duplicate line --- Tests/test_file_libtiff.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 881d9096cc1..f92fc3b9b12 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -260,7 +260,6 @@ def test_custom_metadata(self): tc(4.25, TiffTags.FLOAT, True), tc(4.25, TiffTags.DOUBLE, True), tc("custom tag value", TiffTags.ASCII, True), - tc("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), From 810b61e78f873cc973407c4010fc0579e712b8a2 Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 2 Oct 2019 18:11:35 +0300 Subject: [PATCH 04/18] Reinstate and simplify parallel auto-detection --- setup.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/setup.py b/setup.py index c3e0dfc9fe1..c72e029665e 100755 --- a/setup.py +++ b/setup.py @@ -326,6 +326,15 @@ def finalize_options(self): if self.debug: global DEBUG DEBUG = True + 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) From 7e3156eb173c00d8cac0961d44e0d9c1f1dbcd8f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 7 Oct 2019 20:09:16 +1100 Subject: [PATCH 05/18] Updated IFDRational operators --- src/PIL/TiffImagePlugin.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 0fffbfb147f..59d323fc26d 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -358,10 +358,10 @@ def delegate(self, *args): 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)) """ @@ -370,8 +370,6 @@ def delegate(self, *args): __radd__ = _delegate("__radd__") __sub__ = _delegate("__sub__") __rsub__ = _delegate("__rsub__") - __div__ = _delegate("__div__") - __rdiv__ = _delegate("__rdiv__") __mul__ = _delegate("__mul__") __rmul__ = _delegate("__rmul__") __truediv__ = _delegate("__truediv__") @@ -390,7 +388,7 @@ def delegate(self, *args): __gt__ = _delegate("__gt__") __le__ = _delegate("__le__") __ge__ = _delegate("__ge__") - __nonzero__ = _delegate("__nonzero__") + __bool__ = _delegate("__bool__") __ceil__ = _delegate("__ceil__") __floor__ = _delegate("__floor__") __round__ = _delegate("__round__") From 865b17d5cf8682cc77889ba26db36f486a6cf6f3 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 7 Oct 2019 15:34:12 +0300 Subject: [PATCH 06/18] Remove Python 2-compatibility code --- Tests/test_file_png.py | 4 +--- Tests/test_imagefont.py | 5 +---- src/PIL/ImageQt.py | 6 +----- src/PIL/PdfParser.py | 12 ++---------- src/PIL/TiffImagePlugin.py | 2 +- 5 files changed, 6 insertions(+), 23 deletions(-) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 3f5f003aca3..26c40ab44af 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -448,9 +448,7 @@ def test_nonunicode_text(self): 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)) diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 6daac701baf..d2e24836e3f 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -463,10 +463,7 @@ def test_unicode_pilfont(self): with self.assertRaises(UnicodeEncodeError): font.getsize("’") - @unittest.skipIf( - sys.version.startswith("2") or hasattr(sys, "pypy_translation_info"), - "requires CPython 3.3+", - ) + @unittest.skipIf(hasattr(sys, "pypy_translation_info"), "requires CPython") def test_unicode_extended(self): # issue #3777 text = "A\u278A\U0001F12B" diff --git a/src/PIL/ImageQt.py b/src/PIL/ImageQt.py index ce34b0a043a..f19ad3df989 100644 --- a/src/PIL/ImageQt.py +++ b/src/PIL/ImageQt.py @@ -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) diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 6e054af0899..3267ee49152 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -7,11 +7,6 @@ import time import zlib -try: - from UserDict import UserDict # Python 2.x -except ImportError: - UserDict = collections.UserDict # Python 3.x - def make_bytes(s): return s.encode("us-ascii") @@ -256,13 +251,10 @@ def __bytes__(self): __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 diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 59d323fc26d..1094a6072e2 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1027,7 +1027,7 @@ def _seek(self, frame): "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) From 4382413bb4bd7986e24cc838ff41181416a2d28f Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 7 Oct 2019 15:40:00 +0300 Subject: [PATCH 07/18] Remove redundant bytearray --- Tests/test_file_gif.py | 14 ++++++-------- Tests/test_lib_pack.py | 4 ++-- src/PIL/TiffImagePlugin.py | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 8be614412a3..68301a84f3c 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -71,9 +71,7 @@ def test_optimize_correctness(self): 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() @@ -103,7 +101,7 @@ def check(colors, size, expected_palette_length): 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,7 +630,7 @@ def test_transparent_optimize(self): # 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)) @@ -680,7 +678,7 @@ def test_palette_save_L(self): 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) @@ -695,7 +693,7 @@ def test_palette_save_P(self): # 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) @@ -736,7 +734,7 @@ def test_getdata(self): 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_lib_pack.py b/Tests/test_lib_pack.py index 6178184bc1d..45958d2eb1a 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -18,7 +18,7 @@ def assert_pack(self, mode, rawmode, data, *pixels): 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 @@ def assert_unpack(self, mode, rawmode, data, *pixels): """ 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/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 1094a6072e2..a6fa412ca96 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1742,7 +1742,7 @@ def goToEnd(self): # 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): From 84e53e375799639153756a586ddceab3a94539ad Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 8 Oct 2019 11:24:36 +0300 Subject: [PATCH 08/18] Simplify using subprocess.DEVNULL Co-Authored-By: Jon Dufresne --- Tests/helper.py | 9 ++++----- setup.py | 6 +++--- src/PIL/EpsImagePlugin.py | 3 +-- src/PIL/GifImagePlugin.py | 18 +++++++++--------- src/PIL/IcnsImagePlugin.py | 7 +++---- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 302e1f6acfb..2c9ec331e52 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -321,11 +321,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 diff --git a/setup.py b/setup.py index c72e029665e..ff68b1e8b7b 100755 --- a/setup.py +++ b/setup.py @@ -164,10 +164,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() diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index 6d85da988ee..e38de58cfe1 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -57,8 +57,7 @@ def has_ghostscript(): return True if not sys.platform.startswith("win"): try: - with open(os.devnull, "wb") as devnull: - subprocess.check_call(["gs", "--version"], stdout=devnull) + subprocess.check_call(["gs", "--version"], stdout=subprocess.DEVNULL) return True except OSError: # No Ghostscript diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 2024e025dd9..3079cc95043 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -623,20 +623,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() diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index efa7f3c2bf4..b80ac2179b5 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -336,10 +336,9 @@ def _save(im, fp, filename): # iconutil -c icns -o {} {} convert_cmd = ["iconutil", "-c", "icns", "-o", filename, iconset] - with open(os.devnull, "wb") as devnull: - convert_proc = subprocess.Popen( - convert_cmd, stdout=subprocess.PIPE, stderr=devnull - ) + convert_proc = subprocess.Popen( + convert_cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL + ) convert_proc.stdout.close() From 3a34081db5762b18e630d7b313dc75e4bebe0c31 Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 8 Oct 2019 16:32:42 +0300 Subject: [PATCH 09/18] Simplify temporary directory cleanup Co-Authored-By: Jon Dufresne --- Tests/test_file_pdf.py | 5 +-- src/PIL/IcnsImagePlugin.py | 63 +++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 0158807f7f5..3547a59381f 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -162,13 +162,10 @@ def test_pdf_open(self): 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) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index b80ac2179b5..18e8403d1f5 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -314,41 +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) - - 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 - - # iconutil -c icns -o {} {} - - convert_cmd = ["iconutil", "-c", "icns", "-o", filename, iconset] - convert_proc = subprocess.Popen( - convert_cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL - ) - - convert_proc.stdout.close() + 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) + + 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 {} {} + + convert_cmd = ["iconutil", "-c", "icns", "-o", filename, iconset] + convert_proc = subprocess.Popen( + convert_cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL + ) - retcode = convert_proc.wait() + convert_proc.stdout.close() - # remove the temporary files - shutil.rmtree(iconset) + retcode = convert_proc.wait() - 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") From 0caa48b179eb8d9b3baa26d1f4d9c44f3bd46101 Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 8 Oct 2019 16:41:57 +0300 Subject: [PATCH 10/18] Remove redundant __future__ from docs Co-Authored-By: Jon Dufresne --- docs/handbook/tutorial.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/handbook/tutorial.rst b/docs/handbook/tutorial.rst index 16090b040c2..e57bc440f9d 100644 --- a/docs/handbook/tutorial.rst +++ b/docs/handbook/tutorial.rst @@ -18,7 +18,6 @@ in the :py:mod:`~PIL.Image` module:: If successful, this function returns an :py:class:`~PIL.Image.Image` object. You can now use instance attributes to examine the file contents:: - >>> 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 @@ -513,7 +509,6 @@ This is only available for JPEG and MPO files. :: from PIL import Image - from __future__ import print_function im = Image.open(file) print("original =", im.mode, im.size) From e118de943d20690e9957dc902c9ec44e4754e784 Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 8 Oct 2019 16:55:22 +0300 Subject: [PATCH 11/18] Remove redundant __ne__ method Co-Authored-By: Jon Dufresne --- src/PIL/Image.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 494be337a0e..6468fbddb02 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -646,10 +646,6 @@ def __eq__(self, other): 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__, From 3e24c5fea42a84fe18b7e6c08e6316addd1bb127 Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 8 Oct 2019 17:01:11 +0300 Subject: [PATCH 12/18] Replace isStringType(t) with isinstance(t, str) Co-Authored-By: Jon Dufresne --- Tests/test_util.py | 20 -------------------- src/PIL/Image.py | 8 ++++---- src/PIL/ImageCms.py | 3 +-- src/PIL/ImageDraw.py | 5 ++--- src/PIL/ImageOps.py | 3 +-- src/PIL/JpegImagePlugin.py | 5 ++--- src/PIL/_util.py | 4 ---- 7 files changed, 10 insertions(+), 38 deletions(-) diff --git a/Tests/test_util.py b/Tests/test_util.py index 5ec21a77cbc..cb2101e1d4b 100644 --- a/Tests/test_util.py +++ b/Tests/test_util.py @@ -4,26 +4,6 @@ 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/src/PIL/Image.py b/src/PIL/Image.py index 6468fbddb02..26194b9985c 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -43,7 +43,7 @@ # Use __version__ instead. from . import ImageMode, TiffTags, __version__, _plugins from ._binary import i8, i32le -from ._util import deferred_error, isPath, isStringType +from ._util import deferred_error, isPath logger = logging.getLogger(__name__) @@ -1466,7 +1466,7 @@ def paste(self, im, box=None, mask=None): 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) @@ -2120,7 +2120,7 @@ def getchannel(self, channel): """ self.load() - if isStringType(channel): + if isinstance(channel, str): try: channel = self.getbands().index(channel) except ValueError: @@ -2447,7 +2447,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 diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 89a4426fa78..d05b3102ca8 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -18,7 +18,6 @@ import sys from PIL import Image -from PIL._util import isStringType try: from PIL import _imagingcms @@ -159,7 +158,7 @@ def __init__(self, profile): """ - 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())) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 65e4d7ac97f..3ece201521b 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -34,7 +34,6 @@ import numbers from . import Image, ImageColor -from ._util import isStringType """ @@ -107,13 +106,13 @@ def _getink(self, ink, fill=None): 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) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 5a06adaf3a6..3ffe50806c2 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -21,7 +21,6 @@ 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) diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index 22ec5ceb90c..17cb0c412b5 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -41,7 +41,6 @@ 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 @@ -638,7 +637,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": @@ -659,7 +658,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/_util.py b/src/PIL/_util.py index 95bb457af11..755b4b27233 100644 --- a/src/PIL/_util.py +++ b/src/PIL/_util.py @@ -4,10 +4,6 @@ py36 = sys.version_info[0:2] >= (3, 6) -def isStringType(t): - return isinstance(t, str) - - if py36: from pathlib import Path From 23fa3c69790521873425bedf63319f0409bc9938 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 12 Oct 2019 14:16:10 +0300 Subject: [PATCH 13/18] Remove outdated OS scripts, point docs to Dockerfiles --- depends/alpine_Dockerfile | 43 --------------------------------------- depends/debian_8.2.sh | 18 ---------------- depends/fedora_23.sh | 18 ---------------- depends/freebsd_10.sh | 13 ------------ depends/ubuntu_12.04.sh | 17 ---------------- depends/ubuntu_14.04.sh | 16 --------------- docs/installation.rst | 7 +++---- 7 files changed, 3 insertions(+), 129 deletions(-) delete mode 100644 depends/alpine_Dockerfile delete mode 100755 depends/debian_8.2.sh delete mode 100755 depends/fedora_23.sh delete mode 100755 depends/freebsd_10.sh delete mode 100755 depends/ubuntu_12.04.sh delete mode 100755 depends/ubuntu_14.04.sh diff --git a/depends/alpine_Dockerfile b/depends/alpine_Dockerfile deleted file mode 100644 index 69bdf84f6cc..00000000000 --- 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 c4f72bf8ee5..00000000000 --- 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 5bdcf7f174a..00000000000 --- 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 36d9c106913..00000000000 --- 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 9bfae43b0bc..00000000000 --- 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 f7d28fba71b..00000000000 --- 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/installation.rst b/docs/installation.rst index 35547cb55fa..baca3629bf8 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -123,10 +123,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: From 3dac6e2c6284d5c013c6b4dce03b70070198892d Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 12 Oct 2019 21:40:11 +0300 Subject: [PATCH 14/18] Replace ImageShow.which() with stdlib Co-Authored-By: Jon Dufresne --- src/PIL/ImageShow.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index 2999d20876c..f7e809279e4 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -12,6 +12,7 @@ # See the README file for information on usage and redistribution. # import os +import shutil import subprocess import sys import tempfile @@ -145,16 +146,6 @@ def show_file(self, file, **options): # 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} @@ -183,7 +174,7 @@ def get_command_ex(self, file, **options): command = executable = "display" return command, executable - if which("display"): + if shutil.which("display"): register(DisplayViewer) class EogViewer(UnixViewer): @@ -191,7 +182,7 @@ def get_command_ex(self, file, **options): command = executable = "eog" return command, executable - if which("eog"): + if shutil.which("eog"): register(EogViewer) class XVViewer(UnixViewer): @@ -203,7 +194,7 @@ def get_command_ex(self, file, title=None, **options): command += " -name %s" % quote(title) return command, executable - if which("xv"): + if shutil.which("xv"): register(XVViewer) if __name__ == "__main__": From b4f93cf140faeaab59a46924d01694f106d165e2 Mon Sep 17 00:00:00 2001 From: Hugo Date: Fri, 1 Nov 2019 13:54:19 +0200 Subject: [PATCH 15/18] Upgrade Python syntax with pyupgrade --py3-plus --- Tests/test_image_fromqimage.py | 2 +- Tests/test_imageops_usm.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/test_image_fromqimage.py b/Tests/test_image_fromqimage.py index bf3a250f3f2..0d961572cde 100644 --- a/Tests/test_image_fromqimage.py +++ b/Tests/test_image_fromqimage.py @@ -6,7 +6,7 @@ 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_imageops_usm.py b/Tests/test_imageops_usm.py index 4ed8a83a789..71e85868184 100644 --- a/Tests/test_imageops_usm.py +++ b/Tests/test_imageops_usm.py @@ -5,7 +5,7 @@ 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") From 6f88d8dd6bf8526c760f311820296833807d18b0 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 2 Nov 2019 20:02:07 +0200 Subject: [PATCH 16/18] black --target-version py35 --- src/PIL/ImageDraw.py | 4 ++-- src/PIL/ImageFilter.py | 2 +- tox.ini | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 3ece201521b..c6e12150e8a 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -313,7 +313,7 @@ def draw_text(ink, stroke_width=0, stroke_offset=None): language=language, stroke_width=stroke_width, *args, - **kwargs + **kwargs, ) coord = coord[0] + offset[0], coord[1] + offset[1] except AttributeError: @@ -326,7 +326,7 @@ def draw_text(ink, stroke_width=0, stroke_offset=None): language, stroke_width, *args, - **kwargs + **kwargs, ) except TypeError: mask = font.getmask(text) diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index 9cb62ad2748..6b0f5eb376b 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -495,7 +495,7 @@ def transform(self, callback, with_normals=False, channels=None, target_mode=Non r / (size1D - 1), g / (size2D - 1), b / (size3D - 1), - *values + *values, ) else: values = callback(*values) diff --git a/tox.ini b/tox.ini index 0bf833b815f..07d75be64a4 100644 --- a/tox.ini +++ b/tox.ini @@ -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 From 58e6d127b7631fcbab6e42263482b229c7316e35 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 3 Nov 2019 16:02:08 +0200 Subject: [PATCH 17/18] In Python 3, 'next' is renamed to '__next__' --- src/PIL/ImageSequence.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index 28a54c7b056..4e9f5c210b7 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -52,9 +52,6 @@ def __next__(self): except EOFError: raise StopIteration - def next(self): - return self.__next__() - def all_frames(im, func=None): """ From 24b8501d4b01f80181820aea8ed23472474db79a Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 4 Nov 2019 00:32:33 +0200 Subject: [PATCH 18/18] Remove handling for pre-3.3 wide/narrow builds --- src/PIL/Image.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 0374d1583db..2d73d8f53e5 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -88,22 +88,6 @@ class DecompressionBombError(Exception): ) 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