Decouple the Settings class from DangerzoneCore

No real reason to pass the whole object where what we really need is
just the location of the configuration folder.
This commit is contained in:
Alexis Métaireau 2025-03-21 15:41:58 +01:00
parent 5b5bef2a58
commit 1353fa76d9
No known key found for this signature in database
GPG key ID: C65C7A89A8FFC56E
3 changed files with 27 additions and 52 deletions

View file

@ -23,16 +23,13 @@ class DangerzoneCore(object):
# Initialize terminal colors
colorama.init(autoreset=True)
# App data folder
self.appdata_path = util.get_config_dir()
# Languages supported by tesseract
with get_resource_path("ocr-languages.json").open("r") as f:
unsorted_ocr_languages = json.load(f)
self.ocr_languages = dict(sorted(unsorted_ocr_languages.items()))
# Load settings
self.settings = Settings(self)
self.settings = Settings()
self.documents: List[Document] = []
self.isolation_provider = isolation_provider

View file

@ -6,24 +6,18 @@ from typing import TYPE_CHECKING, Any, Dict
from packaging import version
from .document import SAFE_EXTENSION
from .util import get_version
from .util import get_config_dir, get_version
log = logging.getLogger(__name__)
if TYPE_CHECKING:
from .logic import DangerzoneCore
SETTINGS_FILENAME: str = "settings.json"
class Settings:
settings: Dict[str, Any]
def __init__(self, dangerzone: "DangerzoneCore") -> None:
self.dangerzone = dangerzone
self.settings_filename = os.path.join(
self.dangerzone.appdata_path, SETTINGS_FILENAME
)
def __init__(self) -> None:
self.settings_filename = get_config_dir() / SETTINGS_FILENAME
self.default_settings: Dict[str, Any] = self.generate_default_settings()
self.load()
@ -91,6 +85,6 @@ class Settings:
self.save()
def save(self) -> None:
os.makedirs(self.dangerzone.appdata_path, exist_ok=True)
with open(self.settings_filename, "w") as settings_file:
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)

View file

@ -1,5 +1,4 @@
import json
import os
from pathlib import Path
from unittest.mock import PropertyMock
@ -22,40 +21,31 @@ def default_settings_0_4_1() -> dict:
}
@pytest.fixture
def settings(tmp_path: Path, mocker: MockerFixture) -> Settings:
dz_core = mocker.MagicMock()
type(dz_core).appdata_path = PropertyMock(return_value=tmp_path)
return Settings(dz_core)
def save_settings(tmp_path: Path, settings: dict) -> None:
"""Mimic the way Settings save a dictionary to a settings.json file."""
settings_filename = tmp_path / "settings.json"
with open(settings_filename, "w") as settings_file:
json.dump(settings, settings_file, indent=4)
def test_no_settings_file_creates_new_one(settings: Settings) -> None:
def test_no_settings_file_creates_new_one(
tmp_path: Path,
mocker: MockerFixture,
) -> None:
"""Default settings file is created on first run"""
assert os.path.isfile(settings.settings_filename)
new_settings_dict = json.load(open(settings.settings_filename))
assert sorted(new_settings_dict.items()) == sorted(
settings.generate_default_settings().items()
)
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
settings = Settings()
assert settings.settings_filename.is_file()
with settings.settings_filename.open() as settings_file:
new_settings_dict = json.load(settings_file)
assert sorted(new_settings_dict.items()) == sorted(
settings.generate_default_settings().items()
)
def test_corrupt_settings(tmp_path: Path, mocker: MockerFixture) -> None:
# Set some broken settings file
corrupt_settings_dict = "{:}"
with open(tmp_path / SETTINGS_FILENAME, "w") as settings_file:
with (tmp_path / SETTINGS_FILENAME).open("w") as settings_file:
settings_file.write(corrupt_settings_dict)
# Initialize settings
dz_core = mocker.MagicMock()
type(dz_core).appdata_path = PropertyMock(return_value=tmp_path)
settings = Settings(dz_core)
assert os.path.isfile(settings.settings_filename)
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
settings = Settings()
assert settings.settings_filename.is_file()
# Check if settings file was reset to the default
new_settings_dict = json.load(open(settings.settings_filename))
@ -66,10 +56,7 @@ def test_corrupt_settings(tmp_path: Path, mocker: MockerFixture) -> None:
def test_new_default_setting(tmp_path: Path, mocker: MockerFixture) -> None:
# Initialize settings
dz_core = mocker.MagicMock()
type(dz_core).appdata_path = PropertyMock(return_value=tmp_path)
settings = Settings(dz_core)
settings = Settings()
settings.save()
# Ensure new default setting is imported into settings
@ -78,15 +65,12 @@ def test_new_default_setting(tmp_path: Path, mocker: MockerFixture) -> None:
return_value={"mock_setting": 1},
)
settings2 = Settings(dz_core)
settings2 = Settings()
assert settings2.get("mock_setting") == 1
def test_new_settings_added(tmp_path: Path, mocker: MockerFixture) -> None:
# Initialize settings
dz_core = mocker.MagicMock()
type(dz_core).appdata_path = PropertyMock(return_value=tmp_path)
settings = Settings(dz_core)
settings = Settings()
# Add new setting
settings.set("new_setting_autosaved", 20, autosave=True)
@ -95,7 +79,7 @@ def test_new_settings_added(tmp_path: Path, mocker: MockerFixture) -> None:
) # XXX has to be afterwards; otherwise this will be saved
# Simulate new app startup (settings recreation)
settings2 = Settings(dz_core)
settings2 = Settings()
# Check if new setting persisted
assert 20 == settings2.get("new_setting_autosaved")