mozregression/gui/splash_hook.py

65 строки
2.1 KiB
Python

import multiprocessing as mp
import os
import subprocess
from mozregression import version
class Splash:
# Milliseconds to pass before re-checking open files.
CHECK_MILLISECONDS = 500
def __init__(self):
# Must import here to avoid multiprocess forking issue with Core Foundation.
import tkinter
# Get parent PID which will be the one extracting files, etc...
self.ppid = str(os.getppid())
# Variable to keep track of last lsof output.
self.last_lsof = None
# Create the splash screen.
self.win = tkinter.Tk()
self.win.overrideredirect(True)
tkinter.Label(self.win, text=f"mozregression {version} starting, please wait...").pack(
pady=20, padx=20
)
self.win.eval("tk::PlaceWindow . center")
self.win.after(self.CHECK_MILLISECONDS, self.check_doneness)
self.win.mainloop()
def get_lsof(self):
"""Return a list of files that are extracted by the bootloader."""
out = subprocess.check_output(["lsof", "-p", self.ppid])
lines = out.splitlines()
# _MEI is the prefix used in the temporary folder when extracting. See
# pyinstaller.org/en/stable/operating-mode.html#how-the-one-file-program-works.
relevant_lines = [line for line in lines if b"_MEI" in line]
# Return only the filenames.
parsed_lines = [line.split(b" ")[-1] for line in relevant_lines]
parsed_lines.sort()
return parsed_lines
def check_doneness(self):
"""Check whether the bootloader has finished loading files."""
# NOTE: This is a bit hacky. The output from lsof is checked every few seconds
# and if it has not changed between those two checks, assume extraction is
# complete.
parsed_lsof = self.get_lsof()
if parsed_lsof == self.last_lsof:
self.win.destroy()
else:
self.last_lsof = parsed_lsof
self.win.after(self.CHECK_MILLISECONDS, self.check_doneness)
if __name__ == "__main__":
mp.set_start_method("fork")
p = mp.Process(target=Splash)
p.start()