mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 09:52:37 +02:00
make dangerzone.settings a global
This commit is contained in:
parent
1353fa76d9
commit
8142e4a48a
10 changed files with 215 additions and 241 deletions
|
@ -12,6 +12,8 @@ from typing import Optional
|
||||||
|
|
||||||
from colorama import Fore
|
from colorama import Fore
|
||||||
|
|
||||||
|
from .. import settings
|
||||||
|
|
||||||
# FIXME: See https://github.com/freedomofpress/dangerzone/issues/320 for more details.
|
# FIXME: See https://github.com/freedomofpress/dangerzone/issues/320 for more details.
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from PySide2 import QtCore, QtGui, QtWidgets
|
from PySide2 import QtCore, QtGui, QtWidgets
|
||||||
|
@ -80,7 +82,7 @@ class DangerzoneGui(DangerzoneCore):
|
||||||
|
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
# Get the PDF reader command
|
# Get the PDF reader command
|
||||||
args = shlex.split(self.pdf_viewers[self.settings.get("open_app")])
|
args = shlex.split(self.pdf_viewers[settings.get("open_app")])
|
||||||
# %f, %F, %u, and %U are filenames or URLS -- so replace with the file to open
|
# %f, %F, %u, and %U are filenames or URLS -- so replace with the file to open
|
||||||
for i in range(len(args)):
|
for i in range(len(args)):
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -8,6 +8,8 @@ from multiprocessing.pool import ThreadPool
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from .. import settings
|
||||||
|
|
||||||
# FIXME: See https://github.com/freedomofpress/dangerzone/issues/320 for more details.
|
# FIXME: See https://github.com/freedomofpress/dangerzone/issues/320 for more details.
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from PySide2 import QtCore, QtGui, QtSvg, QtWidgets
|
from PySide2 import QtCore, QtGui, QtSvg, QtWidgets
|
||||||
|
@ -163,9 +165,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.toggle_updates_action = hamburger_menu.addAction("Check for updates")
|
self.toggle_updates_action = hamburger_menu.addAction("Check for updates")
|
||||||
self.toggle_updates_action.triggered.connect(self.toggle_updates_triggered)
|
self.toggle_updates_action.triggered.connect(self.toggle_updates_triggered)
|
||||||
self.toggle_updates_action.setCheckable(True)
|
self.toggle_updates_action.setCheckable(True)
|
||||||
self.toggle_updates_action.setChecked(
|
self.toggle_updates_action.setChecked(bool(settings.get("updater_check")))
|
||||||
bool(self.dangerzone.settings.get("updater_check"))
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add the "Exit" action
|
# Add the "Exit" action
|
||||||
hamburger_menu.addSeparator()
|
hamburger_menu.addSeparator()
|
||||||
|
@ -231,8 +231,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
|
|
||||||
def show_update_success(self) -> None:
|
def show_update_success(self) -> None:
|
||||||
"""Inform the user about a new Dangerzone release."""
|
"""Inform the user about a new Dangerzone release."""
|
||||||
version = self.dangerzone.settings.get("updater_latest_version")
|
version = settings.get("updater_latest_version")
|
||||||
changelog = self.dangerzone.settings.get("updater_latest_changelog")
|
changelog = settings.get("updater_latest_changelog")
|
||||||
|
|
||||||
changelog_widget = CollapsibleBox("What's New?")
|
changelog_widget = CollapsibleBox("What's New?")
|
||||||
changelog_layout = QtWidgets.QVBoxLayout()
|
changelog_layout = QtWidgets.QVBoxLayout()
|
||||||
|
@ -277,8 +277,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
def toggle_updates_triggered(self) -> None:
|
def toggle_updates_triggered(self) -> None:
|
||||||
"""Change the underlying update check settings based on the user's choice."""
|
"""Change the underlying update check settings based on the user's choice."""
|
||||||
check = self.toggle_updates_action.isChecked()
|
check = self.toggle_updates_action.isChecked()
|
||||||
self.dangerzone.settings.set("updater_check", check)
|
settings.set("updater_check", check)
|
||||||
self.dangerzone.settings.save()
|
settings.save()
|
||||||
|
|
||||||
def handle_docker_desktop_version_check(
|
def handle_docker_desktop_version_check(
|
||||||
self, is_version_valid: bool, version: str
|
self, is_version_valid: bool, version: str
|
||||||
|
@ -328,16 +328,16 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
"""
|
"""
|
||||||
# If there are no new updates, reset the error counter (if any) and return.
|
# If there are no new updates, reset the error counter (if any) and return.
|
||||||
if report.empty():
|
if report.empty():
|
||||||
self.dangerzone.settings.set("updater_errors", 0, autosave=True)
|
settings.set("updater_errors", 0, autosave=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
hamburger_menu = self.hamburger_button.menu()
|
hamburger_menu = self.hamburger_button.menu()
|
||||||
|
|
||||||
if report.error:
|
if report.error:
|
||||||
log.error(f"Encountered an error during an update check: {report.error}")
|
log.error(f"Encountered an error during an update check: {report.error}")
|
||||||
errors = self.dangerzone.settings.get("updater_errors") + 1
|
errors = settings.get("updater_errors") + 1
|
||||||
self.dangerzone.settings.set("updater_errors", errors)
|
settings.set("updater_errors", errors)
|
||||||
self.dangerzone.settings.save()
|
settings.save()
|
||||||
self.updater_error = report.error
|
self.updater_error = report.error
|
||||||
|
|
||||||
# If we encounter more than three errors in a row, show a red notification
|
# If we encounter more than three errors in a row, show a red notification
|
||||||
|
@ -369,13 +369,13 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
hamburger_menu.insertAction(sep, error_action)
|
hamburger_menu.insertAction(sep, error_action)
|
||||||
else:
|
else:
|
||||||
log.debug(f"Handling new version: {report.version}")
|
log.debug(f"Handling new version: {report.version}")
|
||||||
self.dangerzone.settings.set("updater_latest_version", report.version)
|
settings.set("updater_latest_version", report.version)
|
||||||
self.dangerzone.settings.set("updater_latest_changelog", report.changelog)
|
settings.set("updater_latest_changelog", report.changelog)
|
||||||
self.dangerzone.settings.set("updater_errors", 0)
|
settings.set("updater_errors", 0)
|
||||||
|
|
||||||
# FIXME: Save the settings to the filesystem only when they have really changed,
|
# FIXME: Save the settings to the filesystem only when they have really changed,
|
||||||
# maybe with a dirty bit.
|
# maybe with a dirty bit.
|
||||||
self.dangerzone.settings.save()
|
settings.save()
|
||||||
|
|
||||||
self.hamburger_button.setIcon(
|
self.hamburger_button.setIcon(
|
||||||
QtGui.QIcon(
|
QtGui.QIcon(
|
||||||
|
@ -985,39 +985,37 @@ class SettingsWidget(QtWidgets.QWidget):
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
# Load values from settings
|
# Load values from settings
|
||||||
if self.dangerzone.settings.get("save"):
|
if settings.get("save"):
|
||||||
self.save_checkbox.setCheckState(QtCore.Qt.Checked)
|
self.save_checkbox.setCheckState(QtCore.Qt.Checked)
|
||||||
else:
|
else:
|
||||||
self.save_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
self.save_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
||||||
|
|
||||||
if self.dangerzone.settings.get("safe_extension"):
|
if settings.get("safe_extension"):
|
||||||
self.safe_extension.setText(self.dangerzone.settings.get("safe_extension"))
|
self.safe_extension.setText(settings.get("safe_extension"))
|
||||||
else:
|
else:
|
||||||
self.safe_extension.setText(SAFE_EXTENSION)
|
self.safe_extension.setText(SAFE_EXTENSION)
|
||||||
|
|
||||||
if self.dangerzone.settings.get("archive"):
|
if settings.get("archive"):
|
||||||
self.radio_move_untrusted.setChecked(True)
|
self.radio_move_untrusted.setChecked(True)
|
||||||
else:
|
else:
|
||||||
self.radio_save_to.setChecked(True)
|
self.radio_save_to.setChecked(True)
|
||||||
|
|
||||||
if self.dangerzone.settings.get("ocr"):
|
if settings.get("ocr"):
|
||||||
self.ocr_checkbox.setCheckState(QtCore.Qt.Checked)
|
self.ocr_checkbox.setCheckState(QtCore.Qt.Checked)
|
||||||
else:
|
else:
|
||||||
self.ocr_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
self.ocr_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
||||||
|
|
||||||
index = self.ocr_combobox.findText(self.dangerzone.settings.get("ocr_language"))
|
index = self.ocr_combobox.findText(settings.get("ocr_language"))
|
||||||
if index != -1:
|
if index != -1:
|
||||||
self.ocr_combobox.setCurrentIndex(index)
|
self.ocr_combobox.setCurrentIndex(index)
|
||||||
|
|
||||||
if self.dangerzone.settings.get("open"):
|
if settings.get("open"):
|
||||||
self.open_checkbox.setCheckState(QtCore.Qt.Checked)
|
self.open_checkbox.setCheckState(QtCore.Qt.Checked)
|
||||||
else:
|
else:
|
||||||
self.open_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
self.open_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
||||||
|
|
||||||
if platform.system() == "Linux":
|
if platform.system() == "Linux":
|
||||||
index = self.open_combobox.findText(
|
index = self.open_combobox.findText(settings.get("open_app"))
|
||||||
self.dangerzone.settings.get("open_app")
|
|
||||||
)
|
|
||||||
if index != -1:
|
if index != -1:
|
||||||
self.open_combobox.setCurrentIndex(index)
|
self.open_combobox.setCurrentIndex(index)
|
||||||
|
|
||||||
|
@ -1138,21 +1136,15 @@ class SettingsWidget(QtWidgets.QWidget):
|
||||||
document.output_filename = tmp
|
document.output_filename = tmp
|
||||||
|
|
||||||
# Update settings
|
# Update settings
|
||||||
self.dangerzone.settings.set(
|
settings.set("save", self.save_checkbox.checkState() == QtCore.Qt.Checked)
|
||||||
"save", self.save_checkbox.checkState() == QtCore.Qt.Checked
|
settings.set("safe_extension", self.safe_extension.text())
|
||||||
)
|
settings.set("archive", self.radio_move_untrusted.isChecked())
|
||||||
self.dangerzone.settings.set("safe_extension", self.safe_extension.text())
|
settings.set("ocr", self.ocr_checkbox.checkState() == QtCore.Qt.Checked)
|
||||||
self.dangerzone.settings.set("archive", self.radio_move_untrusted.isChecked())
|
settings.set("ocr_language", self.ocr_combobox.currentText())
|
||||||
self.dangerzone.settings.set(
|
settings.set("open", self.open_checkbox.checkState() == QtCore.Qt.Checked)
|
||||||
"ocr", self.ocr_checkbox.checkState() == QtCore.Qt.Checked
|
|
||||||
)
|
|
||||||
self.dangerzone.settings.set("ocr_language", self.ocr_combobox.currentText())
|
|
||||||
self.dangerzone.settings.set(
|
|
||||||
"open", self.open_checkbox.checkState() == QtCore.Qt.Checked
|
|
||||||
)
|
|
||||||
if platform.system() == "Linux":
|
if platform.system() == "Linux":
|
||||||
self.dangerzone.settings.set("open_app", self.open_combobox.currentText())
|
settings.set("open_app", self.open_combobox.currentText())
|
||||||
self.dangerzone.settings.save()
|
settings.save()
|
||||||
|
|
||||||
# Start!
|
# Start!
|
||||||
self.start_clicked.emit()
|
self.start_clicked.emit()
|
||||||
|
@ -1234,10 +1226,8 @@ class DocumentsListWidget(QtWidgets.QListWidget):
|
||||||
|
|
||||||
def get_ocr_lang(self) -> Optional[str]:
|
def get_ocr_lang(self) -> Optional[str]:
|
||||||
ocr_lang = None
|
ocr_lang = None
|
||||||
if self.dangerzone.settings.get("ocr"):
|
if settings.get("ocr"):
|
||||||
ocr_lang = self.dangerzone.ocr_languages[
|
ocr_lang = self.dangerzone.ocr_languages[settings.get("ocr_language")]
|
||||||
self.dangerzone.settings.get("ocr_language")
|
|
||||||
]
|
|
||||||
return ocr_lang
|
return ocr_lang
|
||||||
|
|
||||||
|
|
||||||
|
@ -1326,7 +1316,7 @@ class DocumentWidget(QtWidgets.QWidget):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Open
|
# Open
|
||||||
if self.dangerzone.settings.get("open"):
|
if settings.get("open"):
|
||||||
self.dangerzone.open_pdf_viewer(self.document.output_filename)
|
self.dangerzone.open_pdf_viewer(self.document.output_filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ from typing import Optional
|
||||||
|
|
||||||
from packaging import version
|
from packaging import version
|
||||||
|
|
||||||
|
from .. import settings
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from PySide2 import QtCore, QtWidgets
|
from PySide2 import QtCore, QtWidgets
|
||||||
else:
|
else:
|
||||||
|
@ -126,11 +128,11 @@ class UpdaterThread(QtCore.QThread):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def check(self) -> Optional[bool]:
|
def check(self) -> Optional[bool]:
|
||||||
return self.dangerzone.settings.get("updater_check")
|
return settings.get("updater_check")
|
||||||
|
|
||||||
@check.setter
|
@check.setter
|
||||||
def check(self, val: bool) -> None:
|
def check(self, val: bool) -> None:
|
||||||
self.dangerzone.settings.set("updater_check", val, autosave=True)
|
settings.set("updater_check", val, autosave=True)
|
||||||
|
|
||||||
def prompt_for_checks(self) -> Optional[bool]:
|
def prompt_for_checks(self) -> Optional[bool]:
|
||||||
"""Ask the user if they want to be informed about Dangerzone updates."""
|
"""Ask the user if they want to be informed about Dangerzone updates."""
|
||||||
|
@ -169,9 +171,9 @@ class UpdaterThread(QtCore.QThread):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
log.debug("Checking if first run of Dangerzone")
|
log.debug("Checking if first run of Dangerzone")
|
||||||
if self.dangerzone.settings.get("updater_last_check") is None:
|
if settings.get("updater_last_check") is None:
|
||||||
log.debug("Dangerzone is running for the first time, updates are stalled")
|
log.debug("Dangerzone is running for the first time, updates are stalled")
|
||||||
self.dangerzone.settings.set("updater_last_check", 0, autosave=True)
|
settings.set("updater_last_check", 0, autosave=True)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
log.debug("Checking if user has already expressed their preference")
|
log.debug("Checking if user has already expressed their preference")
|
||||||
|
@ -204,7 +206,7 @@ class UpdaterThread(QtCore.QThread):
|
||||||
again.
|
again.
|
||||||
"""
|
"""
|
||||||
current_time = self._get_now_timestamp()
|
current_time = self._get_now_timestamp()
|
||||||
last_check = self.dangerzone.settings.get("updater_last_check")
|
last_check = settings.get("updater_last_check")
|
||||||
if current_time < last_check + UPDATE_CHECK_COOLDOWN_SECS:
|
if current_time < last_check + UPDATE_CHECK_COOLDOWN_SECS:
|
||||||
log.debug("Cooling down update checks")
|
log.debug("Cooling down update checks")
|
||||||
return True
|
return True
|
||||||
|
@ -256,12 +258,12 @@ class UpdaterThread(QtCore.QThread):
|
||||||
2. In GitHub, by hitting the latest releases API.
|
2. In GitHub, by hitting the latest releases API.
|
||||||
"""
|
"""
|
||||||
log.debug("Checking for Dangerzone updates")
|
log.debug("Checking for Dangerzone updates")
|
||||||
latest_version = self.dangerzone.settings.get("updater_latest_version")
|
latest_version = settings.get("updater_latest_version")
|
||||||
if version.parse(get_version()) < version.parse(latest_version):
|
if version.parse(get_version()) < version.parse(latest_version):
|
||||||
log.debug("Determined that there is an update due to cached results")
|
log.debug("Determined that there is an update due to cached results")
|
||||||
return UpdateReport(
|
return UpdateReport(
|
||||||
version=latest_version,
|
version=latest_version,
|
||||||
changelog=self.dangerzone.settings.get("updater_latest_changelog"),
|
changelog=settings.get("updater_latest_changelog"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# If the previous check happened before the cooldown period expires, do not
|
# If the previous check happened before the cooldown period expires, do not
|
||||||
|
@ -271,9 +273,7 @@ class UpdaterThread(QtCore.QThread):
|
||||||
if self._should_postpone_update_check():
|
if self._should_postpone_update_check():
|
||||||
return UpdateReport()
|
return UpdateReport()
|
||||||
else:
|
else:
|
||||||
self.dangerzone.settings.set(
|
settings.set("updater_last_check", self._get_now_timestamp(), autosave=True)
|
||||||
"updater_last_check", self._get_now_timestamp(), autosave=True
|
|
||||||
)
|
|
||||||
|
|
||||||
log.debug("Checking the latest GitHub release")
|
log.debug("Checking the latest GitHub release")
|
||||||
report = self.get_latest_info()
|
report = self.get_latest_info()
|
||||||
|
|
|
@ -5,10 +5,9 @@ from typing import Callable, List, Optional
|
||||||
|
|
||||||
import colorama
|
import colorama
|
||||||
|
|
||||||
from . import errors, util
|
from . import errors, settings, util
|
||||||
from .document import Document
|
from .document import Document
|
||||||
from .isolation_provider.base import IsolationProvider
|
from .isolation_provider.base import IsolationProvider
|
||||||
from .settings import Settings
|
|
||||||
from .util import get_resource_path
|
from .util import get_resource_path
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -28,8 +27,6 @@ class DangerzoneCore(object):
|
||||||
unsorted_ocr_languages = json.load(f)
|
unsorted_ocr_languages = json.load(f)
|
||||||
self.ocr_languages = dict(sorted(unsorted_ocr_languages.items()))
|
self.ocr_languages = dict(sorted(unsorted_ocr_languages.items()))
|
||||||
|
|
||||||
# Load settings
|
|
||||||
self.settings = Settings()
|
|
||||||
self.documents: List[Document] = []
|
self.documents: List[Document] = []
|
||||||
self.isolation_provider = isolation_provider
|
self.isolation_provider = isolation_provider
|
||||||
|
|
||||||
|
|
|
@ -10,81 +10,78 @@ from .util import get_config_dir, get_version
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
SETTINGS_FILENAME: str = "settings.json"
|
FILENAME = get_config_dir() / "settings.json"
|
||||||
|
|
||||||
|
SETTINGS: dict = {}
|
||||||
|
|
||||||
|
|
||||||
class Settings:
|
def generate_default_settings() -> Dict[str, Any]:
|
||||||
settings: Dict[str, Any]
|
return {
|
||||||
|
"save": True,
|
||||||
|
"archive": True,
|
||||||
|
"ocr": True,
|
||||||
|
"ocr_language": "English",
|
||||||
|
"open": True,
|
||||||
|
"open_app": None,
|
||||||
|
"safe_extension": SAFE_EXTENSION,
|
||||||
|
"updater_check": None,
|
||||||
|
"updater_last_check": None, # last check in UNIX epoch (secs since 1970)
|
||||||
|
# FIXME: How to invalidate those if they change upstream?
|
||||||
|
"updater_latest_version": get_version(),
|
||||||
|
"updater_latest_changelog": "",
|
||||||
|
"updater_errors": 0,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.settings_filename = get_config_dir() / SETTINGS_FILENAME
|
|
||||||
self.default_settings: Dict[str, Any] = self.generate_default_settings()
|
|
||||||
self.load()
|
|
||||||
|
|
||||||
@classmethod
|
def get(key: str) -> Any:
|
||||||
def generate_default_settings(cls) -> Dict[str, Any]:
|
return SETTINGS[key]
|
||||||
return {
|
|
||||||
"save": True,
|
|
||||||
"archive": True,
|
|
||||||
"ocr": True,
|
|
||||||
"ocr_language": "English",
|
|
||||||
"open": True,
|
|
||||||
"open_app": None,
|
|
||||||
"safe_extension": SAFE_EXTENSION,
|
|
||||||
"updater_check": None,
|
|
||||||
"updater_last_check": None, # last check in UNIX epoch (secs since 1970)
|
|
||||||
# FIXME: How to invalidate those if they change upstream?
|
|
||||||
"updater_latest_version": get_version(),
|
|
||||||
"updater_latest_changelog": "",
|
|
||||||
"updater_errors": 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
def get(self, key: str) -> Any:
|
|
||||||
return self.settings[key]
|
|
||||||
|
|
||||||
def set(self, key: str, val: Any, autosave: bool = False) -> None:
|
def set(key: str, val: Any, autosave: bool = False) -> None:
|
||||||
|
global SETTINGS
|
||||||
|
try:
|
||||||
|
old_val = SETTINGS.get(key)
|
||||||
|
except KeyError:
|
||||||
|
old_val = None
|
||||||
|
SETTINGS[key] = val
|
||||||
|
if autosave and val != old_val:
|
||||||
|
save()
|
||||||
|
|
||||||
|
|
||||||
|
def get_updater_settings() -> Dict[str, Any]:
|
||||||
|
return {key: val for key, val in SETTINGS.items() if key.startswith("updater_")}
|
||||||
|
|
||||||
|
|
||||||
|
def load() -> None:
|
||||||
|
global SETTINGS
|
||||||
|
default_settings = generate_default_settings()
|
||||||
|
if FILENAME.is_file() and FILENAME.exists():
|
||||||
|
# If the settings file exists, load it
|
||||||
try:
|
try:
|
||||||
old_val = self.get(key)
|
with FILENAME.open("r") as settings_file:
|
||||||
except KeyError:
|
SETTINGS = json.load(settings_file)
|
||||||
old_val = None
|
|
||||||
self.settings[key] = val
|
|
||||||
if autosave and val != old_val:
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
def get_updater_settings(self) -> Dict[str, Any]:
|
# If it's missing any fields, add them from the default settings
|
||||||
return {
|
for key in default_settings:
|
||||||
key: val for key, val in self.settings.items() if key.startswith("updater_")
|
if key not in SETTINGS:
|
||||||
}
|
SETTINGS[key] = default_settings[key]
|
||||||
|
elif key == "updater_latest_version":
|
||||||
|
if version.parse(get_version()) > version.parse(get(key)):
|
||||||
|
set(key, get_version())
|
||||||
|
|
||||||
def load(self) -> None:
|
except Exception:
|
||||||
if os.path.isfile(self.settings_filename):
|
log.error("Error loading settings, falling back to default")
|
||||||
self.settings = self.default_settings
|
SETTINGS = default_settings
|
||||||
|
|
||||||
# If the settings file exists, load it
|
else:
|
||||||
try:
|
# Save with default settings
|
||||||
with open(self.settings_filename, "r") as settings_file:
|
log.info("Settings file doesn't exist, starting with default")
|
||||||
self.settings = json.load(settings_file)
|
SETTINGS = default_settings
|
||||||
|
|
||||||
# If it's missing any fields, add them from the default settings
|
save()
|
||||||
for key in self.default_settings:
|
|
||||||
if key not in self.settings:
|
|
||||||
self.settings[key] = self.default_settings[key]
|
|
||||||
elif key == "updater_latest_version":
|
|
||||||
if version.parse(get_version()) > version.parse(self.get(key)):
|
|
||||||
self.set(key, get_version())
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
log.error("Error loading settings, falling back to default")
|
|
||||||
self.settings = self.default_settings
|
|
||||||
|
|
||||||
else:
|
def save() -> None:
|
||||||
# Save with default settings
|
FILENAME.parent.mkdir(parents=True, exist_ok=True)
|
||||||
log.info("Settings file doesn't exist, starting with default")
|
with FILENAME.open("w") as settings_file:
|
||||||
self.settings = self.default_settings
|
json.dump(SETTINGS, settings_file, indent=4)
|
||||||
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
def save(self) -> None:
|
|
||||||
self.settings_filename.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with self.settings_filename.open("w") as settings_file:
|
|
||||||
json.dump(self.settings, settings_file, indent=4)
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ from pathlib import Path
|
||||||
from typing import Callable, List
|
from typing import Callable, List
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from dangerzone.document import SAFE_EXTENSION
|
from dangerzone.document import SAFE_EXTENSION
|
||||||
from dangerzone.gui import Application
|
from dangerzone.gui import Application
|
||||||
|
@ -111,6 +112,26 @@ def sample_pdf() -> str:
|
||||||
return str(test_docs_dir.joinpath(BASIC_SAMPLE_PDF))
|
return str(test_docs_dir.joinpath(BASIC_SAMPLE_PDF))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_settings(mocker: MockerFixture, tmp_path: Path) -> Path:
|
||||||
|
mocker.patch("dangerzone.settings.FILENAME", tmp_path / "settings.json")
|
||||||
|
return tmp_path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def default_settings_0_4_1() -> dict:
|
||||||
|
"""Get the default settings for the 0.4.1 Dangerzone release."""
|
||||||
|
return {
|
||||||
|
"save": True,
|
||||||
|
"archive": True,
|
||||||
|
"ocr": True,
|
||||||
|
"ocr_language": "English",
|
||||||
|
"open": True,
|
||||||
|
"open_app": None,
|
||||||
|
"safe_extension": "-safe.pdf",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SAMPLE_DIRECTORY = "test_docs"
|
SAMPLE_DIRECTORY = "test_docs"
|
||||||
BASIC_SAMPLE_PDF = "sample-pdf.pdf"
|
BASIC_SAMPLE_PDF = "sample-pdf.pdf"
|
||||||
BASIC_SAMPLE_DOC = "sample-doc.doc"
|
BASIC_SAMPLE_DOC = "sample-doc.doc"
|
||||||
|
|
|
@ -30,25 +30,20 @@ def generate_isolated_updater(
|
||||||
else:
|
else:
|
||||||
app = get_qt_app()
|
app = get_qt_app()
|
||||||
|
|
||||||
dummy = Dummy()
|
dangerzone = DangerzoneGui(app, isolation_provider=Dummy())
|
||||||
# XXX: We can monkey-patch global state without wrapping it in a context manager, or
|
|
||||||
# worrying that it will leak between tests, for two reasons:
|
|
||||||
#
|
|
||||||
# 1. Parallel tests in PyTest take place in different processes.
|
|
||||||
# 2. The monkeypatch fixture tears down the monkey-patch after each test ends.
|
|
||||||
monkeypatch.setattr(util, "get_config_dir", lambda: tmp_path)
|
|
||||||
dangerzone = DangerzoneGui(app, isolation_provider=dummy)
|
|
||||||
updater = UpdaterThread(dangerzone)
|
updater = UpdaterThread(dangerzone)
|
||||||
return updater
|
return updater
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def updater(
|
def updater(
|
||||||
tmp_path: Path, monkeypatch: MonkeyPatch, mocker: MockerFixture
|
tmp_path: Path, monkeypatch: MonkeyPatch, mocker: MockerFixture, mock_settings: Path
|
||||||
) -> UpdaterThread:
|
) -> UpdaterThread:
|
||||||
return generate_isolated_updater(tmp_path, monkeypatch, mocker)
|
return generate_isolated_updater(tmp_path, monkeypatch, mocker)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def qt_updater(tmp_path: Path, monkeypatch: MonkeyPatch) -> UpdaterThread:
|
def qt_updater(
|
||||||
|
tmp_path: Path, monkeypatch: MonkeyPatch, mock_settings: Path
|
||||||
|
) -> UpdaterThread:
|
||||||
return generate_isolated_updater(tmp_path, monkeypatch)
|
return generate_isolated_updater(tmp_path, monkeypatch)
|
||||||
|
|
|
@ -3,13 +3,14 @@ import pathlib
|
||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from pytest import MonkeyPatch, fixture
|
from pytest import MonkeyPatch, fixture
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from pytestqt.qtbot import QtBot
|
from pytestqt.qtbot import QtBot
|
||||||
|
|
||||||
from dangerzone import errors
|
from dangerzone import errors, settings
|
||||||
from dangerzone.document import Document
|
from dangerzone.document import Document
|
||||||
from dangerzone.gui import MainWindow
|
from dangerzone.gui import MainWindow
|
||||||
from dangerzone.gui import main_window as main_window_module
|
from dangerzone.gui import main_window as main_window_module
|
||||||
|
@ -96,7 +97,7 @@ def test_default_menu(
|
||||||
updater: UpdaterThread,
|
updater: UpdaterThread,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check that the default menu entries are in order."""
|
"""Check that the default menu entries are in order."""
|
||||||
updater.dangerzone.settings.set("updater_check", True)
|
settings.set("updater_check", True)
|
||||||
|
|
||||||
window = MainWindow(updater.dangerzone)
|
window = MainWindow(updater.dangerzone)
|
||||||
menu_actions = window.hamburger_button.menu().actions()
|
menu_actions = window.hamburger_button.menu().actions()
|
||||||
|
@ -114,7 +115,7 @@ def test_default_menu(
|
||||||
|
|
||||||
toggle_updates_action.trigger()
|
toggle_updates_action.trigger()
|
||||||
assert not toggle_updates_action.isChecked()
|
assert not toggle_updates_action.isChecked()
|
||||||
assert updater.dangerzone.settings.get("updater_check") is False
|
assert settings.get("updater_check") is False
|
||||||
|
|
||||||
|
|
||||||
def test_no_update(
|
def test_no_update(
|
||||||
|
@ -127,9 +128,9 @@ def test_no_update(
|
||||||
# Check that when no update is detected, e.g., due to update cooldown, an empty
|
# Check that when no update is detected, e.g., due to update cooldown, an empty
|
||||||
# report is received that does not affect the menu entries.
|
# report is received that does not affect the menu entries.
|
||||||
curtime = int(time.time())
|
curtime = int(time.time())
|
||||||
updater.dangerzone.settings.set("updater_check", True)
|
settings.set("updater_check", True)
|
||||||
updater.dangerzone.settings.set("updater_errors", 9)
|
settings.set("updater_errors", 9)
|
||||||
updater.dangerzone.settings.set("updater_last_check", curtime)
|
settings.set("updater_last_check", curtime)
|
||||||
|
|
||||||
expected_settings = default_updater_settings()
|
expected_settings = default_updater_settings()
|
||||||
expected_settings["updater_check"] = True
|
expected_settings["updater_check"] = True
|
||||||
|
@ -154,7 +155,7 @@ def test_no_update(
|
||||||
assert menu_actions_before == menu_actions_after
|
assert menu_actions_before == menu_actions_after
|
||||||
|
|
||||||
# Check that any previous update errors are cleared.
|
# Check that any previous update errors are cleared.
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
|
|
||||||
def test_update_detected(
|
def test_update_detected(
|
||||||
|
@ -165,9 +166,9 @@ def test_update_detected(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that a newly detected version leads to a notification to the user."""
|
"""Test that a newly detected version leads to a notification to the user."""
|
||||||
|
|
||||||
qt_updater.dangerzone.settings.set("updater_check", True)
|
settings.set("updater_check", True)
|
||||||
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
settings.set("updater_last_check", 0)
|
||||||
qt_updater.dangerzone.settings.set("updater_errors", 9)
|
settings.set("updater_errors", 9)
|
||||||
|
|
||||||
# Make requests.get().json() return the following dictionary.
|
# Make requests.get().json() return the following dictionary.
|
||||||
mock_upstream_info = {"tag_name": "99.9.9", "body": "changelog"}
|
mock_upstream_info = {"tag_name": "99.9.9", "body": "changelog"}
|
||||||
|
@ -197,13 +198,11 @@ def test_update_detected(
|
||||||
# Check that the settings have been updated properly.
|
# Check that the settings have been updated properly.
|
||||||
expected_settings = default_updater_settings()
|
expected_settings = default_updater_settings()
|
||||||
expected_settings["updater_check"] = True
|
expected_settings["updater_check"] = True
|
||||||
expected_settings["updater_last_check"] = qt_updater.dangerzone.settings.get(
|
expected_settings["updater_last_check"] = settings.get("updater_last_check")
|
||||||
"updater_last_check"
|
|
||||||
)
|
|
||||||
expected_settings["updater_latest_version"] = "99.9.9"
|
expected_settings["updater_latest_version"] = "99.9.9"
|
||||||
expected_settings["updater_latest_changelog"] = "<p>changelog</p>"
|
expected_settings["updater_latest_changelog"] = "<p>changelog</p>"
|
||||||
expected_settings["updater_errors"] = 0
|
expected_settings["updater_errors"] = 0
|
||||||
assert qt_updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
# Check that the hamburger icon has changed with the expected SVG image.
|
# Check that the hamburger icon has changed with the expected SVG image.
|
||||||
assert load_svg_spy.call_count == 2
|
assert load_svg_spy.call_count == 2
|
||||||
|
@ -228,7 +227,7 @@ def test_update_detected(
|
||||||
update_dialog_spy = mocker.spy(main_window_module, "UpdateDialog")
|
update_dialog_spy = mocker.spy(main_window_module, "UpdateDialog")
|
||||||
|
|
||||||
def check_dialog() -> None:
|
def check_dialog() -> None:
|
||||||
dialog = qt_updater.dangerzone.app.activeWindow()
|
dialog = qt_app.activeWindow()
|
||||||
|
|
||||||
update_dialog_spy.assert_called_once()
|
update_dialog_spy.assert_called_once()
|
||||||
kwargs = update_dialog_spy.call_args.kwargs
|
kwargs = update_dialog_spy.call_args.kwargs
|
||||||
|
@ -274,12 +273,13 @@ def test_update_error(
|
||||||
qt_updater: UpdaterThread,
|
qt_updater: UpdaterThread,
|
||||||
monkeypatch: MonkeyPatch,
|
monkeypatch: MonkeyPatch,
|
||||||
mocker: MockerFixture,
|
mocker: MockerFixture,
|
||||||
|
mock_settings: Path,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that an error during an update check leads to a notification to the user."""
|
"""Test that an error during an update check leads to a notification to the user."""
|
||||||
# Test 1 - Check that the first error does not notify the user.
|
# Test 1 - Check that the first error does not notify the user.
|
||||||
qt_updater.dangerzone.settings.set("updater_check", True)
|
settings.set("updater_check", True)
|
||||||
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
settings.set("updater_last_check", 0)
|
||||||
qt_updater.dangerzone.settings.set("updater_errors", 0)
|
settings.set("updater_errors", 0)
|
||||||
|
|
||||||
# Make requests.get() return an errorthe following dictionary.
|
# Make requests.get() return an errorthe following dictionary.
|
||||||
mocker.patch("dangerzone.gui.updater.requests.get")
|
mocker.patch("dangerzone.gui.updater.requests.get")
|
||||||
|
@ -305,11 +305,9 @@ def test_update_error(
|
||||||
# Check that the settings have been updated properly.
|
# Check that the settings have been updated properly.
|
||||||
expected_settings = default_updater_settings()
|
expected_settings = default_updater_settings()
|
||||||
expected_settings["updater_check"] = True
|
expected_settings["updater_check"] = True
|
||||||
expected_settings["updater_last_check"] = qt_updater.dangerzone.settings.get(
|
expected_settings["updater_last_check"] = settings.get("updater_last_check")
|
||||||
"updater_last_check"
|
|
||||||
)
|
|
||||||
expected_settings["updater_errors"] += 1
|
expected_settings["updater_errors"] += 1
|
||||||
assert qt_updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
# Check that the hamburger icon has not changed.
|
# Check that the hamburger icon has not changed.
|
||||||
assert load_svg_spy.call_count == 0
|
assert load_svg_spy.call_count == 0
|
||||||
|
@ -318,7 +316,7 @@ def test_update_error(
|
||||||
assert menu_actions_before == menu_actions_after
|
assert menu_actions_before == menu_actions_after
|
||||||
|
|
||||||
# Test 2 - Check that the second error does not notify the user either.
|
# Test 2 - Check that the second error does not notify the user either.
|
||||||
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
settings.set("updater_last_check", 0)
|
||||||
with qtbot.waitSignal(qt_updater.finished):
|
with qtbot.waitSignal(qt_updater.finished):
|
||||||
qt_updater.start()
|
qt_updater.start()
|
||||||
|
|
||||||
|
@ -326,16 +324,14 @@ def test_update_error(
|
||||||
|
|
||||||
# Check that the settings have been updated properly.
|
# Check that the settings have been updated properly.
|
||||||
expected_settings["updater_errors"] += 1
|
expected_settings["updater_errors"] += 1
|
||||||
expected_settings["updater_last_check"] = qt_updater.dangerzone.settings.get(
|
expected_settings["updater_last_check"] = settings.get("updater_last_check")
|
||||||
"updater_last_check"
|
assert settings.get_updater_settings() == expected_settings
|
||||||
)
|
|
||||||
assert qt_updater.dangerzone.settings.get_updater_settings() == expected_settings
|
|
||||||
|
|
||||||
# Check that no menu entries have been added.
|
# Check that no menu entries have been added.
|
||||||
assert menu_actions_before == menu_actions_after
|
assert menu_actions_before == menu_actions_after
|
||||||
|
|
||||||
# Test 3 - Check that a third error shows a new menu entry.
|
# Test 3 - Check that a third error shows a new menu entry.
|
||||||
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
settings.set("updater_last_check", 0)
|
||||||
with qtbot.waitSignal(qt_updater.finished):
|
with qtbot.waitSignal(qt_updater.finished):
|
||||||
qt_updater.start()
|
qt_updater.start()
|
||||||
|
|
||||||
|
@ -360,7 +356,7 @@ def test_update_error(
|
||||||
update_dialog_spy = mocker.spy(main_window_module, "UpdateDialog")
|
update_dialog_spy = mocker.spy(main_window_module, "UpdateDialog")
|
||||||
|
|
||||||
def check_dialog() -> None:
|
def check_dialog() -> None:
|
||||||
dialog = qt_updater.dangerzone.app.activeWindow()
|
dialog = qt_app.activeWindow()
|
||||||
|
|
||||||
update_dialog_spy.assert_called_once()
|
update_dialog_spy.assert_called_once()
|
||||||
kwargs = update_dialog_spy.call_args.kwargs
|
kwargs = update_dialog_spy.call_args.kwargs
|
||||||
|
|
|
@ -15,7 +15,6 @@ from dangerzone.gui import updater as updater_module
|
||||||
from dangerzone.gui.updater import UpdateReport, UpdaterThread
|
from dangerzone.gui.updater import UpdateReport, UpdaterThread
|
||||||
from dangerzone.util import get_version
|
from dangerzone.util import get_version
|
||||||
|
|
||||||
from ..test_settings import default_settings_0_4_1, save_settings
|
|
||||||
from .conftest import generate_isolated_updater
|
from .conftest import generate_isolated_updater
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ def default_updater_settings() -> dict:
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
key: val
|
key: val
|
||||||
for key, val in settings.Settings.generate_default_settings().items()
|
for key, val in settings.generate_default_settings().items()
|
||||||
if key.startswith("updater_")
|
if key.startswith("updater_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,13 +42,15 @@ def test_default_updater_settings(updater: UpdaterThread) -> None:
|
||||||
|
|
||||||
This test is mostly a sanity check.
|
This test is mostly a sanity check.
|
||||||
"""
|
"""
|
||||||
assert (
|
assert settings.get_updater_settings() == default_updater_settings()
|
||||||
updater.dangerzone.settings.get_updater_settings() == default_updater_settings()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_pre_0_4_2_settings(
|
def test_pre_0_4_2_settings(
|
||||||
tmp_path: Path, monkeypatch: MonkeyPatch, mocker: MockerFixture
|
tmp_path: Path,
|
||||||
|
monkeypatch: MonkeyPatch,
|
||||||
|
mocker: MockerFixture,
|
||||||
|
mock_settings: Path,
|
||||||
|
default_settings_0_4_1: dict,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check settings of installations prior to 0.4.2.
|
"""Check settings of installations prior to 0.4.2.
|
||||||
|
|
||||||
|
@ -57,11 +58,10 @@ def test_pre_0_4_2_settings(
|
||||||
will automatically get the default updater settings, even though they never existed
|
will automatically get the default updater settings, even though they never existed
|
||||||
in their settings.json file.
|
in their settings.json file.
|
||||||
"""
|
"""
|
||||||
save_settings(tmp_path, default_settings_0_4_1())
|
settings.SETTINGS = default_settings_0_4_1
|
||||||
|
settings.save()
|
||||||
updater = generate_isolated_updater(tmp_path, monkeypatch, mocker)
|
updater = generate_isolated_updater(tmp_path, monkeypatch, mocker)
|
||||||
assert (
|
assert settings.get_updater_settings() == default_updater_settings()
|
||||||
updater.dangerzone.settings.get_updater_settings() == default_updater_settings()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_post_0_4_2_settings(
|
def test_post_0_4_2_settings(
|
||||||
|
@ -75,9 +75,8 @@ def test_post_0_4_2_settings(
|
||||||
erroneously prompted to a version they already have.
|
erroneously prompted to a version they already have.
|
||||||
"""
|
"""
|
||||||
# Store the settings of Dangerzone 0.4.2 to the filesystem.
|
# Store the settings of Dangerzone 0.4.2 to the filesystem.
|
||||||
old_settings = settings.Settings.generate_default_settings()
|
settings.SETTINGS = settings.generate_default_settings()
|
||||||
old_settings["updater_latest_version"] = "0.4.2"
|
settings.set("updater_latest_version", "0.4.2", autosave=True)
|
||||||
save_settings(tmp_path, old_settings)
|
|
||||||
|
|
||||||
# Mimic an upgrade to version 0.4.3, by making Dangerzone report that the current
|
# Mimic an upgrade to version 0.4.3, by making Dangerzone report that the current
|
||||||
# version is 0.4.3.
|
# version is 0.4.3.
|
||||||
|
@ -89,19 +88,17 @@ def test_post_0_4_2_settings(
|
||||||
|
|
||||||
# Ensure that the Settings class will correct the latest version field to 0.4.3.
|
# Ensure that the Settings class will correct the latest version field to 0.4.3.
|
||||||
updater = generate_isolated_updater(tmp_path, monkeypatch, mocker)
|
updater = generate_isolated_updater(tmp_path, monkeypatch, mocker)
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
# Simulate an updater check that found a newer Dangerzone version (e.g., 0.4.4).
|
# Simulate an updater check that found a newer Dangerzone version (e.g., 0.4.4).
|
||||||
expected_settings["updater_latest_version"] = "0.4.4"
|
expected_settings["updater_latest_version"] = "0.4.4"
|
||||||
updater.dangerzone.settings.set(
|
settings.set("updater_latest_version", expected_settings["updater_latest_version"])
|
||||||
"updater_latest_version", expected_settings["updater_latest_version"]
|
settings.save()
|
||||||
)
|
|
||||||
updater.dangerzone.settings.save()
|
|
||||||
|
|
||||||
# Ensure that the Settings class will leave the "updater_latest_version" field
|
# Ensure that the Settings class will leave the "updater_latest_version" field
|
||||||
# intact the next time we reload the settings.
|
# intact the next time we reload the settings.
|
||||||
updater.dangerzone.settings.load()
|
settings.load()
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(platform.system() != "Linux", reason="Linux-only test")
|
@pytest.mark.skipif(platform.system() != "Linux", reason="Linux-only test")
|
||||||
|
@ -115,7 +112,7 @@ def test_linux_no_check(updater: UpdaterThread, monkeypatch: MonkeyPatch) -> Non
|
||||||
monkeypatch.delattr(sys, "dangerzone_dev")
|
monkeypatch.delattr(sys, "dangerzone_dev")
|
||||||
|
|
||||||
assert updater.should_check_for_updates() is False
|
assert updater.should_check_for_updates() is False
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
|
|
||||||
def test_user_prompts(
|
def test_user_prompts(
|
||||||
|
@ -130,7 +127,7 @@ def test_user_prompts(
|
||||||
expected_settings["updater_check"] = None
|
expected_settings["updater_check"] = None
|
||||||
expected_settings["updater_last_check"] = 0
|
expected_settings["updater_last_check"] = 0
|
||||||
assert updater.should_check_for_updates() is False
|
assert updater.should_check_for_updates() is False
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
# Second run
|
# Second run
|
||||||
#
|
#
|
||||||
|
@ -144,14 +141,14 @@ def test_user_prompts(
|
||||||
prompt_mock().launch.return_value = False # type: ignore [attr-defined]
|
prompt_mock().launch.return_value = False # type: ignore [attr-defined]
|
||||||
expected_settings["updater_check"] = False
|
expected_settings["updater_check"] = False
|
||||||
assert updater.should_check_for_updates() is False
|
assert updater.should_check_for_updates() is False
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
# Reset the "updater_check" field and check enabling update checks.
|
# Reset the "updater_check" field and check enabling update checks.
|
||||||
updater.dangerzone.settings.set("updater_check", None)
|
settings.set("updater_check", None)
|
||||||
prompt_mock().launch.return_value = True # type: ignore [attr-defined]
|
prompt_mock().launch.return_value = True # type: ignore [attr-defined]
|
||||||
expected_settings["updater_check"] = True
|
expected_settings["updater_check"] = True
|
||||||
assert updater.should_check_for_updates() is True
|
assert updater.should_check_for_updates() is True
|
||||||
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
assert settings.get_updater_settings() == expected_settings
|
||||||
|
|
||||||
# Third run
|
# Third run
|
||||||
#
|
#
|
||||||
|
@ -159,7 +156,7 @@ def test_user_prompts(
|
||||||
# checks.
|
# checks.
|
||||||
prompt_mock().side_effect = RuntimeError("Should not be called") # type: ignore [attr-defined]
|
prompt_mock().side_effect = RuntimeError("Should not be called") # type: ignore [attr-defined]
|
||||||
for check in [True, False]:
|
for check in [True, False]:
|
||||||
updater.dangerzone.settings.set("updater_check", check)
|
settings.set("updater_check", check)
|
||||||
assert updater.should_check_for_updates() == check
|
assert updater.should_check_for_updates() == check
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,8 +197,8 @@ def test_update_checks(
|
||||||
assert_report_equal(report, UpdateReport(error=error_msg))
|
assert_report_equal(report, UpdateReport(error=error_msg))
|
||||||
|
|
||||||
# Test 4 - Check that cached version/changelog info do not trigger an update check.
|
# Test 4 - Check that cached version/changelog info do not trigger an update check.
|
||||||
updater.dangerzone.settings.set("updater_latest_version", "99.9.9")
|
settings.set("updater_latest_version", "99.9.9")
|
||||||
updater.dangerzone.settings.set("updater_latest_changelog", "<p>changelog</p>")
|
settings.set("updater_latest_changelog", "<p>changelog</p>")
|
||||||
|
|
||||||
report = updater.check_for_updates()
|
report = updater.check_for_updates()
|
||||||
assert_report_equal(
|
assert_report_equal(
|
||||||
|
@ -211,8 +208,8 @@ def test_update_checks(
|
||||||
|
|
||||||
def test_update_checks_cooldown(updater: UpdaterThread, mocker: MockerFixture) -> None:
|
def test_update_checks_cooldown(updater: UpdaterThread, mocker: MockerFixture) -> None:
|
||||||
"""Make sure Dangerzone only checks for updates every X hours"""
|
"""Make sure Dangerzone only checks for updates every X hours"""
|
||||||
updater.dangerzone.settings.set("updater_check", True)
|
settings.set("updater_check", True)
|
||||||
updater.dangerzone.settings.set("updater_last_check", 0)
|
settings.set("updater_last_check", 0)
|
||||||
|
|
||||||
# Mock some functions before the tests start
|
# Mock some functions before the tests start
|
||||||
cooldown_spy = mocker.spy(updater, "_should_postpone_update_check")
|
cooldown_spy = mocker.spy(updater, "_should_postpone_update_check")
|
||||||
|
@ -233,7 +230,7 @@ def test_update_checks_cooldown(updater: UpdaterThread, mocker: MockerFixture) -
|
||||||
|
|
||||||
report = updater.check_for_updates()
|
report = updater.check_for_updates()
|
||||||
assert cooldown_spy.spy_return is False
|
assert cooldown_spy.spy_return is False
|
||||||
assert updater.dangerzone.settings.get("updater_last_check") == curtime
|
assert settings.get("updater_last_check") == curtime
|
||||||
assert_report_equal(report, UpdateReport("99.9.9", "<p>changelog</p>"))
|
assert_report_equal(report, UpdateReport("99.9.9", "<p>changelog</p>"))
|
||||||
|
|
||||||
# Test 2: Advance the current time by 1 second, and ensure that no update will take
|
# Test 2: Advance the current time by 1 second, and ensure that no update will take
|
||||||
|
@ -242,12 +239,12 @@ def test_update_checks_cooldown(updater: UpdaterThread, mocker: MockerFixture) -
|
||||||
curtime += 1
|
curtime += 1
|
||||||
timestamp_mock.return_value = curtime
|
timestamp_mock.return_value = curtime
|
||||||
requests_mock.side_effect = Exception("failed") # type: ignore [attr-defined]
|
requests_mock.side_effect = Exception("failed") # type: ignore [attr-defined]
|
||||||
updater.dangerzone.settings.set("updater_latest_version", get_version())
|
settings.set("updater_latest_version", get_version())
|
||||||
updater.dangerzone.settings.set("updater_latest_changelog", None)
|
settings.set("updater_latest_changelog", None)
|
||||||
|
|
||||||
report = updater.check_for_updates()
|
report = updater.check_for_updates()
|
||||||
assert cooldown_spy.spy_return is True
|
assert cooldown_spy.spy_return is True
|
||||||
assert updater.dangerzone.settings.get("updater_last_check") == curtime - 1 # type: ignore [unreachable]
|
assert settings.get("updater_last_check") == curtime - 1 # type: ignore [unreachable]
|
||||||
assert_report_equal(report, UpdateReport())
|
assert_report_equal(report, UpdateReport())
|
||||||
|
|
||||||
# Test 3: Advance the current time by <cooldown period> seconds. Ensure that
|
# Test 3: Advance the current time by <cooldown period> seconds. Ensure that
|
||||||
|
@ -258,14 +255,14 @@ def test_update_checks_cooldown(updater: UpdaterThread, mocker: MockerFixture) -
|
||||||
|
|
||||||
report = updater.check_for_updates()
|
report = updater.check_for_updates()
|
||||||
assert cooldown_spy.spy_return is False
|
assert cooldown_spy.spy_return is False
|
||||||
assert updater.dangerzone.settings.get("updater_last_check") == curtime
|
assert settings.get("updater_last_check") == curtime
|
||||||
assert_report_equal(report, UpdateReport("99.9.9", "<p>changelog</p>"))
|
assert_report_equal(report, UpdateReport("99.9.9", "<p>changelog</p>"))
|
||||||
|
|
||||||
# Test 4: Make Dangerzone check for updates again, but this time, it should
|
# Test 4: Make Dangerzone check for updates again, but this time, it should
|
||||||
# encounter an error while doing so. In that case, the last check timestamp
|
# encounter an error while doing so. In that case, the last check timestamp
|
||||||
# should be bumped, so that subsequent checks don't take place.
|
# should be bumped, so that subsequent checks don't take place.
|
||||||
updater.dangerzone.settings.set("updater_latest_version", get_version())
|
settings.set("updater_latest_version", get_version())
|
||||||
updater.dangerzone.settings.set("updater_latest_changelog", None)
|
settings.set("updater_latest_changelog", None)
|
||||||
|
|
||||||
curtime += updater_module.UPDATE_CHECK_COOLDOWN_SECS
|
curtime += updater_module.UPDATE_CHECK_COOLDOWN_SECS
|
||||||
timestamp_mock.return_value = curtime
|
timestamp_mock.return_value = curtime
|
||||||
|
@ -273,7 +270,7 @@ def test_update_checks_cooldown(updater: UpdaterThread, mocker: MockerFixture) -
|
||||||
|
|
||||||
report = updater.check_for_updates()
|
report = updater.check_for_updates()
|
||||||
assert cooldown_spy.spy_return is False
|
assert cooldown_spy.spy_return is False
|
||||||
assert updater.dangerzone.settings.get("updater_last_check") == curtime
|
assert settings.get("updater_last_check") == curtime
|
||||||
error_msg = (
|
error_msg = (
|
||||||
f"Encountered an exception while checking {updater.GH_RELEASE_URL}: failed"
|
f"Encountered an exception while checking {updater.GH_RELEASE_URL}: failed"
|
||||||
)
|
)
|
||||||
|
@ -375,7 +372,7 @@ def test_update_check_prompt(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that the prompt to enable update checks works properly."""
|
"""Test that the prompt to enable update checks works properly."""
|
||||||
# Force Dangerzone to check immediately for updates
|
# Force Dangerzone to check immediately for updates
|
||||||
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
qt_settings.set("updater_last_check", 0)
|
||||||
|
|
||||||
# Test 1 - Check that on the second run of Dangerzone, the user is prompted to
|
# Test 1 - Check that on the second run of Dangerzone, the user is prompted to
|
||||||
# choose if they want to enable update checks.
|
# choose if they want to enable update checks.
|
||||||
|
|
|
@ -5,50 +5,33 @@ from unittest.mock import PropertyMock
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from dangerzone.settings import SETTINGS_FILENAME, Settings
|
from dangerzone import settings
|
||||||
|
|
||||||
|
|
||||||
def default_settings_0_4_1() -> dict:
|
|
||||||
"""Get the default settings for the 0.4.1 Dangerzone release."""
|
|
||||||
return {
|
|
||||||
"save": True,
|
|
||||||
"archive": True,
|
|
||||||
"ocr": True,
|
|
||||||
"ocr_language": "English",
|
|
||||||
"open": True,
|
|
||||||
"open_app": None,
|
|
||||||
"safe_extension": "-safe.pdf",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_no_settings_file_creates_new_one(
|
def test_no_settings_file_creates_new_one(
|
||||||
tmp_path: Path,
|
mock_settings: Path,
|
||||||
mocker: MockerFixture,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Default settings file is created on first run"""
|
"""Default settings file is created on first run"""
|
||||||
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
|
settings.load()
|
||||||
settings = Settings()
|
assert settings.FILENAME.is_file()
|
||||||
|
|
||||||
assert settings.settings_filename.is_file()
|
with settings.FILENAME.open() as settings_file:
|
||||||
with settings.settings_filename.open() as settings_file:
|
|
||||||
new_settings_dict = json.load(settings_file)
|
new_settings_dict = json.load(settings_file)
|
||||||
assert sorted(new_settings_dict.items()) == sorted(
|
assert sorted(new_settings_dict.items()) == sorted(
|
||||||
settings.generate_default_settings().items()
|
settings.generate_default_settings().items()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_corrupt_settings(tmp_path: Path, mocker: MockerFixture) -> None:
|
def test_corrupt_settings(mocker: MockerFixture, mock_settings: Path) -> None:
|
||||||
# Set some broken settings file
|
# Set some broken settings file
|
||||||
corrupt_settings_dict = "{:}"
|
corrupt_settings_dict = "{:}"
|
||||||
with (tmp_path / SETTINGS_FILENAME).open("w") as settings_file:
|
with settings.FILENAME.open("w") as settings_file:
|
||||||
settings_file.write(corrupt_settings_dict)
|
settings_file.write(corrupt_settings_dict)
|
||||||
|
|
||||||
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
|
assert settings.FILENAME.is_file()
|
||||||
settings = Settings()
|
settings.load()
|
||||||
assert settings.settings_filename.is_file()
|
|
||||||
|
|
||||||
# Check if settings file was reset to the default
|
# Check if settings file was reset to the default
|
||||||
new_settings_dict = json.load(open(settings.settings_filename))
|
new_settings_dict = json.load(open(settings.FILENAME))
|
||||||
assert new_settings_dict != corrupt_settings_dict
|
assert new_settings_dict != corrupt_settings_dict
|
||||||
assert sorted(new_settings_dict.items()) == sorted(
|
assert sorted(new_settings_dict.items()) == sorted(
|
||||||
settings.generate_default_settings().items()
|
settings.generate_default_settings().items()
|
||||||
|
@ -56,32 +39,28 @@ def test_corrupt_settings(tmp_path: Path, mocker: MockerFixture) -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_new_default_setting(tmp_path: Path, mocker: MockerFixture) -> None:
|
def test_new_default_setting(tmp_path: Path, mocker: MockerFixture) -> None:
|
||||||
settings = Settings()
|
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
|
||||||
settings.save()
|
settings.save()
|
||||||
|
|
||||||
# Ensure new default setting is imported into settings
|
# Ensure new default setting is imported into settings
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"dangerzone.settings.Settings.generate_default_settings",
|
"dangerzone.settings.generate_default_settings",
|
||||||
return_value={"mock_setting": 1},
|
return_value={"mock_setting": 1},
|
||||||
)
|
)
|
||||||
|
settings.load()
|
||||||
settings2 = Settings()
|
assert settings.get("mock_setting") == 1
|
||||||
assert settings2.get("mock_setting") == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_new_settings_added(tmp_path: Path, mocker: MockerFixture) -> None:
|
def test_new_settings_added(tmp_path: Path, mocker: MockerFixture) -> None:
|
||||||
settings = Settings()
|
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
|
||||||
|
|
||||||
# Add new setting
|
# Add new setting
|
||||||
settings.set("new_setting_autosaved", 20, autosave=True)
|
settings.set("new_setting_autosaved", 20, autosave=True)
|
||||||
settings.set(
|
settings.set(
|
||||||
"new_setting", 10
|
"new_setting", 10
|
||||||
) # XXX has to be afterwards; otherwise this will be saved
|
) # XXX has to be afterwards; otherwise this will be saved
|
||||||
|
|
||||||
# Simulate new app startup (settings recreation)
|
settings.load()
|
||||||
settings2 = Settings()
|
|
||||||
|
|
||||||
# Check if new setting persisted
|
# Check if new setting persisted
|
||||||
assert 20 == settings2.get("new_setting_autosaved")
|
assert 20 == settings.get("new_setting_autosaved")
|
||||||
with pytest.raises(KeyError):
|
with pytest.raises(KeyError):
|
||||||
settings2.get("new_setting")
|
settings.get("new_setting")
|
||||||
|
|
Loading…
Reference in a new issue