From 099d696dc7d3c349265ae3cdbb5f949bca1e2866 Mon Sep 17 00:00:00 2001 From: rrcgat Date: Sat, 15 Apr 2023 18:24:19 +0800 Subject: [PATCH 01/18] Fix ImageGrab with wl-paste --- Tests/test_imagegrab.py | 19 +++++++++++++++++++ src/PIL/ImageGrab.py | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index fa88065f4..e7c2c6c9f 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -98,3 +98,22 @@ $ms = new-object System.IO.MemoryStream(, $bytes) im = ImageGrab.grabclipboard() assert_image_equal_tofile(im, "Tests/images/hopper.png") + + @pytest.mark.skipif( + ( + sys.platform != "linux" + or not all(shutil.which(cmd) for cmd in ["wl-paste", "wl-copy"]) + ), + reason="Linux with wl-clipboard only", + ) + @pytest.mark.parametrize( + "image_path", ["Tests/images/hopper.gif", "Tests/images/hopper.png"] + ) + def test_grabclipboard_wl_clipboard(self, image_path): + with open(image_path, mode="rb") as raw_image: + try: + subprocess.call(["wl-copy"], stdin=raw_image) + im = ImageGrab.grabclipboard() + assert_image_equal_tofile(im, image_path) + except OSError as e: + pytest.skip(str(e)) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index 982f77f20..175eb4671 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -135,6 +135,12 @@ def grabclipboard(): else: if shutil.which("wl-paste"): args = ["wl-paste"] + output = subprocess.check_output(["wl-paste", "-l"]).decode() + mime_types = output.splitlines() + for image_type in ["image/gif", "image/png"]: + if image_type in mime_types: + args.extend(["-t", image_type]) + break elif shutil.which("xclip"): args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"] else: From 6d12581385688c3af964e6707a1b4ed2651d31a5 Mon Sep 17 00:00:00 2001 From: Carl Weaver Date: Sun, 16 Apr 2023 15:37:38 +0800 Subject: [PATCH 02/18] Update src/PIL/ImageGrab.py Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- src/PIL/ImageGrab.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index 175eb4671..6550a7706 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -136,10 +136,11 @@ def grabclipboard(): if shutil.which("wl-paste"): args = ["wl-paste"] output = subprocess.check_output(["wl-paste", "-l"]).decode() - mime_types = output.splitlines() - for image_type in ["image/gif", "image/png"]: - if image_type in mime_types: - args.extend(["-t", image_type]) + clipboard_mimetypes = output.splitlines() + Image.preinit() + for mimetype in Image.MIME.values(): + if mimetype in clipboard_mimetypes: + args.extend(["-t", mimetype]) break elif shutil.which("xclip"): args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"] From 3d54b8e2b2419255a6b5a74dd0f2841ea4de7416 Mon Sep 17 00:00:00 2001 From: rrcgat Date: Sun, 16 Apr 2023 15:41:14 +0800 Subject: [PATCH 03/18] Remove useless try catch block --- Tests/test_imagegrab.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index e7c2c6c9f..703472c4a 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -111,9 +111,6 @@ $ms = new-object System.IO.MemoryStream(, $bytes) ) def test_grabclipboard_wl_clipboard(self, image_path): with open(image_path, mode="rb") as raw_image: - try: - subprocess.call(["wl-copy"], stdin=raw_image) - im = ImageGrab.grabclipboard() - assert_image_equal_tofile(im, image_path) - except OSError as e: - pytest.skip(str(e)) + subprocess.call(["wl-copy"], stdin=raw_image) + im = ImageGrab.grabclipboard() + assert_image_equal_tofile(im, image_path) From aa2e662995eaf67e2f9f53d6817a173c12b45a19 Mon Sep 17 00:00:00 2001 From: rrcgat Date: Mon, 17 Apr 2023 16:44:43 +0800 Subject: [PATCH 04/18] Add sway and wl-clipboard dependencies to GitHub CI workflow --- .ci/install.sh | 3 ++- .github/workflows/test.yml | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.ci/install.sh b/.ci/install.sh index 17c349ab1..d5cbd8248 100755 --- a/.ci/install.sh +++ b/.ci/install.sh @@ -22,7 +22,8 @@ set -e if [[ $(uname) != CYGWIN* ]]; then sudo apt-get -qq install libfreetype6-dev liblcms2-dev python3-tk\ ghostscript libffi-dev libjpeg-turbo-progs libopenjp2-7-dev\ - cmake meson imagemagick libharfbuzz-dev libfribidi-dev + cmake meson imagemagick libharfbuzz-dev libfribidi-dev\ + sway wl-clipboard fi python3 -m pip install --upgrade pip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fced6113b..53b7ee688 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,7 +84,15 @@ jobs: python3 -m pip install pytest-reverse fi if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then - xvfb-run -s '-screen 0 1024x768x24' .ci/test.sh + export XDG_RUNTIME_DIR="/tmp/headless-sway" + export SWAYSOCK="$XDG_RUNTIME_DIR/sway.sock" + export WLR_BACKENDS=headless + export WLR_LIBINPUT_NO_DEVICES=1 + mkdir "$XDG_RUNTIME_DIR" + xvfb-run -s '-screen 0 1024x768x24'\ + sway -V -d -c /dev/null& + export WAYLAND_DISPLAY=wayland-1 + .ci/test.sh else .ci/test.sh fi From b7585b0597855f15ccf998d84684d90488a1133a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 18 Apr 2023 10:27:36 +1000 Subject: [PATCH 05/18] Removed unnecessary settings --- .github/workflows/test.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 53b7ee688..afb8fb56c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,13 +84,7 @@ jobs: python3 -m pip install pytest-reverse fi if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then - export XDG_RUNTIME_DIR="/tmp/headless-sway" - export SWAYSOCK="$XDG_RUNTIME_DIR/sway.sock" - export WLR_BACKENDS=headless - export WLR_LIBINPUT_NO_DEVICES=1 - mkdir "$XDG_RUNTIME_DIR" - xvfb-run -s '-screen 0 1024x768x24'\ - sway -V -d -c /dev/null& + xvfb-run -s '-screen 0 1024x768x24' sway& export WAYLAND_DISPLAY=wayland-1 .ci/test.sh else From f15d7265f779c04d4e01b425f1e8b7211422a7dd Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 18 Apr 2023 10:33:31 +1000 Subject: [PATCH 06/18] Call init() if mimetype is not found with preinit() --- Tests/test_imagegrab.py | 11 +++++------ src/PIL/ImageGrab.py | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index 703472c4a..065c9c1b5 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -106,11 +106,10 @@ $ms = new-object System.IO.MemoryStream(, $bytes) ), reason="Linux with wl-clipboard only", ) - @pytest.mark.parametrize( - "image_path", ["Tests/images/hopper.gif", "Tests/images/hopper.png"] - ) - def test_grabclipboard_wl_clipboard(self, image_path): - with open(image_path, mode="rb") as raw_image: - subprocess.call(["wl-copy"], stdin=raw_image) + @pytest.mark.parametrize("ext", ("gif", "png", "ico")) + def test_grabclipboard_wl_clipboard(self, ext): + image_path = "Tests/images/hopper." + ext + with open(image_path, "rb") as fp: + subprocess.call(["wl-copy"], stdin=fp) im = ImageGrab.grabclipboard() assert_image_equal_tofile(im, image_path) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index 6550a7706..55b50fb48 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -137,11 +137,19 @@ def grabclipboard(): args = ["wl-paste"] output = subprocess.check_output(["wl-paste", "-l"]).decode() clipboard_mimetypes = output.splitlines() + + def find_mimetype(): + for mime in Image.MIME.values(): + if mime in clipboard_mimetypes: + return mime + Image.preinit() - for mimetype in Image.MIME.values(): - if mimetype in clipboard_mimetypes: - args.extend(["-t", mimetype]) - break + mimetype = find_mimetype() + if not mimetype: + Image.init() + mimetype = find_mimetype() + if mimetype: + args.extend(["-t", mimetype]) elif shutil.which("xclip"): args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"] else: From 546f6cbc27e178bfc742d8216a1af508b3e26e02 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 20 May 2023 17:11:43 +1000 Subject: [PATCH 07/18] Replaced absolute PIL import with relative import --- src/PIL/IcnsImagePlugin.py | 4 ++-- src/PIL/ImageCms.py | 6 +++--- src/PIL/ImageShow.py | 2 +- src/PIL/SpiderImagePlugin.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index c2f050edd..27cb89f73 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -22,11 +22,11 @@ import os import struct import sys -from PIL import Image, ImageFile, PngImagePlugin, features +from . import Image, ImageFile, PngImagePlugin, features enable_jpeg2k = features.check_codec("jpg_2000") if enable_jpeg2k: - from PIL import Jpeg2KImagePlugin + from . import Jpeg2KImagePlugin MAGIC = b"icns" HEADERSIZE = 8 diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 38cbab19c..3a337f9f2 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -18,10 +18,10 @@ import sys from enum import IntEnum -from PIL import Image +from . import Image try: - from PIL import _imagingcms + from . import _imagingcms except ImportError as ex: # Allow error import for doc purposes, but error out when accessing # anything in core. @@ -271,7 +271,7 @@ def get_display_profile(handle=None): if sys.platform != "win32": return None - from PIL import ImageWin + from . import ImageWin if isinstance(handle, ImageWin.HDC): profile = core.get_display_profile_win32(handle, 1) diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index 3f68a2696..8b1c3f8bb 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -17,7 +17,7 @@ import subprocess import sys from shlex import quote -from PIL import Image +from . import Image _viewers = [] diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index eac27e679..5614957c1 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -36,7 +36,7 @@ import os import struct import sys -from PIL import Image, ImageFile +from . import Image, ImageFile def isInt(f): @@ -191,7 +191,7 @@ class SpiderImageFile(ImageFile.ImageFile): # returns a ImageTk.PhotoImage object, after rescaling to 0..255 def tkPhotoImage(self): - from PIL import ImageTk + from . import ImageTk return ImageTk.PhotoImage(self.convert2byte(), palette=256) From dc6d0641b3c5e93b26b214a251754e549b84260a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 22 May 2023 19:39:25 +1000 Subject: [PATCH 08/18] Updated redirected URLs --- codecov.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codecov.yml b/codecov.yml index f3afccc1c..b794632fa 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,9 +1,9 @@ -# Documentation: https://docs.codecov.io/docs/codecov-yaml +# Documentation: https://docs.codecov.com/docs/codecov-yaml codecov: # Avoid "Missing base report" due to committing CHANGES.rst with "[CI skip]" # https://github.com/codecov/support/issues/363 - # https://docs.codecov.io/docs/comparing-commits + # https://docs.codecov.com/docs/comparing-commits allow_coverage_offsets: true comment: false From fffcb558f64f2350789b67ec5eb55681408a93d5 Mon Sep 17 00:00:00 2001 From: rrcgat Date: Tue, 23 May 2023 18:44:25 +0800 Subject: [PATCH 09/18] Use image/png mime type for ImageGrab (wl-paste) if possible, otherwise the first mime type taken --- src/PIL/ImageGrab.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index 3771e6a79..b7f416321 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -147,15 +147,12 @@ def grabclipboard(): clipboard_mimetypes = output.splitlines() def find_mimetype(): - for mime in Image.MIME.values(): - if mime in clipboard_mimetypes: - return mime + if "image/png" in clipboard_mimetypes: + return "image/png" + if clipboard_mimetypes: + return clipboard_mimetypes[0] - Image.preinit() mimetype = find_mimetype() - if not mimetype: - Image.init() - mimetype = find_mimetype() if mimetype: args.extend(["-t", mimetype]) elif shutil.which("xclip"): From bce0f0d5a64c008b9d9ffbea33e98a79ffdae8c3 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 23 May 2023 21:25:11 +1000 Subject: [PATCH 10/18] Moved function code inline --- src/PIL/ImageGrab.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index b7f416321..7f6d50af4 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -142,17 +142,16 @@ def grabclipboard(): return None else: if shutil.which("wl-paste"): - args = ["wl-paste"] output = subprocess.check_output(["wl-paste", "-l"]).decode() - clipboard_mimetypes = output.splitlines() + mimetypes = output.splitlines() + if "image/png" in mimetypes: + mimetype = "image/png" + elif mimetypes: + mimetype = mimetypes[0] + else: + mimetype = None - def find_mimetype(): - if "image/png" in clipboard_mimetypes: - return "image/png" - if clipboard_mimetypes: - return clipboard_mimetypes[0] - - mimetype = find_mimetype() + args = ["wl-paste"] if mimetype: args.extend(["-t", mimetype]) elif shutil.which("xclip"): From 26d5f4fcb1fa23c920f42c56e187de092da544a7 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 23 May 2023 21:27:55 +1000 Subject: [PATCH 11/18] Use tuple instead of list --- Tests/test_imagegrab.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index 065c9c1b5..f8059eca4 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -102,7 +102,7 @@ $ms = new-object System.IO.MemoryStream(, $bytes) @pytest.mark.skipif( ( sys.platform != "linux" - or not all(shutil.which(cmd) for cmd in ["wl-paste", "wl-copy"]) + or not all(shutil.which(cmd) for cmd in ("wl-paste", "wl-copy")) ), reason="Linux with wl-clipboard only", ) @@ -111,5 +111,5 @@ $ms = new-object System.IO.MemoryStream(, $bytes) image_path = "Tests/images/hopper." + ext with open(image_path, "rb") as fp: subprocess.call(["wl-copy"], stdin=fp) - im = ImageGrab.grabclipboard() - assert_image_equal_tofile(im, image_path) + im = ImageGrab.grabclipboard() + assert_image_equal_tofile(im, image_path) From 117618b01f959f016833158b7b128e896c6d38b6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 24 May 2023 22:47:43 +1000 Subject: [PATCH 12/18] Update CHANGES.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 626b8b231..190751ad2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Changelog (Pillow) 10.0.0 (unreleased) ------------------- +- Improved wl-paste mimetype handling in ImageGrab #7094 + [rrcgat, radarhere] + - Added _repr_jpeg_() for IPython display_jpeg #7135 [n3011, radarhere, nulano] From e6d7f1f3477b915d4f2fb7d71d609af74e47a444 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 26 May 2023 19:52:13 +1000 Subject: [PATCH 13/18] Install setuptools on Windows --- .github/workflows/test-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index a00880111..076b80839 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -65,8 +65,8 @@ jobs: - name: Print build system information run: python3 .github/workflows/system-info.py - - name: python3 -m pip install wheel pytest pytest-cov pytest-timeout defusedxml - run: python3 -m pip install wheel pytest pytest-cov pytest-timeout defusedxml + - name: python3 -m pip install setuptools wheel pytest pytest-cov pytest-timeout defusedxml + run: python3 -m pip install setuptools wheel pytest pytest-cov pytest-timeout defusedxml - name: Install dependencies id: install From 7a5ddc1712240b21d89581602acbb851c3897e4a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 27 May 2023 10:28:38 +1000 Subject: [PATCH 14/18] Do not test PyQt6 on Python 3.12 --- .ci/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/install.sh b/.ci/install.sh index d5cbd8248..6e87d386d 100755 --- a/.ci/install.sh +++ b/.ci/install.sh @@ -42,7 +42,7 @@ if [[ $(uname) != CYGWIN* ]]; then if ! [ "$GHA_PYTHON_VERSION" == "3.12-dev" ]; then python3 -m pip install numpy ; fi # PyQt6 doesn't support PyPy3 - if [[ $GHA_PYTHON_VERSION == 3.* ]]; then + if [[ "$GHA_PYTHON_VERSION" != "3.12-dev" && $GHA_PYTHON_VERSION == 3.* ]]; then sudo apt-get -qq install libegl1 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxkbcommon-x11-0 python3 -m pip install pyqt6 fi From c45019fe0ccbf54c925aba914329371a7f188a48 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 29 May 2023 12:28:03 +1000 Subject: [PATCH 15/18] Replaced deprecated Py_FileSystemDefaultEncoding for Python >= 3.12 --- src/_imagingft.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/_imagingft.c b/src/_imagingft.c index 78e3f7f10..80f862bb7 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -132,6 +132,27 @@ getfont(PyObject *self_, PyObject *args, PyObject *kw) { return NULL; } +#if PY_MAJOR_VERSION > 3 || PY_MINOR_VERSION > 11 + PyConfig config; + PyConfig_InitPythonConfig(&config); + if (!PyArg_ParseTupleAndKeywords( + args, + kw, + "etf|nsy#n", + kwlist, + config.filesystem_encoding, + &filename, + &size, + &index, + &encoding, + &font_bytes, + &font_bytes_size, + &layout_engine)) { + PyConfig_Clear(&config); + return NULL; + } + PyConfig_Clear(&config); +#else if (!PyArg_ParseTupleAndKeywords( args, kw, @@ -147,6 +168,7 @@ getfont(PyObject *self_, PyObject *args, PyObject *kw) { &layout_engine)) { return NULL; } +#endif self = PyObject_New(FontObject, &Font_Type); if (!self) { From e01a0195dd9f54b8174f322d47d4f618f0cf6c50 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 1 Jun 2023 22:53:07 +1000 Subject: [PATCH 16/18] Removed duplicate config --- .editorconfig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index 449530717..d74549fe2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,10 +13,6 @@ indent_style = space trim_trailing_whitespace = true -[*.rst] -# Four-space indentation -indent_size = 4 - [*.yml] # Two-space indentation indent_size = 2 From ea3e4242d8fd8bb5cfc9e528f863ce16e20b529f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 2 Jun 2023 08:07:05 +1000 Subject: [PATCH 17/18] Removed files and types override --- .pre-commit-config.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4882a317f..0ddc6beb4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,9 +4,6 @@ repos: hooks: - id: black args: [--target-version=py38] - # Only .py files, until https://github.com/psf/black/issues/402 resolved - files: \.py$ - types: [] - repo: https://github.com/PyCQA/isort rev: 5.12.0 From 3693b84ba0b44f71119cec73c8517ec32d1774b5 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 2 Jun 2023 09:21:47 +1000 Subject: [PATCH 18/18] Lint fixes --- docs/Guardfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/Guardfile b/docs/Guardfile index b689b079a..6cbf07b06 100755 --- a/docs/Guardfile +++ b/docs/Guardfile @@ -2,7 +2,7 @@ from livereload.compiler import shell from livereload.task import Task -Task.add('*.rst', shell('make html')) -Task.add('*/*.rst', shell('make html')) -Task.add('Makefile', shell('make html')) -Task.add('conf.py', shell('make html')) +Task.add("*.rst", shell("make html")) +Task.add("*/*.rst", shell("make html")) +Task.add("Makefile", shell("make html")) +Task.add("conf.py", shell("make html"))