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

Make progress reports work on Qubes #450

Merged
merged 2 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions dangerzone/conversion/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ async def run_command(


class DangerzoneConverter:
def __init__(self) -> None:
def __init__(self, progress_callback: Optional[Callable] = None) -> None:
self.percentage: float = 0.0
self.progress_callback = progress_callback

def calculate_timeout(
self, size: float, pages: Optional[float] = None
Expand Down Expand Up @@ -134,7 +135,10 @@ async def convert(self) -> None:
pass

def update_progress(self, text: str, *, error: bool = False) -> None:
if not running_on_qubes():
if running_on_qubes():
if self.progress_callback:
self.progress_callback(error, text, int(self.percentage))
else:
print(
json.dumps(
{"error": error, "text": text, "percentage": int(self.percentage)}
Expand Down
4 changes: 2 additions & 2 deletions dangerzone/gui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,11 +680,11 @@ def convert_document(self) -> None:
self.dangerzone.isolation_provider.convert(
self.document,
self.ocr_lang,
self.stdout_callback,
self.progress_callback,
)
self.finished.emit(self.error)

def stdout_callback(self, error: bool, text: str, percentage: int) -> None:
def progress_callback(self, error: bool, text: str, percentage: int) -> None:
if error:
self.error = True

Expand Down
9 changes: 6 additions & 3 deletions dangerzone/isolation_provider/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ def convert(
self,
document: Document,
ocr_lang: Optional[str],
stdout_callback: Optional[Callable] = None,
progress_callback: Optional[Callable] = None,
) -> None:
self.progress_callback = progress_callback
document.mark_as_converting()
try:
success = self._convert(document, ocr_lang, stdout_callback)
success = self._convert(document, ocr_lang)
except Exception:
success = False
log.exception(
Expand All @@ -45,7 +46,6 @@ def _convert(
self,
document: Document,
ocr_lang: Optional[str],
stdout_callback: Optional[Callable] = None,
) -> bool:
pass

Expand All @@ -61,6 +61,9 @@ def print_progress(
s += Style.RESET_ALL + text
log.info(s)

if self.progress_callback:
self.progress_callback(error, text, percentage)

@abstractmethod
def get_max_parallel_conversions(self) -> int:
pass
Expand Down
27 changes: 9 additions & 18 deletions dangerzone/isolation_provider/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,27 +133,24 @@ def is_container_installed() -> bool:

return installed

def parse_progress(self, document: Document, line: str) -> Tuple[bool, str, int]:
def parse_progress(self, document: Document, line: str) -> None:
"""
Parses a line returned by the container.
"""
try:
status = json.loads(line)
self.print_progress(
document, status["error"], status["text"], status["percentage"]
)
except:
error_message = f"Invalid JSON returned from container:\n\n\t {line}"
log.error(error_message)
return (True, error_message, -1)

self.print_progress(
document, status["error"], status["text"], status["percentage"]
)
return (status["error"], status["text"], status["percentage"])
self.print_progress(document, True, error_message, -1)

def exec(
self,
document: Document,
args: List[str],
stdout_callback: Optional[Callable] = None,
) -> int:
args_str = " ".join(pipes.quote(s) for s in args)
log.info("> " + args_str)
Expand All @@ -169,9 +166,7 @@ def exec(
) as p:
if p.stdout is not None:
for line in p.stdout:
(error, text, percentage) = self.parse_progress(document, line)
if stdout_callback:
stdout_callback(error, text, percentage)
self.parse_progress(document, line)

p.communicate()
return p.returncode
Expand All @@ -181,7 +176,6 @@ def exec_container(
document: Document,
command: List[str],
extra_args: List[str] = [],
stdout_callback: Optional[Callable] = None,
) -> int:
container_runtime = self.get_runtime()

Expand All @@ -208,13 +202,12 @@ def exec_container(
)

args = [container_runtime] + args
return self.exec(document, args, stdout_callback)
return self.exec(document, args)

def _convert(
self,
document: Document,
ocr_lang: Optional[str],
stdout_callback: Optional[Callable] = None,
) -> bool:
# Create a temporary directory inside the cache directory for this run. Then,
# create some subdirectories for the various stages of the file conversion:
Expand All @@ -237,7 +230,6 @@ def _convert(
pixel_dir=pixel_dir,
safe_dir=safe_dir,
ocr_lang=ocr_lang,
stdout_callback=stdout_callback,
)

def _convert_with_tmpdirs(
Expand All @@ -247,7 +239,6 @@ def _convert_with_tmpdirs(
pixel_dir: pathlib.Path,
safe_dir: pathlib.Path,
ocr_lang: Optional[str],
stdout_callback: Optional[Callable] = None,
) -> bool:
success = False

Expand All @@ -273,7 +264,7 @@ def _convert_with_tmpdirs(
"-e",
f"ENABLE_TIMEOUTS={self.enable_timeouts}",
]
ret = self.exec_container(document, command, extra_args, stdout_callback)
ret = self.exec_container(document, command, extra_args)
if ret != 0:
log.error("documents-to-pixels failed")
else:
Expand All @@ -297,7 +288,7 @@ def _convert_with_tmpdirs(
"-e",
f"ENABLE_TIMEOUTS={self.enable_timeouts}",
]
ret = self.exec_container(document, command, extra_args, stdout_callback)
ret = self.exec_container(document, command, extra_args)
if ret != 0:
log.error("pixels-to-pdf failed")
else:
Expand Down
3 changes: 0 additions & 3 deletions dangerzone/isolation_provider/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def _convert(
self,
document: Document,
ocr_lang: Optional[str],
stdout_callback: Optional[Callable] = None,
) -> bool:
log.debug("Dummy converter started:")
log.debug(
Expand All @@ -58,8 +57,6 @@ def _convert(

for error, text, percentage in progress:
self.print_progress(document, error, text, percentage) # type: ignore [arg-type]
if stdout_callback:
stdout_callback(error, text, percentage)
if error:
success = False
time.sleep(0.2)
Expand Down
14 changes: 4 additions & 10 deletions dangerzone/isolation_provider/qubes.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def _convert(
self,
document: Document,
ocr_lang: Optional[str],
stdout_callback: Optional[Callable] = None,
) -> bool:
success = False

Expand Down Expand Up @@ -121,30 +120,25 @@ def _convert(

text = f"Converting page {page}/{n_pages} to pixels"
self.print_progress(document, False, text, percentage)
if stdout_callback:
stdout_callback(False, text, percentage)

# TODO handle leftover code input
text = "Converted document to pixels"
self.print_progress(document, False, text, percentage)
if stdout_callback:
stdout_callback(False, text, percentage)

# FIXME pass OCR stuff properly (see #455)
old_environ = dict(os.environ)
if ocr_lang:
os.environ["OCR"] = "1"
os.environ["OCR_LANGUAGE"] = ocr_lang

asyncio.run(
PixelsToPDF().convert()
) # TODO add progress updates on second stage
def print_progress_wrapper(error: bool, text: str, percentage: float) -> None:
self.print_progress(document, error, text, percentage)

asyncio.run(PixelsToPDF(progress_callback=print_progress_wrapper).convert())

percentage = 100.0
text = "Safe PDF created"
self.print_progress(document, False, text, percentage)
if stdout_callback:
stdout_callback(False, text, percentage)

# FIXME remove once the OCR args are no longer passed with env vars
os.environ.clear()
Expand Down