From 30c7735de14301ad0f74be96ebc8327beceb5964 Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 09:43:52 +0300 Subject: [PATCH 01/16] refactoring: enable pylint checks for R0801 --- common/encfstools.py | 8 +--- common/mount.py | 18 ++------- common/test/config_template | 18 +++++++++ common/test/constants.py | 13 +++++++ common/test/test_applicationinstance.py | 12 +++--- common/test/test_config_crontab.py | 44 +++++++++++----------- common/test/test_lint.py | 2 +- common/test/test_plugin_usercallback.py | 50 ++++++++++++------------- common/test/test_restore.py | 45 ++++++++++------------ common/test/test_snapshots.py | 7 +--- common/test/test_tools.py | 15 +++----- common/test/untils.py | 39 +++++++++++++++++++ qt/test/test_lint.py | 2 +- 13 files changed, 158 insertions(+), 115 deletions(-) create mode 100644 common/test/config_template create mode 100644 common/test/constants.py create mode 100644 common/test/untils.py diff --git a/common/encfstools.py b/common/encfstools.py index 4e19b1039..15d780c8e 100644 --- a/common/encfstools.py +++ b/common/encfstools.py @@ -219,12 +219,8 @@ class EncFS_SSH(EncFS_mount): rsync will then sync the encrypted view on / to the remote path """ def __init__(self, cfg = None, profile_id = None, mode = None, parent = None,*args, **kwargs): - self.config = cfg - if self.config is None: - self.config = config.Config() - self.profile_id = profile_id - if self.profile_id is None: - self.profile_id = self.config.currentProfile() + self.config = cfg or config.Config() + self.profile_id = profile_id or self.config.currentProfile() self.mode = mode if self.mode is None: self.mode = self.config.snapshotsMode(self.profile_id) diff --git a/common/mount.py b/common/mount.py index 357023cc1..345db7109 100644 --- a/common/mount.py +++ b/common/mount.py @@ -143,14 +143,8 @@ def __init__(self, profile_id = None, tmp_mount = False, parent = None): - self.config = cfg - if self.config is None: - self.config = config.Config() - - self.profile_id = profile_id - if self.profile_id is None: - self.profile_id = self.config.currentProfile() - + self.config = cfg if cfg is not None else config.Config() + self.profile_id = profile_id if profile_id is not None else self.config.currentProfile() self.tmp_mount = tmp_mount self.parent = parent @@ -437,13 +431,9 @@ def __init__(self, self.mountproc = None self.symlink_subfolder = None - self.config = cfg - if self.config is None: - self.config = config.Config() + self.config = cfg if cfg is not None else config.Config() - self.profile_id = profile_id - if self.profile_id is None: - self.profile_id = self.config.currentProfile() + self.profile_id = profile_id if profile_id is not None else self.config.currentProfile() self.tmp_mount = tmp_mount self.hash_id = hash_id diff --git a/common/test/config_template b/common/test/config_template new file mode 100644 index 000000000..a10e115e8 --- /dev/null +++ b/common/test/config_template @@ -0,0 +1,18 @@ +config.version=6 +profile1.snapshots.include.1.type={snapshot_type} +profile1.snapshots.include.1.value={snapshot_value} +profile1.snapshots.include.size={snapshot_size} +profile1.snapshots.no_on_battery={no_on_battery} +profile1.snapshots.notify.enabled={notify_enabled} +profile1.snapshots.path={snapshot_path} +profile1.snapshots.path.host={snapshot_host} +profile1.snapshots.path.profile={snapshot_profile} +profile1.snapshots.path.user={snapshot_user} +profile1.snapshots.preserve_acl={preserve_acl} +profile1.snapshots.preserve_xattr={preserve_xattr} +profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} +profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} +profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} +profile1.snapshots.rsync_options.enabled={rsync_options_enabled} +profile1.snapshots.rsync_options.value={rsync_options_value} +profiles.version={profiles_version} diff --git a/common/test/constants.py b/common/test/constants.py new file mode 100644 index 000000000..6e5b6056f --- /dev/null +++ b/common/test/constants.py @@ -0,0 +1,13 @@ +""" +This file contains constants that are used in the test files. +""" +import grp +import os +import pwd + +CURRENTUID = os.geteuid() +CURRENTUSER = pwd.getpwuid(CURRENTUID).pw_name +CURRENTGID = os.getegid() +CURRENTGROUP = grp.getgrgid(CURRENTGID).gr_name +CURRENTUID = os.geteuid() +CURRENTGID = os.getegid() diff --git a/common/test/test_applicationinstance.py b/common/test/test_applicationinstance.py index a55b6b7f6..19b99cd60 100644 --- a/common/test/test_applicationinstance.py +++ b/common/test/test_applicationinstance.py @@ -15,13 +15,13 @@ # with this program; if not, write to the Free Software Foundation,Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import subprocess import os import sys -import unittest +import subprocess from unittest.mock import patch from threading import Thread -from test import generic + +from test import generic, utils sys.path.append(os.path.join(os.path.dirname(__file__), "..")) @@ -70,10 +70,8 @@ def _createProcess(self): return self.subproc.pid def _killProcess(self): - if self.subproc: - self.subproc.kill() - self.subproc.wait() - self.subproc = None + utils.kill_subprocess(self.subproc) + self.subproc = None def test_create_and_remove_pid_file(self): # create pid file diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index 9ed4366d0..a21d05c63 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -19,15 +19,16 @@ See also test_schedule.py for low-level-Cron-behavior implemented in schedule module.""" import unittest -import pyfakefs.fake_filesystem_unittest as pyfakefs_ut import sys import os import tempfile import inspect from pathlib import Path from unittest import mock +import pyfakefs.fake_filesystem_unittest as pyfakefs_ut sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import config +from test import utils class Cron(unittest.TestCase): @@ -80,26 +81,27 @@ def setUp(self): def _create_config_file(self, parent_path): """Minimal config file""" - cfg_content = inspect.cleandoc(''' - config.version=6 - profile1.snapshots.include.1.type=0 - profile1.snapshots.include.1.value=rootpath/source - profile1.snapshots.include.size=1 - profile1.snapshots.no_on_battery=false - profile1.snapshots.notify.enabled=true - profile1.snapshots.path=rootpath/destination - profile1.snapshots.path.host=test-host - profile1.snapshots.path.profile=1 - profile1.snapshots.path.user=test-user - profile1.snapshots.preserve_acl=false - profile1.snapshots.preserve_xattr=false - profile1.snapshots.remove_old_snapshots.enabled=true - profile1.snapshots.remove_old_snapshots.unit=80 - profile1.snapshots.remove_old_snapshots.value=10 - profile1.snapshots.rsync_options.enabled=false - profile1.snapshots.rsync_options.value= - profiles.version=1 - ''') + config_data = utils.generate_temp_config(utils.SnapshotConfig( + config_version=6, + snapshot_type=0, + snapshot_value='rootpath/source', + snapshot_size=1, + no_on_battery='false', + notify_enabled='true', + snapshot_path='rootpath/destination', + snapshot_host='test-host', + snapshot_profile=1, + snapshot_user='test-user', + preserve_acl='false', + preserve_xattr='false', + remove_old_snapshots_enabled='true', + remove_old_snapshots_unit=80, + remove_old_snapshots_value=10, + rsync_options_enabled='false', + rsync_options_value='', + profiles_version=1 + )) + cfg_content = inspect.cleandoc(config_data) # config file location config_fp = parent_path / 'config_path' / 'config' diff --git a/common/test/test_lint.py b/common/test/test_lint.py index 304c9e40c..c2fd95824 100644 --- a/common/test/test_lint.py +++ b/common/test/test_lint.py @@ -108,7 +108,7 @@ def test_with_pylint(self): # Enable asap. This list is a selection of existing (not all!) # problems currently existing in the BIT code base. Quite easy to fix # because their count is low. - # 'R0801', # duplicate-code + 'R0801', # duplicate-code # 'W0237', # arguments-renamed # 'W0221', # arguments-differ # 'W0603', # global-statement diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index 4155a3bea..ed0fdaa1f 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -1,22 +1,20 @@ import sys import inspect import tempfile -from pathlib import Path import stat import io -from datetime import datetime import unittest import unittest.mock as mock -import json -from contextlib import redirect_stdout, redirect_stderr +from pathlib import Path from ast import literal_eval +from contextlib import redirect_stdout, redirect_stderr # This workaround will become obsolet when migrating to src-layout sys.path.append(str(Path(__file__).parent)) sys.path.append(str(Path(__file__).parent / 'plugins')) -import logger import pluginmanager from config import Config +from test import utils from snapshots import Snapshots, SID from usercallbackplugin import UserCallbackPlugin @@ -210,26 +208,28 @@ def _create_source_and_destination_folders(cls, parent_path): @classmethod def _create_config_file(cls, parent_path): - cfg_content = inspect.cleandoc(''' - config.version=6 - profile1.snapshots.include.1.type=0 - profile1.snapshots.include.1.value={rootpath}/{source} - profile1.snapshots.include.size=1 - profile1.snapshots.no_on_battery=false - profile1.snapshots.notify.enabled=true - profile1.snapshots.path={rootpath}/{destination} - profile1.snapshots.path.host=test-host - profile1.snapshots.path.profile=1 - profile1.snapshots.path.user=test-user - profile1.snapshots.preserve_acl=false - profile1.snapshots.preserve_xattr=false - profile1.snapshots.remove_old_snapshots.enabled=true - profile1.snapshots.remove_old_snapshots.unit=80 - profile1.snapshots.remove_old_snapshots.value=10 - profile1.snapshots.rsync_options.enabled=false - profile1.snapshots.rsync_options.value= - profiles.version=1 - ''') + """Minimal config file""" + config_data = utils.generate_temp_config(utils.SnapshotConfig( + config_version=6, + snapshot_type=0, + snapshot_value=f'{parent_path}/{cls.NAME_SOURCE}', + snapshot_size=1, + no_on_battery='false', + notify_enabled='true', + snapshot_path=f'{parent_path}/{cls.NAME_DESTINATION}', + snapshot_host='test-host', + snapshot_profile=1, + snapshot_user='test-user', + preserve_acl='false', + preserve_xattr='false', + remove_old_snapshots_enabled='true', + remove_old_snapshots_unit=80, + remove_old_snapshots_value=10, + rsync_options_enabled='false', + rsync_options_value='', + profiles_version=1 + )) + cfg_content = inspect.cleandoc(config_data) cfg_content = cfg_content.format( rootpath=parent_path, diff --git a/common/test/test_restore.py b/common/test/test_restore.py index 08f025bc5..e3a68e68f 100644 --- a/common/test/test_restore.py +++ b/common/test/test_restore.py @@ -1,39 +1,34 @@ -# Back In Time -# Copyright (C) 2008-2022 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation,Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" +Back In Time +Copyright (C) 2008-2022 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation,Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" import os import sys import unittest -import pwd -import grp import stat from tempfile import TemporaryDirectory + from test import generic +from test.constants import CURRENTUSER, CURRENTGROUP sys.path.append(os.path.join(os.path.dirname(__file__), '..')) -import config -import snapshots import mount -CURRENTUID = os.geteuid() -CURRENTUSER = pwd.getpwuid(CURRENTUID).pw_name - -CURRENTGID = os.getegid() -CURRENTGROUP = grp.getgrgid(CURRENTGID).gr_name class RestoreTestCase(generic.SnapshotsWithSidTestCase): def setUp(self): diff --git a/common/test/test_snapshots.py b/common/test/test_snapshots.py index 202fba8e4..8becc562f 100644 --- a/common/test/test_snapshots.py +++ b/common/test/test_snapshots.py @@ -28,9 +28,9 @@ import unittest from unittest.mock import patch from datetime import date, datetime -from threading import Thread from tempfile import TemporaryDirectory from test import generic +from test.constants import CURRENTUSER, CURRENTGROUP, CURRENTGID, CURRENTUID sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import logger @@ -39,11 +39,6 @@ import tools import mount -CURRENTUID = os.geteuid() -CURRENTUSER = pwd.getpwuid(CURRENTUID).pw_name - -CURRENTGID = os.getegid() -CURRENTGROUP = grp.getgrgid(CURRENTGID).gr_name # all groups the current user is member in GROUPS = [i.gr_name for i in grp.getgrall() if CURRENTUSER in i.gr_mem] diff --git a/common/test/test_tools.py b/common/test/test_tools.py index b72618456..06b99497f 100644 --- a/common/test/test_tools.py +++ b/common/test/test_tools.py @@ -23,14 +23,13 @@ import gzip import stat import signal -import unittest -from unittest.mock import patch +from time import sleep +from datetime import datetime from copy import deepcopy +from unittest.mock import patch from tempfile import NamedTemporaryFile, TemporaryDirectory -from datetime import datetime -from test import generic -from time import sleep import pyfakefs.fake_filesystem_unittest as pyfakefs_ut +from test import generic, utils sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import tools @@ -96,10 +95,8 @@ def _create_process(self, *args): return self.subproc.pid def _kill_process(self): - if self.subproc: - self.subproc.kill() - self.subproc.wait() - self.subproc = None + utils.kill_subprocess(self.subproc) + self.subproc = None def test_sharePath(self): share = tools.sharePath() diff --git a/common/test/untils.py b/common/test/untils.py new file mode 100644 index 000000000..e8e2b6b27 --- /dev/null +++ b/common/test/untils.py @@ -0,0 +1,39 @@ +"""Utilities for testing""" +from pathlib import Path +from collections import namedtuple + +SnapshotConfig = namedtuple('SnapshotConfig', [ + 'config_version', + 'snapshot_type', + 'snapshot_value', + 'snapshot_size', + 'no_on_battery', + 'notify_enabled', + 'snapshot_path', + 'snapshot_host', + 'snapshot_profile', + 'snapshot_user', + 'preserve_acl', + 'preserve_xattr', + 'remove_old_snapshots_enabled', + 'remove_old_snapshots_unit', + 'remove_old_snapshots_value', + 'rsync_options_enabled', + 'rsync_options_value', + 'profiles_version' +]) + + +def generate_temp_config(snapshot_config: SnapshotConfig) -> str: + """Generate a temporary config file with the given snapshot values.""" + template_path = Path(__file__).parent / 'config_template' + + with open(template_path, 'r', encoding='utf-8') as template: + return template.read().format(**snapshot_config._asdict()) + + +def kill_subprocess(proc): + """Kill a process and wait for it to terminate.""" + if proc: + proc.kill() + proc.wait() diff --git a/qt/test/test_lint.py b/qt/test/test_lint.py index 82bad4a0d..30b35ae0c 100644 --- a/qt/test/test_lint.py +++ b/qt/test/test_lint.py @@ -103,7 +103,7 @@ def test_with_pylint(self): # 'R0201', # no-self-use # 'R0202', # no-classmethod-decorator # 'R0203', # no-staticmethod-decorator - # 'R0801', # duplicate-code + 'R0801', # duplicate-code # 'W0123', # eval-used # 'W0237', # arguments-renamed # 'W0221', # arguments-differ From cd3adb545d1f0412c83aaa7c7d80b18bc661410c Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 10:16:32 +0300 Subject: [PATCH 02/16] remove duplicates in qt --- qt/app.py | 7 ++----- qt/logviewdialog.py | 9 +++------ qt/qtsystrayicon.py | 4 ++-- qt/settingsdialog.py | 15 ++++++--------- qt/utils.py | 18 ++++++++++++++++++ 5 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 qt/utils.py diff --git a/qt/app.py b/qt/app.py index 8936483e0..62505d3ea 100644 --- a/qt/app.py +++ b/qt/app.py @@ -98,6 +98,7 @@ import languagedialog import messagebox from aboutdlg import AboutDlg +from utils import update_combo_profiles class MainWindow(QMainWindow): @@ -880,13 +881,9 @@ def updateProfiles(self): self.comboProfiles.clear() + update_combo_profiles(self.config, self.comboProfiles, self.config.currentProfile()) profiles = self.config.profilesSortedByName() - for profile_id in profiles: - self.comboProfiles.addProfileID(profile_id) - if profile_id == self.config.currentProfile(): - self.comboProfiles.setCurrentProfileID(profile_id) - self.comboProfilesAction.setVisible(len(profiles) > 1) self.updateProfile() diff --git a/qt/logviewdialog.py b/qt/logviewdialog.py index 117308c84..c6b9d32c7 100644 --- a/qt/logviewdialog.py +++ b/qt/logviewdialog.py @@ -31,6 +31,7 @@ import encfstools import snapshotlog import tools +from utils import update_combo_profiles class LogViewDialog(QDialog): @@ -187,16 +188,12 @@ def updateProfiles(self): self.comboProfiles.clear() - profiles = self.config.profilesSortedByName() - for profile_id in profiles: - self.comboProfiles.addProfileID(profile_id) - if profile_id == current_profile_id: - self.comboProfiles.setCurrentProfileID(profile_id) + update_combo_profiles(self.config, self.comboProfiles, current_profile_id) self.enableUpdate = True self.updateLog() - if len(profiles) <= 1: + if len(self.config.profilesSortedByName()) <= 1: self.lblProfile.setVisible(False) self.comboProfiles.setVisible(False) diff --git a/qt/qtsystrayicon.py b/qt/qtsystrayicon.py index 4bcd3a9ec..67f1eb924 100644 --- a/qt/qtsystrayicon.py +++ b/qt/qtsystrayicon.py @@ -201,13 +201,13 @@ def updateInfo(self): self.menuProgress.setVisible(False) def getMenuProgress(self, pg): - d = ( + data = ( ('sent', _('Sent:')), ('speed', _('Speed:')), ('eta', _('ETA:')) ) - for key, txt in d: + for key, txt in data: value = pg.strValue(key, '') if not value: diff --git a/qt/settingsdialog.py b/qt/settingsdialog.py index fcb6aa64f..c6de55748 100644 --- a/qt/settingsdialog.py +++ b/qt/settingsdialog.py @@ -71,6 +71,7 @@ import encfsmsgbox from exceptions import MountException, NoPubKeyLogin, KnownHost from bitbase import URL_ENCRYPT_TRANSITION +from utils import update_combo_profiles class SshProxyWidget(QWidget): @@ -1390,13 +1391,13 @@ def profileChanged(self, index): if self.disableProfileChanged: return - profile_id = self.comboProfiles.currentProfileID() - if not profile_id: + current_profile_id = self.comboProfiles.currentProfileID() + if not current_profile_id: return - if profile_id != self.config.currentProfile(): + if current_profile_id != self.config.currentProfile(): self.saveProfile() - self.config.setCurrentProfile(profile_id) + self.config.setCurrentProfile(current_profile_id) self.updateProfile() def updateProfiles(self, reloadSettings=True): @@ -1409,11 +1410,7 @@ def updateProfiles(self, reloadSettings=True): self.comboProfiles.clear() - profiles = self.config.profilesSortedByName() - for profile_id in profiles: - self.comboProfiles.addProfileID(profile_id) - if profile_id == current_profile_id: - self.comboProfiles.setCurrentProfileID(profile_id) + update_combo_profiles(self.config, self.comboProfiles, current_profile_id) self.disableProfileChanged = False diff --git a/qt/utils.py b/qt/utils.py new file mode 100644 index 000000000..a0d285f9e --- /dev/null +++ b/qt/utils.py @@ -0,0 +1,18 @@ +""" +Utility functions for the Qt GUI. +""" + + +def update_combo_profiles(config, combo_profiles, current_profile_id): + """ + Updates the combo box with profiles. + + :param config: Configuration object with access to profile data. + :param combo_profiles: The combo box widget to be updated. + :param current_profile_id: The ID of the current profile to be selected. + """ + profiles = config.profilesSortedByName() + for profile_id in profiles: + combo_profiles.addProfileID(profile_id) + if profile_id == current_profile_id: + combo_profiles.setCurrentProfileID(profile_id) From 7395ce2e8d30126d8ebe050e3367efac3edb5fa8 Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 10:24:16 +0300 Subject: [PATCH 03/16] fix utils module name --- common/test/{untils.py => utils.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename common/test/{untils.py => utils.py} (100%) diff --git a/common/test/untils.py b/common/test/utils.py similarity index 100% rename from common/test/untils.py rename to common/test/utils.py From 4d7b2173bd3f211c9637a96bb372a90a984f33d9 Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 10:45:18 +0300 Subject: [PATCH 04/16] fix: update config creation --- common/test/config_template | 18 ------------------ common/test/utils.py | 26 +++++++++++++++++++++----- 2 files changed, 21 insertions(+), 23 deletions(-) delete mode 100644 common/test/config_template diff --git a/common/test/config_template b/common/test/config_template deleted file mode 100644 index a10e115e8..000000000 --- a/common/test/config_template +++ /dev/null @@ -1,18 +0,0 @@ -config.version=6 -profile1.snapshots.include.1.type={snapshot_type} -profile1.snapshots.include.1.value={snapshot_value} -profile1.snapshots.include.size={snapshot_size} -profile1.snapshots.no_on_battery={no_on_battery} -profile1.snapshots.notify.enabled={notify_enabled} -profile1.snapshots.path={snapshot_path} -profile1.snapshots.path.host={snapshot_host} -profile1.snapshots.path.profile={snapshot_profile} -profile1.snapshots.path.user={snapshot_user} -profile1.snapshots.preserve_acl={preserve_acl} -profile1.snapshots.preserve_xattr={preserve_xattr} -profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} -profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} -profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} -profile1.snapshots.rsync_options.enabled={rsync_options_enabled} -profile1.snapshots.rsync_options.value={rsync_options_value} -profiles.version={profiles_version} diff --git a/common/test/utils.py b/common/test/utils.py index e8e2b6b27..6f12b82ca 100644 --- a/common/test/utils.py +++ b/common/test/utils.py @@ -25,11 +25,27 @@ def generate_temp_config(snapshot_config: SnapshotConfig) -> str: - """Generate a temporary config file with the given snapshot values.""" - template_path = Path(__file__).parent / 'config_template' - - with open(template_path, 'r', encoding='utf-8') as template: - return template.read().format(**snapshot_config._asdict()) + template_content = """ + config.version=6 + profile1.snapshots.include.1.type={snapshot_type} + profile1.snapshots.include.1.value={snapshot_value} + profile1.snapshots.include.size={snapshot_size} + profile1.snapshots.no_on_battery={no_on_battery} + profile1.snapshots.notify.enabled={notify_enabled} + profile1.snapshots.path={snapshot_path} + profile1.snapshots.path.host={snapshot_host} + profile1.snapshots.path.profile={snapshot_profile} + profile1.snapshots.path.user={snapshot_user} + profile1.snapshots.preserve_acl={preserve_acl} + profile1.snapshots.preserve_xattr={preserve_xattr} + profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} + profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} + profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} + profile1.snapshots.rsync_options.enabled={rsync_options_enabled} + profile1.snapshots.rsync_options.value={rsync_options_value} + profiles.version={profiles_version} + """ + return template_content.format(**snapshot_config._asdict()) def kill_subprocess(proc): From f89292142835c161dc9013db55473613a9a55c0d Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 18:45:26 +0300 Subject: [PATCH 05/16] updates according to PR review --- common/mount.py | 4 +-- common/test/test_config_crontab.py | 4 +-- common/test/test_plugin_usercallback.py | 4 +-- common/test/test_restore.py | 34 ++++++++++++------------- common/test/utils.py | 28 +------------------- qt/app.py | 4 +-- qt/logviewdialog.py | 4 +-- qt/qttools.py | 16 ++++++++++++ qt/settingsdialog.py | 4 +-- qt/utils.py | 18 ------------- 10 files changed, 45 insertions(+), 75 deletions(-) delete mode 100644 qt/utils.py diff --git a/common/mount.py b/common/mount.py index 345db7109..d9937d23c 100644 --- a/common/mount.py +++ b/common/mount.py @@ -143,7 +143,7 @@ def __init__(self, profile_id = None, tmp_mount = False, parent = None): - self.config = cfg if cfg is not None else config.Config() + self.config = cfg or config.Config() self.profile_id = profile_id if profile_id is not None else self.config.currentProfile() self.tmp_mount = tmp_mount self.parent = parent @@ -431,7 +431,7 @@ def __init__(self, self.mountproc = None self.symlink_subfolder = None - self.config = cfg if cfg is not None else config.Config() + self.config = cfg or config.Config() self.profile_id = profile_id if profile_id is not None else self.config.currentProfile() diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index a21d05c63..2a1d6f4b7 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -81,7 +81,7 @@ def setUp(self): def _create_config_file(self, parent_path): """Minimal config file""" - config_data = utils.generate_temp_config(utils.SnapshotConfig( + config_data = utils.config_template.format( config_version=6, snapshot_type=0, snapshot_value='rootpath/source', @@ -100,7 +100,7 @@ def _create_config_file(self, parent_path): rsync_options_enabled='false', rsync_options_value='', profiles_version=1 - )) + ) cfg_content = inspect.cleandoc(config_data) # config file location diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index ed0fdaa1f..ec43f2384 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -209,7 +209,7 @@ def _create_source_and_destination_folders(cls, parent_path): @classmethod def _create_config_file(cls, parent_path): """Minimal config file""" - config_data = utils.generate_temp_config(utils.SnapshotConfig( + config_data = utils.format( config_version=6, snapshot_type=0, snapshot_value=f'{parent_path}/{cls.NAME_SOURCE}', @@ -228,7 +228,7 @@ def _create_config_file(cls, parent_path): rsync_options_enabled='false', rsync_options_value='', profiles_version=1 - )) + ) cfg_content = inspect.cleandoc(config_data) cfg_content = cfg_content.format( diff --git a/common/test/test_restore.py b/common/test/test_restore.py index e3a68e68f..e66027927 100644 --- a/common/test/test_restore.py +++ b/common/test/test_restore.py @@ -1,21 +1,19 @@ -""" -Back In Time -Copyright (C) 2008-2022 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation,Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -""" +# Back In Time +# Copyright (C) 2008-2022 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation,Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import os import sys diff --git a/common/test/utils.py b/common/test/utils.py index 6f12b82ca..c7ac530e1 100644 --- a/common/test/utils.py +++ b/common/test/utils.py @@ -1,31 +1,6 @@ """Utilities for testing""" -from pathlib import Path -from collections import namedtuple -SnapshotConfig = namedtuple('SnapshotConfig', [ - 'config_version', - 'snapshot_type', - 'snapshot_value', - 'snapshot_size', - 'no_on_battery', - 'notify_enabled', - 'snapshot_path', - 'snapshot_host', - 'snapshot_profile', - 'snapshot_user', - 'preserve_acl', - 'preserve_xattr', - 'remove_old_snapshots_enabled', - 'remove_old_snapshots_unit', - 'remove_old_snapshots_value', - 'rsync_options_enabled', - 'rsync_options_value', - 'profiles_version' -]) - - -def generate_temp_config(snapshot_config: SnapshotConfig) -> str: - template_content = """ +config_template = """ config.version=6 profile1.snapshots.include.1.type={snapshot_type} profile1.snapshots.include.1.value={snapshot_value} @@ -45,7 +20,6 @@ def generate_temp_config(snapshot_config: SnapshotConfig) -> str: profile1.snapshots.rsync_options.value={rsync_options_value} profiles.version={profiles_version} """ - return template_content.format(**snapshot_config._asdict()) def kill_subprocess(proc): diff --git a/qt/app.py b/qt/app.py index 62505d3ea..83a937503 100644 --- a/qt/app.py +++ b/qt/app.py @@ -98,7 +98,7 @@ import languagedialog import messagebox from aboutdlg import AboutDlg -from utils import update_combo_profiles +import qttools class MainWindow(QMainWindow): @@ -881,7 +881,7 @@ def updateProfiles(self): self.comboProfiles.clear() - update_combo_profiles(self.config, self.comboProfiles, self.config.currentProfile()) + qttools.update_combo_profiles(self.config, self.comboProfiles, self.config.currentProfile()) profiles = self.config.profilesSortedByName() self.comboProfilesAction.setVisible(len(profiles) > 1) diff --git a/qt/logviewdialog.py b/qt/logviewdialog.py index c6b9d32c7..2cfd0e55e 100644 --- a/qt/logviewdialog.py +++ b/qt/logviewdialog.py @@ -31,7 +31,7 @@ import encfstools import snapshotlog import tools -from utils import update_combo_profiles +import qttools class LogViewDialog(QDialog): @@ -188,7 +188,7 @@ def updateProfiles(self): self.comboProfiles.clear() - update_combo_profiles(self.config, self.comboProfiles, current_profile_id) + qttools.update_combo_profiles(self.config, self.comboProfiles, current_profile_id) self.enableUpdate = True self.updateLog() diff --git a/qt/qttools.py b/qt/qttools.py index 9938d461c..cea8940b2 100644 --- a/qt/qttools.py +++ b/qt/qttools.py @@ -139,6 +139,21 @@ def set_wrapped_tooltip(widget: QWidget, widget.setToolTip('\n'.join(result)) + +def update_combo_profiles(config, combo_profiles, current_profile_id): + """ + Updates the combo box with profiles. + + :param config: Configuration object with access to profile data. + :param combo_profiles: The combo box widget to be updated. + :param current_profile_id: The ID of the current profile to be selected. + """ + profiles = config.profilesSortedByName() + for profile_id in profiles: + combo_profiles.addProfileID(profile_id) + if profile_id == current_profile_id: + combo_profiles.setCurrentProfileID(profile_id) + # |---------------------| # | Misc / Uncatgorized | # |---------------------| @@ -703,3 +718,4 @@ def setCurrentProfileID(self, profileID): if self.itemData(i) == profileID: self.setCurrentIndex(i) break + diff --git a/qt/settingsdialog.py b/qt/settingsdialog.py index c6de55748..3ebcb714f 100644 --- a/qt/settingsdialog.py +++ b/qt/settingsdialog.py @@ -71,7 +71,7 @@ import encfsmsgbox from exceptions import MountException, NoPubKeyLogin, KnownHost from bitbase import URL_ENCRYPT_TRANSITION -from utils import update_combo_profiles +import qttools class SshProxyWidget(QWidget): @@ -1410,7 +1410,7 @@ def updateProfiles(self, reloadSettings=True): self.comboProfiles.clear() - update_combo_profiles(self.config, self.comboProfiles, current_profile_id) + qttools.update_combo_profiles(self.config, self.comboProfiles, current_profile_id) self.disableProfileChanged = False diff --git a/qt/utils.py b/qt/utils.py deleted file mode 100644 index a0d285f9e..000000000 --- a/qt/utils.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -Utility functions for the Qt GUI. -""" - - -def update_combo_profiles(config, combo_profiles, current_profile_id): - """ - Updates the combo box with profiles. - - :param config: Configuration object with access to profile data. - :param combo_profiles: The combo box widget to be updated. - :param current_profile_id: The ID of the current profile to be selected. - """ - profiles = config.profilesSortedByName() - for profile_id in profiles: - combo_profiles.addProfileID(profile_id) - if profile_id == current_profile_id: - combo_profiles.setCurrentProfileID(profile_id) From 9c75024ad93852449d7c6e309cc02c32d09fcdf5 Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 18:57:36 +0300 Subject: [PATCH 06/16] fix: test_plugin_usercallback --- common/test/test_plugin_usercallback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index ec43f2384..e08ed3585 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -209,7 +209,7 @@ def _create_source_and_destination_folders(cls, parent_path): @classmethod def _create_config_file(cls, parent_path): """Minimal config file""" - config_data = utils.format( + config_data = utils.config_template.format( config_version=6, snapshot_type=0, snapshot_value=f'{parent_path}/{cls.NAME_SOURCE}', From 1c13d79c6ac2f3582f3f3424fd4a6dd9dbf84b8d Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Sat, 20 Jul 2024 19:05:11 +0300 Subject: [PATCH 07/16] fix: linting --- qt/qttools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qt/qttools.py b/qt/qttools.py index cea8940b2..f1fdabec0 100644 --- a/qt/qttools.py +++ b/qt/qttools.py @@ -718,4 +718,3 @@ def setCurrentProfileID(self, profileID): if self.itemData(i) == profileID: self.setCurrentIndex(i) break - From 79ed71c807c69647e58382d42b4b9e1218df9846 Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Mon, 22 Jul 2024 09:36:05 +0300 Subject: [PATCH 08/16] fix: update --- common/mount.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/mount.py b/common/mount.py index d9937d23c..f218563ff 100644 --- a/common/mount.py +++ b/common/mount.py @@ -104,18 +104,18 @@ def postUmountCheck(self): return True """ +import getpass +import json import os import subprocess -import json -import getpass -from zlib import crc32 from time import sleep +from zlib import crc32 import config import logger -import tools import password -from exceptions import MountException, HashCollision +import tools +from exceptions import HashCollision, MountException class Mount(object): @@ -144,7 +144,7 @@ def __init__(self, tmp_mount = False, parent = None): self.config = cfg or config.Config() - self.profile_id = profile_id if profile_id is not None else self.config.currentProfile() + self.profile_id = profile_id or self.config.currentProfile() self.tmp_mount = tmp_mount self.parent = parent From 4c0e5a169296077c0efce6e3432c802a293f75cd Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Mon, 22 Jul 2024 09:49:16 +0300 Subject: [PATCH 09/16] fix: update 2 --- common/mount.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/mount.py b/common/mount.py index f218563ff..b7af736e2 100644 --- a/common/mount.py +++ b/common/mount.py @@ -433,7 +433,7 @@ def __init__(self, self.config = cfg or config.Config() - self.profile_id = profile_id if profile_id is not None else self.config.currentProfile() + self.profile_id = profile_id or self.config.currentProfile() self.tmp_mount = tmp_mount self.hash_id = hash_id From ed3d40dec011910b293aa1aba5b0bc7332ec3986 Mon Sep 17 00:00:00 2001 From: Ihor Pryyma Date: Fri, 26 Jul 2024 14:24:18 +0300 Subject: [PATCH 10/16] remove utils --- common/test/test_applicationinstance.py | 7 +++-- common/test/test_config_crontab.py | 31 ++++++++++++++++++---- common/test/test_plugin_usercallback.py | 35 +++++++++++++++++++------ common/test/test_tools.py | 6 +++-- common/test/utils.py | 29 -------------------- 5 files changed, 62 insertions(+), 46 deletions(-) delete mode 100644 common/test/utils.py diff --git a/common/test/test_applicationinstance.py b/common/test/test_applicationinstance.py index 19b99cd60..3f090a2ac 100644 --- a/common/test/test_applicationinstance.py +++ b/common/test/test_applicationinstance.py @@ -21,7 +21,7 @@ from unittest.mock import patch from threading import Thread -from test import generic, utils +from test import generic sys.path.append(os.path.join(os.path.dirname(__file__), "..")) @@ -70,7 +70,10 @@ def _createProcess(self): return self.subproc.pid def _killProcess(self): - utils.kill_subprocess(self.subproc) + if self.subproc: + subproc = self.subproc + subproc.kill() + subproc.wait() self.subproc = None def test_create_and_remove_pid_file(self): diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index 2a1d6f4b7..8eaa11bfa 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -18,17 +18,19 @@ See also test_schedule.py for low-level-Cron-behavior implemented in schedule module.""" -import unittest -import sys +import inspect import os +import sys import tempfile -import inspect +import unittest from pathlib import Path from unittest import mock + import pyfakefs.fake_filesystem_unittest as pyfakefs_ut + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + import config -from test import utils class Cron(unittest.TestCase): @@ -81,7 +83,26 @@ def setUp(self): def _create_config_file(self, parent_path): """Minimal config file""" - config_data = utils.config_template.format( + config_data = """ + config.version={config_version} + profile1.snapshots.include.1.type={snapshot_type} + profile1.snapshots.include.1.value={snapshot_value} + profile1.snapshots.include.size={snapshot_size} + profile1.snapshots.no_on_battery={no_on_battery} + profile1.snapshots.notify.enabled={notify_enabled} + profile1.snapshots.path={snapshot_path} + profile1.snapshots.path.host={snapshot_host} + profile1.snapshots.path.profile={snapshot_profile} + profile1.snapshots.path.user={snapshot_user} + profile1.snapshots.preserve_acl={preserve_acl} + profile1.snapshots.preserve_xattr={preserve_xattr} + profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} + profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} + profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} + profile1.snapshots.rsync_options.enabled={rsync_options_enabled} + profile1.snapshots.rsync_options.value={rsync_options_value} + profiles.version={profiles_version} + """.format( config_version=6, snapshot_type=0, snapshot_value='rootpath/source', diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index e08ed3585..bca0f0cdf 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -1,21 +1,21 @@ -import sys import inspect -import tempfile -import stat import io +import stat +import sys +import tempfile import unittest import unittest.mock as mock -from pathlib import Path from ast import literal_eval -from contextlib import redirect_stdout, redirect_stderr +from contextlib import redirect_stderr, redirect_stdout +from pathlib import Path # This workaround will become obsolet when migrating to src-layout sys.path.append(str(Path(__file__).parent)) sys.path.append(str(Path(__file__).parent / 'plugins')) + import pluginmanager from config import Config -from test import utils -from snapshots import Snapshots, SID +from snapshots import SID, Snapshots from usercallbackplugin import UserCallbackPlugin @@ -209,7 +209,26 @@ def _create_source_and_destination_folders(cls, parent_path): @classmethod def _create_config_file(cls, parent_path): """Minimal config file""" - config_data = utils.config_template.format( + config_data = """ + config.version={config_version} + profile1.snapshots.include.1.type={snapshot_type} + profile1.snapshots.include.1.value={snapshot_value} + profile1.snapshots.include.size={snapshot_size} + profile1.snapshots.no_on_battery={no_on_battery} + profile1.snapshots.notify.enabled={notify_enabled} + profile1.snapshots.path={snapshot_path} + profile1.snapshots.path.host={snapshot_host} + profile1.snapshots.path.profile={snapshot_profile} + profile1.snapshots.path.user={snapshot_user} + profile1.snapshots.preserve_acl={preserve_acl} + profile1.snapshots.preserve_xattr={preserve_xattr} + profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} + profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} + profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} + profile1.snapshots.rsync_options.enabled={rsync_options_enabled} + profile1.snapshots.rsync_options.value={rsync_options_value} + profiles.version={profiles_version} + """.format( config_version=6, snapshot_type=0, snapshot_value=f'{parent_path}/{cls.NAME_SOURCE}', diff --git a/common/test/test_tools.py b/common/test/test_tools.py index 06b99497f..c21c8b615 100644 --- a/common/test/test_tools.py +++ b/common/test/test_tools.py @@ -29,7 +29,7 @@ from unittest.mock import patch from tempfile import NamedTemporaryFile, TemporaryDirectory import pyfakefs.fake_filesystem_unittest as pyfakefs_ut -from test import generic, utils +from test import generic sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import tools @@ -95,7 +95,9 @@ def _create_process(self, *args): return self.subproc.pid def _kill_process(self): - utils.kill_subprocess(self.subproc) + if self.subproc: + self.subproc.kill() + self.subproc.wait() self.subproc = None def test_sharePath(self): diff --git a/common/test/utils.py b/common/test/utils.py deleted file mode 100644 index c7ac530e1..000000000 --- a/common/test/utils.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Utilities for testing""" - -config_template = """ - config.version=6 - profile1.snapshots.include.1.type={snapshot_type} - profile1.snapshots.include.1.value={snapshot_value} - profile1.snapshots.include.size={snapshot_size} - profile1.snapshots.no_on_battery={no_on_battery} - profile1.snapshots.notify.enabled={notify_enabled} - profile1.snapshots.path={snapshot_path} - profile1.snapshots.path.host={snapshot_host} - profile1.snapshots.path.profile={snapshot_profile} - profile1.snapshots.path.user={snapshot_user} - profile1.snapshots.preserve_acl={preserve_acl} - profile1.snapshots.preserve_xattr={preserve_xattr} - profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} - profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} - profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} - profile1.snapshots.rsync_options.enabled={rsync_options_enabled} - profile1.snapshots.rsync_options.value={rsync_options_value} - profiles.version={profiles_version} - """ - - -def kill_subprocess(proc): - """Kill a process and wait for it to terminate.""" - if proc: - proc.kill() - proc.wait() From 0a16463ec27b264087155ca61842ce26ca2c12b8 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sun, 25 Aug 2024 21:47:48 +0200 Subject: [PATCH 11/16] rewind --- common/test/test_config_crontab.py | 59 ++++++++++-------------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index 8eaa11bfa..59f1d78b1 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -83,45 +83,26 @@ def setUp(self): def _create_config_file(self, parent_path): """Minimal config file""" - config_data = """ - config.version={config_version} - profile1.snapshots.include.1.type={snapshot_type} - profile1.snapshots.include.1.value={snapshot_value} - profile1.snapshots.include.size={snapshot_size} - profile1.snapshots.no_on_battery={no_on_battery} - profile1.snapshots.notify.enabled={notify_enabled} - profile1.snapshots.path={snapshot_path} - profile1.snapshots.path.host={snapshot_host} - profile1.snapshots.path.profile={snapshot_profile} - profile1.snapshots.path.user={snapshot_user} - profile1.snapshots.preserve_acl={preserve_acl} - profile1.snapshots.preserve_xattr={preserve_xattr} - profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} - profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} - profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} - profile1.snapshots.rsync_options.enabled={rsync_options_enabled} - profile1.snapshots.rsync_options.value={rsync_options_value} - profiles.version={profiles_version} - """.format( - config_version=6, - snapshot_type=0, - snapshot_value='rootpath/source', - snapshot_size=1, - no_on_battery='false', - notify_enabled='true', - snapshot_path='rootpath/destination', - snapshot_host='test-host', - snapshot_profile=1, - snapshot_user='test-user', - preserve_acl='false', - preserve_xattr='false', - remove_old_snapshots_enabled='true', - remove_old_snapshots_unit=80, - remove_old_snapshots_value=10, - rsync_options_enabled='false', - rsync_options_value='', - profiles_version=1 - ) + cfg_content = inspect.cleandoc(''' + config.version=6 + profile1.snapshots.include.1.type=0 + profile1.snapshots.include.1.value=rootpath/source + profile1.snapshots.include.size=1 + profile1.snapshots.no_on_battery=false + profile1.snapshots.notify.enabled=true + profile1.snapshots.path=rootpath/destination + profile1.snapshots.path.host=test-host + profile1.snapshots.path.profile=1 + profile1.snapshots.path.user=test-user + profile1.snapshots.preserve_acl=false + profile1.snapshots.preserve_xattr=false + profile1.snapshots.remove_old_snapshots.enabled=true + profile1.snapshots.remove_old_snapshots.unit=80 + profile1.snapshots.remove_old_snapshots.value=10 + profile1.snapshots.rsync_options.enabled=false + profile1.snapshots.rsync_options.value= + profiles.version=1 + ''') cfg_content = inspect.cleandoc(config_data) # config file location From 66d3384e008fbed1ac961094191e6205e019a543 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sun, 25 Aug 2024 21:52:39 +0200 Subject: [PATCH 12/16] x --- common/test/constants.py | 9 +++- common/test/test_plugin_usercallback.py | 60 +++++++++---------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/common/test/constants.py b/common/test/constants.py index 6e5b6056f..1f72cdeac 100644 --- a/common/test/constants.py +++ b/common/test/constants.py @@ -1,5 +1,12 @@ +# SPDX-FileCopyrightText: © 2024 Ihor Pryyma +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the program "Back In Time" which is released under GNU +# General Public License v2 (GPLv2). +# See file LICENSE or go to . """ -This file contains constants that are used in the test files. +Constants that are used in the test files. """ import grp import os diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index d52b8bd68..de53b627e 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -206,46 +206,26 @@ def _create_source_and_destination_folders(cls, parent_path): @classmethod def _create_config_file(cls, parent_path): """Minimal config file""" - config_data = """ - config.version={config_version} - profile1.snapshots.include.1.type={snapshot_type} - profile1.snapshots.include.1.value={snapshot_value} - profile1.snapshots.include.size={snapshot_size} - profile1.snapshots.no_on_battery={no_on_battery} - profile1.snapshots.notify.enabled={notify_enabled} - profile1.snapshots.path={snapshot_path} - profile1.snapshots.path.host={snapshot_host} - profile1.snapshots.path.profile={snapshot_profile} - profile1.snapshots.path.user={snapshot_user} - profile1.snapshots.preserve_acl={preserve_acl} - profile1.snapshots.preserve_xattr={preserve_xattr} - profile1.snapshots.remove_old_snapshots.enabled={remove_old_snapshots_enabled} - profile1.snapshots.remove_old_snapshots.unit={remove_old_snapshots_unit} - profile1.snapshots.remove_old_snapshots.value={remove_old_snapshots_value} - profile1.snapshots.rsync_options.enabled={rsync_options_enabled} - profile1.snapshots.rsync_options.value={rsync_options_value} - profiles.version={profiles_version} - """.format( - config_version=6, - snapshot_type=0, - snapshot_value=f'{parent_path}/{cls.NAME_SOURCE}', - snapshot_size=1, - no_on_battery='false', - notify_enabled='true', - snapshot_path=f'{parent_path}/{cls.NAME_DESTINATION}', - snapshot_host='test-host', - snapshot_profile=1, - snapshot_user='test-user', - preserve_acl='false', - preserve_xattr='false', - remove_old_snapshots_enabled='true', - remove_old_snapshots_unit=80, - remove_old_snapshots_value=10, - rsync_options_enabled='false', - rsync_options_value='', - profiles_version=1 - ) - cfg_content = inspect.cleandoc(config_data) + cfg_content = inspect.cleandoc(''' + config.version=6 + profile1.snapshots.include.1.type=0 + profile1.snapshots.include.1.value={rootpath}/{source} + profile1.snapshots.include.size=1 + profile1.snapshots.no_on_battery=false + profile1.snapshots.notify.enabled=true + profile1.snapshots.path={rootpath}/{destination} + profile1.snapshots.path.host=test-host + profile1.snapshots.path.profile=1 + profile1.snapshots.path.user=test-user + profile1.snapshots.preserve_acl=false + profile1.snapshots.preserve_xattr=false + profile1.snapshots.remove_old_snapshots.enabled=true + profile1.snapshots.remove_old_snapshots.unit=80 + profile1.snapshots.remove_old_snapshots.value=10 + profile1.snapshots.rsync_options.enabled=false + profile1.snapshots.rsync_options.value= + profiles.version=1 + ''') cfg_content = cfg_content.format( rootpath=parent_path, From 9bf7ca0d73e3447255d112e57de5c0fadfbd60e8 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sun, 25 Aug 2024 21:56:17 +0200 Subject: [PATCH 13/16] x [skip ci] --- common/test/constants.py | 4 +++ common/test/test_config_crontab.py | 20 +++++--------- common/test/test_plugin_usercallback.py | 36 ++++++++++++------------- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/common/test/constants.py b/common/test/constants.py index 1f72cdeac..c3b2449a7 100644 --- a/common/test/constants.py +++ b/common/test/constants.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: © 2008-2022 Oprea Dan +# SPDX-FileCopyrightText: © 2008-2022 Bart de Koning +# SPDX-FileCopyrightText: © 2008-2022 Richard Bailey +# SPDX-FileCopyrightText: © 2008-2022 Germar Reitze # SPDX-FileCopyrightText: © 2024 Ihor Pryyma # # SPDX-License-Identifier: GPL-2.0-or-later diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index 59f1d78b1..63ee23cf6 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -1,19 +1,11 @@ -# Back In Time -# Copyright (C) 2024 Kosta Vukicevic, Christian Buhtz +# SPDX-FileCopyrightText: © 2024 Christian Buhtz +# SPDX-FileCopyrightText: © 2024 Kosta Vukicevic # -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. +# SPDX-License-Identifier: GPL-2.0-or-later # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation,Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# This file is part of the program "Back In Time" which is released under GNU +# General Public License v2 (GPLv2). +# See file LICENSE or go to . """Tests about Cron-related behavior of the config module. See also test_schedule.py for low-level-Cron-behavior implemented in schedule diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index de53b627e..077eb3251 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -207,24 +207,24 @@ def _create_source_and_destination_folders(cls, parent_path): def _create_config_file(cls, parent_path): """Minimal config file""" cfg_content = inspect.cleandoc(''' - config.version=6 - profile1.snapshots.include.1.type=0 - profile1.snapshots.include.1.value={rootpath}/{source} - profile1.snapshots.include.size=1 - profile1.snapshots.no_on_battery=false - profile1.snapshots.notify.enabled=true - profile1.snapshots.path={rootpath}/{destination} - profile1.snapshots.path.host=test-host - profile1.snapshots.path.profile=1 - profile1.snapshots.path.user=test-user - profile1.snapshots.preserve_acl=false - profile1.snapshots.preserve_xattr=false - profile1.snapshots.remove_old_snapshots.enabled=true - profile1.snapshots.remove_old_snapshots.unit=80 - profile1.snapshots.remove_old_snapshots.value=10 - profile1.snapshots.rsync_options.enabled=false - profile1.snapshots.rsync_options.value= - profiles.version=1 + config.version=6 + profile1.snapshots.include.1.type=0 + profile1.snapshots.include.1.value={rootpath}/{source} + profile1.snapshots.include.size=1 + profile1.snapshots.no_on_battery=false + profile1.snapshots.notify.enabled=true + profile1.snapshots.path={rootpath}/{destination} + profile1.snapshots.path.host=test-host + profile1.snapshots.path.profile=1 + profile1.snapshots.path.user=test-user + profile1.snapshots.preserve_acl=false + profile1.snapshots.preserve_xattr=false + profile1.snapshots.remove_old_snapshots.enabled=true + profile1.snapshots.remove_old_snapshots.unit=80 + profile1.snapshots.remove_old_snapshots.value=10 + profile1.snapshots.rsync_options.enabled=false + profile1.snapshots.rsync_options.value= + profiles.version=1 ''') cfg_content = cfg_content.format( From be71c47d9a2e2cb3f4e62066e0cc48f000685ff7 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sun, 25 Aug 2024 21:57:04 +0200 Subject: [PATCH 14/16] x [skip ci] --- common/test/test_config_crontab.py | 1 - 1 file changed, 1 deletion(-) diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index 63ee23cf6..4cfc23542 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -95,7 +95,6 @@ def _create_config_file(self, parent_path): profile1.snapshots.rsync_options.value= profiles.version=1 ''') - cfg_content = inspect.cleandoc(config_data) # config file location config_fp = parent_path / 'config_path' / 'config' From 158d4fb0d4262a5b18b6b2caa04afc2e4ffc2b75 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sun, 25 Aug 2024 22:05:18 +0200 Subject: [PATCH 15/16] x --- common/test/test_applicationinstance.py | 1 + common/test/test_plugin_usercallback.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/test/test_applicationinstance.py b/common/test/test_applicationinstance.py index e038bee56..8af1b67bf 100644 --- a/common/test/test_applicationinstance.py +++ b/common/test/test_applicationinstance.py @@ -17,6 +17,7 @@ import os import sys +import subprocess from unittest.mock import patch from threading import Thread diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index 077eb3251..a339fb927 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -1,10 +1,12 @@ +import sys import inspect import io import unittest import unittest.mock as mock +import tempfile +import stat from contextlib import redirect_stdout, redirect_stderr from ast import literal_eval -from contextlib import redirect_stderr, redirect_stdout from pathlib import Path # This workaround will become obsolet when migrating to src-layout From d8486f24e971f2e80215dd82bedf9aaea189b707 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sun, 25 Aug 2024 22:12:28 +0200 Subject: [PATCH 16/16] fin --- common/test/test_config_crontab.py | 1 + common/test/test_plugin_usercallback.py | 1 + common/test/test_snapshots.py | 2 -- common/test/test_tools.py | 3 ++- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/test/test_config_crontab.py b/common/test/test_config_crontab.py index 4cfc23542..693a68b72 100644 --- a/common/test/test_config_crontab.py +++ b/common/test/test_config_crontab.py @@ -75,6 +75,7 @@ def setUp(self): def _create_config_file(self, parent_path): """Minimal config file""" + # pylint: disable-next=R0801 cfg_content = inspect.cleandoc(''' config.version=6 profile1.snapshots.include.1.type=0 diff --git a/common/test/test_plugin_usercallback.py b/common/test/test_plugin_usercallback.py index a339fb927..7213e485d 100644 --- a/common/test/test_plugin_usercallback.py +++ b/common/test/test_plugin_usercallback.py @@ -208,6 +208,7 @@ def _create_source_and_destination_folders(cls, parent_path): @classmethod def _create_config_file(cls, parent_path): """Minimal config file""" + # pylint: disable-next=R0801 cfg_content = inspect.cleandoc(''' config.version=6 profile1.snapshots.include.1.type=0 diff --git a/common/test/test_snapshots.py b/common/test/test_snapshots.py index 9fd0ef5fb..925cfa898 100644 --- a/common/test/test_snapshots.py +++ b/common/test/test_snapshots.py @@ -14,13 +14,11 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation,Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - import os import sys import pathlib import shutil import stat -import pwd import grp import re import random diff --git a/common/test/test_tools.py b/common/test/test_tools.py index bf0888739..87f47edc1 100644 --- a/common/test/test_tools.py +++ b/common/test/test_tools.py @@ -23,9 +23,10 @@ import gzip import stat import signal +from datetime import datetime +from time import sleep from unittest.mock import patch from copy import deepcopy -from unittest.mock import patch from tempfile import NamedTemporaryFile, TemporaryDirectory import pyfakefs.fake_filesystem_unittest as pyfakefs_ut from test import generic