mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00
add type hints (1st pass: non problematic cases)
This commit is contained in:
parent
1f8e23f164
commit
d579a47a84
7 changed files with 92 additions and 69 deletions
|
@ -2,6 +2,7 @@ import json
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
import click
|
||||
from colorama import Fore, Style
|
||||
|
@ -11,7 +12,7 @@ from .container import convert
|
|||
from .global_common import GlobalCommon
|
||||
|
||||
|
||||
def print_header(s):
|
||||
def print_header(s: str) -> None:
|
||||
click.echo("")
|
||||
click.echo(Style.BRIGHT + s)
|
||||
|
||||
|
@ -20,7 +21,9 @@ def print_header(s):
|
|||
@click.option("--output-filename", help="Default is filename ending with -safe.pdf")
|
||||
@click.option("--ocr-lang", help="Language to OCR, defaults to none")
|
||||
@click.argument("filename", required=True)
|
||||
def cli_main(output_filename, ocr_lang, filename):
|
||||
def cli_main(
|
||||
output_filename: Optional[str], ocr_lang: Optional[str], filename: str
|
||||
) -> None:
|
||||
setup_logging()
|
||||
global_common = GlobalCommon()
|
||||
common = Common()
|
||||
|
@ -92,7 +95,7 @@ def cli_main(output_filename, ocr_lang, filename):
|
|||
# Convert the document
|
||||
print_header("Converting document to safe PDF")
|
||||
|
||||
def stdout_callback(line):
|
||||
def stdout_callback(line: str) -> None:
|
||||
try:
|
||||
status = json.loads(line)
|
||||
s = Style.BRIGHT + Fore.CYAN + f"{status['percentage']}% "
|
||||
|
|
|
@ -2,6 +2,7 @@ import os
|
|||
import platform
|
||||
import stat
|
||||
import tempfile
|
||||
from typing import Optional
|
||||
|
||||
import appdirs
|
||||
|
||||
|
@ -11,7 +12,7 @@ class Common(object):
|
|||
The Common class is a singleton of shared functionality throughout an open dangerzone window
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self) -> None:
|
||||
# Name of input and out files
|
||||
self.input_filename = None
|
||||
self.output_filename = None
|
||||
self.input_filename: Optional[str] = None
|
||||
self.output_filename: Optional[str] = None
|
||||
|
|
|
@ -8,6 +8,7 @@ import platform
|
|||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
import appdirs
|
||||
import colorama
|
||||
|
@ -24,7 +25,7 @@ class GlobalCommon(object):
|
|||
The GlobalCommon class is a singleton of shared functionality throughout the app
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self) -> None:
|
||||
# Version
|
||||
try:
|
||||
with open(self.get_resource_path("version.txt")) as f:
|
||||
|
@ -210,7 +211,7 @@ class GlobalCommon(object):
|
|||
# Load settings
|
||||
self.settings = Settings(self)
|
||||
|
||||
def display_banner(self):
|
||||
def display_banner(self) -> None:
|
||||
"""
|
||||
Raw ASCII art example:
|
||||
╭──────────────────────────╮
|
||||
|
@ -391,7 +392,7 @@ class GlobalCommon(object):
|
|||
else:
|
||||
return shutil.which("docker")
|
||||
|
||||
def get_resource_path(self, filename):
|
||||
def get_resource_path(self, filename: str) -> str:
|
||||
if getattr(sys, "dangerzone_dev", False):
|
||||
# Look for resources directory relative to python file
|
||||
project_root = pathlib.Path(__file__).parent.parent
|
||||
|
@ -420,12 +421,12 @@ class GlobalCommon(object):
|
|||
else:
|
||||
return None
|
||||
|
||||
def install_container(self):
|
||||
def install_container(self) -> Optional[bool]:
|
||||
"""
|
||||
Make sure the podman container is installed. Linux only.
|
||||
"""
|
||||
if self.is_container_installed():
|
||||
return
|
||||
return None
|
||||
|
||||
# Load the container into podman
|
||||
log.info("Installing Dangerzone container image...")
|
||||
|
@ -454,7 +455,7 @@ class GlobalCommon(object):
|
|||
log.info("Container image installed")
|
||||
return True
|
||||
|
||||
def is_container_installed(self):
|
||||
def is_container_installed(self) -> bool:
|
||||
"""
|
||||
See if the podman container is installed. Linux only.
|
||||
"""
|
||||
|
|
|
@ -4,6 +4,7 @@ import platform
|
|||
import signal
|
||||
import sys
|
||||
import uuid
|
||||
from typing import Dict, NoReturn, Optional, TextIO
|
||||
|
||||
import click
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
|
@ -21,14 +22,14 @@ class ApplicationWrapper(QtCore.QObject):
|
|||
new_window = QtCore.Signal()
|
||||
application_activated = QtCore.Signal()
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self) -> None:
|
||||
super(ApplicationWrapper, self).__init__()
|
||||
self.app = QtWidgets.QApplication()
|
||||
self.app.setQuitOnLastWindowClosed(False)
|
||||
|
||||
self.original_event = self.app.event
|
||||
|
||||
def monkeypatch_event(event):
|
||||
def monkeypatch_event(event: QtCore.QEvent) -> bool:
|
||||
# In macOS, handle the file open event
|
||||
if event.type() == QtCore.QEvent.FileOpen:
|
||||
# Skip file open events in dev mode
|
||||
|
@ -46,7 +47,7 @@ class ApplicationWrapper(QtCore.QObject):
|
|||
|
||||
@click.command()
|
||||
@click.argument("filename", required=False)
|
||||
def gui_main(filename):
|
||||
def gui_main(filename: str) -> bool:
|
||||
setup_logging()
|
||||
|
||||
if platform.system() == "Darwin":
|
||||
|
@ -61,16 +62,16 @@ def gui_main(filename):
|
|||
from strip_ansi import strip_ansi
|
||||
|
||||
class StdoutFilter:
|
||||
def __init__(self, stream):
|
||||
def __init__(self, stream: TextIO) -> None:
|
||||
self.stream = stream
|
||||
|
||||
def __getattr__(self, attr_name):
|
||||
def __getattr__(self, attr_name): # type: ignore [no-untyped-def]
|
||||
return getattr(self.stream, attr_name)
|
||||
|
||||
def write(self, data):
|
||||
def write(self, data: str) -> None:
|
||||
self.stream.write(strip_ansi(data))
|
||||
|
||||
def flush(self):
|
||||
def flush(self) -> None:
|
||||
self.stream.flush()
|
||||
|
||||
sys.stdout = StdoutFilter(sys.stdout)
|
||||
|
@ -90,15 +91,15 @@ def gui_main(filename):
|
|||
# Create the system tray
|
||||
systray = SysTray(global_common, gui_common, app, app_wrapper)
|
||||
|
||||
closed_windows = {}
|
||||
windows = {}
|
||||
closed_windows: Dict[str, MainWindow] = {}
|
||||
windows: Dict[str, MainWindow] = {}
|
||||
|
||||
def delete_window(window_id):
|
||||
def delete_window(window_id: str) -> None:
|
||||
closed_windows[window_id] = windows[window_id]
|
||||
del windows[window_id]
|
||||
|
||||
# Open a document in a window
|
||||
def select_document(filename=None):
|
||||
def select_document(filename: Optional[str] = None) -> bool:
|
||||
if (
|
||||
len(windows) == 1
|
||||
and windows[list(windows.keys())[0]].common.input_filename == None
|
||||
|
@ -112,16 +113,16 @@ def gui_main(filename):
|
|||
|
||||
if filename:
|
||||
# Validate filename
|
||||
filename = os.path.abspath(os.path.expanduser(filename))
|
||||
file_path: str = os.path.abspath(os.path.expanduser(filename))
|
||||
try:
|
||||
open(filename, "rb")
|
||||
open(file_path, "rb")
|
||||
except FileNotFoundError:
|
||||
click.echo("File not found")
|
||||
return False
|
||||
except PermissionError:
|
||||
click.echo("Permission denied")
|
||||
return False
|
||||
window.common.input_filename = filename
|
||||
window.common.input_filename = file_path
|
||||
window.content_widget.doc_selection_widget.document_selected.emit()
|
||||
|
||||
return True
|
||||
|
@ -135,7 +136,7 @@ def gui_main(filename):
|
|||
return True
|
||||
|
||||
# Open a new window, if all windows are closed
|
||||
def application_activated():
|
||||
def application_activated() -> None:
|
||||
if len(windows) == 0:
|
||||
select_document()
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ elif platform.system() == "Linux":
|
|||
import getpass
|
||||
from xdg.DesktopEntry import DesktopEntry
|
||||
|
||||
from ..global_common import GlobalCommon
|
||||
from ..settings import Settings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -26,7 +27,7 @@ class GuiCommon(object):
|
|||
The GuiCommon class is a singleton of shared functionality for the GUI
|
||||
"""
|
||||
|
||||
def __init__(self, app, global_common):
|
||||
def __init__(self, app, global_common: GlobalCommon) -> None:
|
||||
# Qt app
|
||||
self.app = app
|
||||
|
||||
|
@ -42,14 +43,14 @@ class GuiCommon(object):
|
|||
# Are we done waiting (for Docker Desktop to be installed, or for container to install)
|
||||
self.is_waiting_finished = False
|
||||
|
||||
def get_window_icon(self):
|
||||
def get_window_icon(self) -> QtGui.QIcon:
|
||||
if platform.system() == "Windows":
|
||||
path = self.global_common.get_resource_path("dangerzone.ico")
|
||||
else:
|
||||
path = self.global_common.get_resource_path("icon.png")
|
||||
return QtGui.QIcon(path)
|
||||
|
||||
def open_pdf_viewer(self, filename):
|
||||
def open_pdf_viewer(self, filename: str) -> None:
|
||||
if platform.system() == "Darwin":
|
||||
# Open in Preview
|
||||
args = ["open", "-a", "Preview.app", filename]
|
||||
|
@ -79,8 +80,8 @@ class GuiCommon(object):
|
|||
log.info(Fore.YELLOW + "> " + Fore.CYAN + args_str)
|
||||
subprocess.Popen(args)
|
||||
|
||||
def _find_pdf_viewers(self):
|
||||
pdf_viewers = {}
|
||||
def _find_pdf_viewers(self) -> dict[str, str]:
|
||||
pdf_viewers: dict[str, str] = {}
|
||||
if platform.system() == "Linux":
|
||||
# Find all .desktop files
|
||||
for search_path in [
|
||||
|
@ -111,8 +112,13 @@ class GuiCommon(object):
|
|||
|
||||
class Alert(QtWidgets.QDialog):
|
||||
def __init__(
|
||||
self, gui_common, global_common, message, ok_text="Ok", extra_button_text=None
|
||||
):
|
||||
self,
|
||||
gui_common: GuiCommon,
|
||||
global_common: GlobalCommon,
|
||||
message: str,
|
||||
ok_text: str = "Ok",
|
||||
extra_button_text: str = None,
|
||||
) -> None:
|
||||
super(Alert, self).__init__()
|
||||
self.global_common = global_common
|
||||
self.gui_common = gui_common
|
||||
|
@ -167,14 +173,14 @@ class Alert(QtWidgets.QDialog):
|
|||
layout.addLayout(buttons_layout)
|
||||
self.setLayout(layout)
|
||||
|
||||
def clicked_ok(self):
|
||||
def clicked_ok(self) -> None:
|
||||
self.done(QtWidgets.QDialog.Accepted)
|
||||
|
||||
def clicked_extra(self):
|
||||
def clicked_extra(self) -> None:
|
||||
self.done(2)
|
||||
|
||||
def clicked_cancel(self):
|
||||
def clicked_cancel(self) -> None:
|
||||
self.done(QtWidgets.QDialog.Rejected)
|
||||
|
||||
def launch(self):
|
||||
def launch(self) -> int:
|
||||
return self.exec_()
|
||||
|
|
|
@ -5,12 +5,15 @@ import platform
|
|||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from typing import Optional
|
||||
|
||||
from colorama import Fore, Style
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..common import Common
|
||||
from ..container import convert
|
||||
from ..global_common import GlobalCommon
|
||||
from .common import GuiCommon
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -18,7 +21,9 @@ log = logging.getLogger(__name__)
|
|||
class MainWindow(QtWidgets.QMainWindow):
|
||||
delete_window = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, global_common, gui_common, window_id):
|
||||
def __init__(
|
||||
self, global_common: GlobalCommon, gui_common: GuiCommon, window_id: str
|
||||
) -> None:
|
||||
super(MainWindow, self).__init__()
|
||||
self.global_common = global_common
|
||||
self.gui_common = gui_common
|
||||
|
@ -78,12 +83,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
|
||||
self.show()
|
||||
|
||||
def waiting_finished(self):
|
||||
def waiting_finished(self) -> None:
|
||||
self.gui_common.is_waiting_finished = True
|
||||
self.waiting_widget.hide()
|
||||
self.content_widget.show()
|
||||
|
||||
def closeEvent(self, e):
|
||||
def closeEvent(self, e: QtGui.QCloseEvent) -> None:
|
||||
e.accept()
|
||||
self.delete_window.emit(self.window_id)
|
||||
|
||||
|
@ -94,11 +99,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
class InstallContainerThread(QtCore.QThread):
|
||||
finished = QtCore.Signal()
|
||||
|
||||
def __init__(self, global_common):
|
||||
def __init__(self, global_common: GlobalCommon) -> None:
|
||||
super(InstallContainerThread, self).__init__()
|
||||
self.global_common = global_common
|
||||
|
||||
def run(self):
|
||||
def run(self) -> None:
|
||||
self.global_common.install_container()
|
||||
self.finished.emit()
|
||||
|
||||
|
@ -115,7 +120,7 @@ class WaitingWidget(QtWidgets.QWidget):
|
|||
# - "install_container"
|
||||
finished = QtCore.Signal()
|
||||
|
||||
def __init__(self, global_common, gui_common):
|
||||
def __init__(self, global_common: GlobalCommon, gui_common: GuiCommon) -> None:
|
||||
super(WaitingWidget, self).__init__()
|
||||
self.global_common = global_common
|
||||
self.gui_common = gui_common
|
||||
|
@ -148,8 +153,8 @@ class WaitingWidget(QtWidgets.QWidget):
|
|||
# Check the state
|
||||
self.check_state()
|
||||
|
||||
def check_state(self):
|
||||
state = None
|
||||
def check_state(self) -> None:
|
||||
state: Optional[str] = None
|
||||
|
||||
# Can we find the container runtime binary binary
|
||||
if platform.system() == "Linux":
|
||||
|
@ -180,7 +185,7 @@ class WaitingWidget(QtWidgets.QWidget):
|
|||
# Update the state
|
||||
self.state_change(state)
|
||||
|
||||
def state_change(self, state):
|
||||
def state_change(self, state: str) -> None:
|
||||
if state == "not_installed":
|
||||
self.label.setText(
|
||||
"<strong>Dangerzone Requires Docker Desktop</strong><br><br><a href='https://www.docker.com/products/docker-desktop'>Download Docker Desktop</a>, install it, and open it."
|
||||
|
@ -204,7 +209,9 @@ class WaitingWidget(QtWidgets.QWidget):
|
|||
class ContentWidget(QtWidgets.QWidget):
|
||||
close_window = QtCore.Signal()
|
||||
|
||||
def __init__(self, global_common, gui_common, common):
|
||||
def __init__(
|
||||
self, global_common: GlobalCommon, gui_common: GuiCommon, common: Common
|
||||
) -> None:
|
||||
super(ContentWidget, self).__init__()
|
||||
|
||||
self.global_common = global_common
|
||||
|
@ -244,22 +251,22 @@ class ContentWidget(QtWidgets.QWidget):
|
|||
layout.addWidget(self.convert_widget, stretch=1)
|
||||
self.setLayout(layout)
|
||||
|
||||
def document_selected(self):
|
||||
def document_selected(self) -> None:
|
||||
self.doc_selection_widget.hide()
|
||||
self.settings_widget.show()
|
||||
|
||||
def start_clicked(self):
|
||||
def start_clicked(self) -> None:
|
||||
self.settings_widget.hide()
|
||||
self.convert_widget.show()
|
||||
|
||||
def _close_window(self):
|
||||
def _close_window(self) -> None:
|
||||
self.close_window.emit()
|
||||
|
||||
|
||||
class DocSelectionWidget(QtWidgets.QWidget):
|
||||
document_selected = QtCore.Signal()
|
||||
|
||||
def __init__(self, common):
|
||||
def __init__(self, common: Common) -> None:
|
||||
super(DocSelectionWidget, self).__init__()
|
||||
self.common = common
|
||||
|
||||
|
@ -286,7 +293,7 @@ class DocSelectionWidget(QtWidgets.QWidget):
|
|||
layout.addStretch()
|
||||
self.setLayout(layout)
|
||||
|
||||
def dangerous_doc_button_clicked(self):
|
||||
def dangerous_doc_button_clicked(self) -> None:
|
||||
filename = QtWidgets.QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Open document",
|
||||
|
@ -302,7 +309,9 @@ class SettingsWidget(QtWidgets.QWidget):
|
|||
start_clicked = QtCore.Signal()
|
||||
close_window = QtCore.Signal()
|
||||
|
||||
def __init__(self, global_common, gui_common, common):
|
||||
def __init__(
|
||||
self, global_common: GlobalCommon, gui_common: GuiCommon, common: Common
|
||||
) -> None:
|
||||
super(SettingsWidget, self).__init__()
|
||||
self.global_common = global_common
|
||||
self.gui_common = gui_common
|
||||
|
@ -424,7 +433,7 @@ class SettingsWidget(QtWidgets.QWidget):
|
|||
if index != -1:
|
||||
self.open_combobox.setCurrentIndex(index)
|
||||
|
||||
def update_ui(self):
|
||||
def update_ui(self) -> None:
|
||||
if platform.system() == "Windows":
|
||||
# Because the save checkbox is always checked in Windows, the
|
||||
# start button can be enabled
|
||||
|
@ -439,7 +448,7 @@ class SettingsWidget(QtWidgets.QWidget):
|
|||
else:
|
||||
self.start_button.setEnabled(False)
|
||||
|
||||
def document_selected(self):
|
||||
def document_selected(self) -> None:
|
||||
# Update the danger doc label
|
||||
self.dangerous_doc_label.setText(
|
||||
f"Suspicious: {os.path.basename(self.common.input_filename)}"
|
||||
|
@ -450,7 +459,7 @@ class SettingsWidget(QtWidgets.QWidget):
|
|||
self.common.output_filename = output_filename
|
||||
self.save_lineedit.setText(os.path.basename(output_filename))
|
||||
|
||||
def save_browse_button_clicked(self):
|
||||
def save_browse_button_clicked(self) -> None:
|
||||
filename = QtWidgets.QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"Save safe PDF as...",
|
||||
|
@ -461,7 +470,7 @@ class SettingsWidget(QtWidgets.QWidget):
|
|||
self.common.output_filename = filename[0]
|
||||
self.save_lineedit.setText(os.path.basename(self.common.output_filename))
|
||||
|
||||
def start_button_clicked(self):
|
||||
def start_button_clicked(self) -> None:
|
||||
if self.common.output_filename is None:
|
||||
# If not saving, then save it to a temp file instead
|
||||
tmp = tempfile.mkstemp(suffix=".pdf", prefix="dangerzone_")
|
||||
|
@ -493,13 +502,13 @@ class ConvertThread(QtCore.QThread):
|
|||
finished = QtCore.Signal(bool)
|
||||
update = QtCore.Signal(bool, str, int)
|
||||
|
||||
def __init__(self, global_common, common):
|
||||
def __init__(self, global_common: GlobalCommon, common: Common) -> None:
|
||||
super(ConvertThread, self).__init__()
|
||||
self.global_common = global_common
|
||||
self.common = common
|
||||
self.error = False
|
||||
|
||||
def run(self):
|
||||
def run(self) -> None:
|
||||
if self.global_common.settings.get("ocr"):
|
||||
ocr_lang = self.global_common.ocr_languages[
|
||||
self.global_common.settings.get("ocr_language")
|
||||
|
@ -515,7 +524,7 @@ class ConvertThread(QtCore.QThread):
|
|||
):
|
||||
self.finished.emit(self.error)
|
||||
|
||||
def stdout_callback(self, line):
|
||||
def stdout_callback(self, line: str) -> None:
|
||||
try:
|
||||
status = json.loads(line)
|
||||
except:
|
||||
|
@ -541,7 +550,9 @@ class ConvertThread(QtCore.QThread):
|
|||
class ConvertWidget(QtWidgets.QWidget):
|
||||
close_window = QtCore.Signal()
|
||||
|
||||
def __init__(self, global_common, gui_common, common):
|
||||
def __init__(
|
||||
self, global_common: GlobalCommon, gui_common: GuiCommon, common: Common
|
||||
) -> None:
|
||||
super(ConvertWidget, self).__init__()
|
||||
self.global_common = global_common
|
||||
self.gui_common = gui_common
|
||||
|
@ -588,19 +599,19 @@ class ConvertWidget(QtWidgets.QWidget):
|
|||
layout.addStretch()
|
||||
self.setLayout(layout)
|
||||
|
||||
def document_selected(self):
|
||||
def document_selected(self) -> None:
|
||||
# Update the danger doc label
|
||||
self.dangerous_doc_label.setText(
|
||||
f"Suspicious: {os.path.basename(self.common.input_filename)}"
|
||||
)
|
||||
|
||||
def start(self):
|
||||
def start(self) -> None:
|
||||
self.convert_t = ConvertThread(self.global_common, self.common)
|
||||
self.convert_t.update.connect(self.update)
|
||||
self.convert_t.finished.connect(self.all_done)
|
||||
self.convert_t.start()
|
||||
|
||||
def update(self, error, text, percentage):
|
||||
def update(self, error, text, percentage) -> None:
|
||||
if error:
|
||||
self.error = True
|
||||
self.error_image.show()
|
||||
|
@ -609,7 +620,7 @@ class ConvertWidget(QtWidgets.QWidget):
|
|||
self.label.setText(text)
|
||||
self.progress.setValue(percentage)
|
||||
|
||||
def all_done(self):
|
||||
def all_done(self) -> None:
|
||||
if self.error:
|
||||
return
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@ class Settings:
|
|||
|
||||
self.load()
|
||||
|
||||
def get(self, key):
|
||||
def get(self, key: str):
|
||||
return self.settings[key]
|
||||
|
||||
def set(self, key, val):
|
||||
def set(self, key: str, val) -> None:
|
||||
self.settings[key] = val
|
||||
|
||||
def load(self):
|
||||
def load(self) -> None:
|
||||
if os.path.isfile(self.settings_filename):
|
||||
# If the settings file exists, load it
|
||||
try:
|
||||
|
|
Loading…
Reference in a new issue