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

Wait until executable has finished to remove file on Unix #6039

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
65 changes: 38 additions & 27 deletions src/PIL/ImageShow.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ def show(image, title=None, **options):
"""
for viewer in _viewers:
if viewer.show(image, title=title, **options):
return 1
return 0
return True
return False


class Viewer:
Expand Down Expand Up @@ -126,16 +126,6 @@ def show_file(self, path=None, **options):
os.system(self.get_command(path, **options))
return 1

def _remove_path_after_delay(self, path):
subprocess.Popen(
[
sys.executable,
"-c",
"import os, sys, time; time.sleep(20); os.remove(sys.argv[1])",
path,
]
)


# --------------------------------------------------------------------

Expand Down Expand Up @@ -190,7 +180,14 @@ def show_file(self, path=None, **options):
else:
raise TypeError("Missing required argument: 'path'")
subprocess.call(["open", "-a", "Preview.app", path])
self._remove_path_after_delay(path)
subprocess.Popen(
[
sys.executable,
"-c",
"import os, sys, time; time.sleep(20); os.remove(sys.argv[1])",
path,
]
)
return 1


Expand All @@ -206,10 +203,22 @@ def get_command(self, file, **options):
command = self.get_command_ex(file, **options)[0]
return f"({command} {quote(file)}; rm -f {quote(file)})&"

def _run_and_remove_path(self, args):
subprocess.Popen(
[
sys.executable,
"-c",
"import os, subprocess, sys;"
"subprocess.run(sys.argv[1:]); os.remove(sys.argv[-1])",
]
+ args,
stderr=subprocess.DEVNULL,
)


class XDGViewer(UnixViewer):
"""
The freedesktop.org ``xdg-open`` command.
The freedesktop.org xdg-utils.
"""

def get_command_ex(self, file, **options):
Expand All @@ -234,8 +243,14 @@ def show_file(self, path=None, **options):
path = options.pop("file")
else:
raise TypeError("Missing required argument: 'path'")
subprocess.Popen(["xdg-open", path])
self._remove_path_after_delay(path)
filetype = subprocess.run(
["xdg-mime", "query", "filetype", path], capture_output=True
).stdout.strip()
application = subprocess.run(
["xdg-mime", "query", "default", filetype], capture_output=True
).stdout.strip()
command = application[:-8].split(b".")[-1]
self._run_and_remove_path([command, path])
return 1


Expand All @@ -248,7 +263,7 @@ class DisplayViewer(UnixViewer):
def get_command_ex(self, file, title=None, **options):
command = executable = "display"
if title:
command += f" -name {quote(title)}"
command += f" -title {quote(title)}"
return command, executable

def show_file(self, path=None, **options):
Expand All @@ -270,11 +285,10 @@ def show_file(self, path=None, **options):
raise TypeError("Missing required argument: 'path'")
args = ["display"]
if "title" in options:
args += ["-name", options["title"]]
args += ["-title", options["title"]]
args.append(path)

subprocess.Popen(args)
os.remove(path)
self._run_and_remove_path(args)
return 1


Expand Down Expand Up @@ -303,8 +317,7 @@ def show_file(self, path=None, **options):
path = options.pop("file")
else:
raise TypeError("Missing required argument: 'path'")
subprocess.Popen(["gm", "display", path])
os.remove(path)
self._run_and_remove_path(["gm", "display", path])
return 1


Expand Down Expand Up @@ -333,8 +346,7 @@ def show_file(self, path=None, **options):
path = options.pop("file")
else:
raise TypeError("Missing required argument: 'path'")
subprocess.Popen(["eog", "-n", path])
os.remove(path)
self._run_and_remove_path(["eog", "-n", path])
return 1


Expand Down Expand Up @@ -374,13 +386,12 @@ def show_file(self, path=None, **options):
args += ["-name", options["title"]]
args.append(path)

subprocess.Popen(args)
os.remove(path)
self._run_and_remove_path(args)
return 1


if sys.platform not in ("win32", "darwin"): # unixoids
if shutil.which("xdg-open"):
if shutil.which("xdg-open") and shutil.which("xdg-mime"):
register(XDGViewer)
if shutil.which("display"):
register(DisplayViewer)
Expand Down