Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update wl-paste handling and return None for some errors in grabclipboard() on Linux #7745

Merged
merged 13 commits into from
Feb 5, 2024
12 changes: 12 additions & 0 deletions Tests/test_imagegrab.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,15 @@ def test_grabclipboard_wl_clipboard(self, ext) -> None:
subprocess.call(["wl-copy"], stdin=fp)
im = ImageGrab.grabclipboard()
assert_image_equal_tofile(im, image_path)

@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("arg", ("text", "--clear"))
def test_grabclipboard_wl_clipboard_errors(self, arg):
subprocess.call(["wl-copy", arg])
assert ImageGrab.grabclipboard() is None
38 changes: 23 additions & 15 deletions src/PIL/ImageGrab.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,29 +149,37 @@
session_type = None

if shutil.which("wl-paste") and session_type in ("wayland", None):
output = subprocess.check_output(["wl-paste", "-l"]).decode()
mimetypes = output.splitlines()
if "image/png" in mimetypes:
mimetype = "image/png"
elif mimetypes:
mimetype = mimetypes[0]
else:
mimetype = None

args = ["wl-paste"]
if mimetype:
args.extend(["-t", mimetype])
args = ["wl-paste", "-t", "image"]

Check warning on line 152 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L152

Added line #L152 was not covered by tests
elif shutil.which("xclip") and session_type in ("x11", None):
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
else:
msg = "wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
raise NotImplementedError(msg)

p = subprocess.run(args, capture_output=True)
err = p.stderr
if err:
msg = f"{args[0]} error: {err.strip().decode()}"
if p.returncode != 0:
err = p.stderr
for silent_error in [

Check warning on line 162 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L160-L162

Added lines #L160 - L162 were not covered by tests
# wl-paste, when the clipboard is empty
b"Nothing is copied",
# Ubuntu/Debian wl-paste, when the clipboard is empty
b"No selection",
# Ubuntu/Debian wl-paste, when an image isn't available
b"No suitable type of content copied",
# wl-paste or Ubuntu/Debian xclip, when an image isn't available
b" not available",
# xclip, when an image isn't available
b"cannot convert ",
# xclip, when the clipboard isn't initialized
b"xclip: Error: There is no owner for the ",
]:
if silent_error in err:
return None
msg = f"{args[0]} error"
if err:
msg += f": {err.strip().decode()}"

Check warning on line 180 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L176-L180

Added lines #L176 - L180 were not covered by tests
raise ChildProcessError(msg)

data = io.BytesIO(p.stdout)
im = Image.open(data)
im.load()
Expand Down
Loading