From 7bd4900194ecf42bc8efa5e7eedef2e1d3f52904 Mon Sep 17 00:00:00 2001 From: ratchek Date: Wed, 22 Feb 2023 17:05:50 -0500 Subject: [PATCH 01/24] Add development flag to options. This does nothing for now except echo that it was called to terminal. --- src/vorta/__main__.py | 4 ++++ src/vorta/utils.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index eb2ca3a1c..a0bda68b5 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -45,6 +45,7 @@ def exception_handler(type, value, tb): want_version = getattr(args, 'version', False) want_background = getattr(args, 'daemonize', False) + want_development = getattr(args, 'development', False) if want_version: print(f"Vorta {__version__}") @@ -54,6 +55,9 @@ def exception_handler(type, value, tb): if os.fork(): sys.exit() + if want_development: + print("In dev mode") + init_logger(background=want_background) # Init database diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 6217fb518..9982fe379 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -358,7 +358,13 @@ def parse_args(): help='Create a backup in the background using the given profile. ' 'Vorta must already be running for this to work.', ) - + parser.add_argument( + '--development', + '-D', + action='store_true', + help='Start vorta in a local development environment' + 'All log, config, cache, and temp files will be stored within the project tree', + ) return parser.parse_known_args()[0] From 29d7bf25d2f81052f37f9192297c9be03eb5fc04 Mon Sep 17 00:00:00 2001 From: yfprojects <62463991+real-yfprojects@users.noreply.github.com> Date: Sat, 25 Feb 2023 10:10:43 +0000 Subject: [PATCH 02/24] Add tooltips to settings. (#1521) This adds tooltips to the settings as well as a 'info' button that shows the tooltip when hovering over it. * Add tooltips to settings. * src/vorta/store/models.py (SettingsModel): Add `tooltip` column. * src/vorta/store/migrations.py (run_migrations): Create `tooltip` column. * src/vorta/store/connection.py (init_db): Populate `tooltip` column. Increase `SCHEMA_VERSION`. * src/vorta/views/misc_tab.py (MiscTab.populate): Set tooltip of checkbox widgets. * src/vorta/store/settings.py : Add tooltips and update label of `override_mount_permissions` * Add *help* button to settings. * src/vorta/assets/icons/help-about.svg: Add info icon. * src/vorta/views/partials/tooltip_button.py: Implement `ToolTipButton`. * src/vorta/views/misc_tab.py: Add `ToolTipButton` for each setting with a tooltip. Add `set_icons` and connect it to palette change. * tests/test_misc.py (test_autostart): Update test. --------- Co-authored-by: real-yfprojects --- src/vorta/assets/icons/help-about.svg | 12 ++ src/vorta/store/connection.py | 4 +- src/vorta/store/migrations.py | 7 ++ src/vorta/store/models.py | 1 + src/vorta/store/settings.py | 11 +- src/vorta/views/misc_tab.py | 30 ++++- src/vorta/views/partials/tooltip_button.py | 127 +++++++++++++++++++++ tests/test_misc.py | 2 +- 8 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 src/vorta/assets/icons/help-about.svg create mode 100644 src/vorta/views/partials/tooltip_button.py diff --git a/src/vorta/assets/icons/help-about.svg b/src/vorta/assets/icons/help-about.svg new file mode 100644 index 000000000..89fc594e2 --- /dev/null +++ b/src/vorta/assets/icons/help-about.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/vorta/store/connection.py b/src/vorta/store/connection.py index ff1a2b483..72a3461f2 100644 --- a/src/vorta/store/connection.py +++ b/src/vorta/store/connection.py @@ -18,7 +18,7 @@ ) from .settings import get_misc_settings -SCHEMA_VERSION = 19 +SCHEMA_VERSION = 20 @signals.post_save(sender=SettingsModel) @@ -91,5 +91,7 @@ def init_db(con=None): if 'group' in setting: s.group = setting['group'] + if 'tooltip' in setting: + s.tooltip = setting['tooltip'] s.save() diff --git a/src/vorta/store/migrations.py b/src/vorta/store/migrations.py index 4603d7438..0db00e9fb 100644 --- a/src/vorta/store/migrations.py +++ b/src/vorta/store/migrations.py @@ -219,6 +219,13 @@ def run_migrations(current_schema, db_connection): migrator.add_column(SettingsModel._meta.table_name, 'group', pw.CharField(default='')), ) + if current_schema.version < 20: + _apply_schema_update( + current_schema, + 20, + migrator.add_column(SettingsModel._meta.table_name, 'tooltip', pw.CharField(default='')), + ) + def _apply_schema_update(current_schema, version_after, *operations): with DB.atomic(): diff --git a/src/vorta/store/models.py b/src/vorta/store/models.py index 814652b63..c893764e4 100644 --- a/src/vorta/store/models.py +++ b/src/vorta/store/models.py @@ -185,6 +185,7 @@ class SettingsModel(BaseModel): str_value = pw.CharField(default='') label = pw.CharField() group = pw.CharField(default='') # Settings group name and label + tooltip = pw.CharField(default='') # optional tooltip for `checkbox` type type = pw.CharField() class Meta: diff --git a/src/vorta/store/settings.py b/src/vorta/store/settings.py index ae0b2006c..3bcac8653 100644 --- a/src/vorta/store/settings.py +++ b/src/vorta/store/settings.py @@ -32,7 +32,7 @@ def get_misc_settings() -> List[Dict[str, str]]: 'value': False, 'type': 'checkbox', 'group': notifications, - 'label': trans_late('settings', 'Also notify about successful background tasks'), + 'label': trans_late('settings', 'Notify about successful background tasks'), }, { 'key': 'autostart', @@ -40,6 +40,7 @@ def get_misc_settings() -> List[Dict[str, str]]: 'type': 'checkbox', 'group': startup, 'label': trans_late('settings', 'Automatically start Vorta at login'), + 'tooltip': trans_late('settings', 'Add Vorta to the systems autostart list'), }, { 'key': 'foreground', @@ -47,6 +48,7 @@ def get_misc_settings() -> List[Dict[str, str]]: 'type': 'checkbox', 'group': startup, 'label': trans_late('settings', 'Open main window on startup'), + 'tooltip': trans_late('settings', 'Open main window when the application is launched'), }, { 'key': 'get_srcpath_datasize', @@ -54,6 +56,7 @@ def get_misc_settings() -> List[Dict[str, str]]: 'type': 'checkbox', 'group': information, 'label': trans_late('settings', 'Get statistics of file/folder when added'), + 'tooltip': trans_late('settings', 'When adding a new source, calculate its size and the number of files.'), }, { 'key': 'use_system_keyring', @@ -64,6 +67,9 @@ def get_misc_settings() -> List[Dict[str, str]]: 'settings', 'Store repository passwords in system keychain, if available', ), + 'tooltip': trans_late( + 'settings', "Otherwise Vorta's configuration database stores the password in plaintext." + ), }, { 'key': 'override_mount_permissions', @@ -72,8 +78,9 @@ def get_misc_settings() -> List[Dict[str, str]]: 'group': security, 'label': trans_late( 'settings', - 'Try to replace existing permissions when mounting an archive', + 'Try to replace file permissions when mounting an archive', ), + 'tooltip': trans_late('settings', 'Set owner to current user and umask to 0277'), }, { 'key': 'previous_profile_id', diff --git a/src/vorta/views/misc_tab.py b/src/vorta/views/misc_tab.py index b30438034..a94b4d286 100644 --- a/src/vorta/views/misc_tab.py +++ b/src/vorta/views/misc_tab.py @@ -1,13 +1,15 @@ import logging from PyQt5 import uic from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QCheckBox, QFormLayout, QLabel, QSizePolicy, QSpacerItem +from PyQt5.QtWidgets import QApplication, QCheckBox, QFormLayout, QHBoxLayout, QLabel, QSizePolicy, QSpacerItem from vorta._version import __version__ from vorta.config import LOG_DIR from vorta.i18n import translate from vorta.store.models import BackupProfileMixin, SettingsModel from vorta.store.settings import get_misc_settings from vorta.utils import get_asset, search +from vorta.views.partials.tooltip_button import ToolTipButton +from vorta.views.utils import get_colored_icon uifile = get_asset('UI/misctab.ui') MiscTabUI, MiscTabBase = uic.loadUiType(uifile) @@ -29,10 +31,15 @@ def __init__(self, parent=None): self.checkboxLayout.setSpacing(4) self.checkboxLayout.setHorizontalSpacing(8) self.checkboxLayout.setContentsMargins(0, 0, 0, 12) + self.checkboxLayout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.FieldsStayAtSizeHint) self.checkboxLayout.setFormAlignment(Qt.AlignmentFlag.AlignHCenter) + self.tooltip_buttons = [] self.populate() + # Connect to palette change + QApplication.instance().paletteChanged.connect(lambda p: self.set_icons()) + def populate(self): """ Populate the misc tab with the settings widgets. @@ -45,6 +52,7 @@ def populate(self): self.checkboxLayout.removeItem(child) if child.widget(): child.widget().deleteLater() + self.tooltip_buttons = [] # dynamically add widgets for settings misc_settings = get_misc_settings() @@ -78,16 +86,34 @@ def populate(self): # create widget cb = QCheckBox(translate('settings', setting.label)) + cb.setToolTip(setting.tooltip) cb.setCheckState(setting.value) cb.setTristate(False) cb.stateChanged.connect(lambda v, key=setting.key: self.save_setting(key, v)) + tb = ToolTipButton() + tb.setToolTip(setting.tooltip) + + cbl = QHBoxLayout() + cbl.addWidget(cb) + if setting.tooltip: + cbl.addWidget(tb) + cbl.addItem(QSpacerItem(0, 0, hPolicy=QSizePolicy.Policy.Expanding)) + # add widget - self.checkboxLayout.setWidget(i, QFormLayout.ItemRole.FieldRole, cb) + self.checkboxLayout.setLayout(i, QFormLayout.ItemRole.FieldRole, cbl) + self.tooltip_buttons.append(tb) # increase i i += 1 + self.set_icons() + + def set_icons(self): + """Set or update the icons in this view.""" + for button in self.tooltip_buttons: + button.setIcon(get_colored_icon('help-about')) + def save_setting(self, key, new_value): setting = SettingsModel.get(key=key) setting.value = bool(new_value) diff --git a/src/vorta/views/partials/tooltip_button.py b/src/vorta/views/partials/tooltip_button.py new file mode 100644 index 000000000..bde53a81f --- /dev/null +++ b/src/vorta/views/partials/tooltip_button.py @@ -0,0 +1,127 @@ +from typing import Optional +from PyQt5.QtCore import QCoreApplication, QEvent, QSize, Qt +from PyQt5.QtGui import QHelpEvent, QIcon, QMouseEvent, QPaintEvent +from PyQt5.QtWidgets import QSizePolicy, QStyle, QStylePainter, QToolTip, QWidget + + +class ToolTipButton(QWidget): + """ + A flat button showing a tooltip when the mouse moves over it. + + The default icon is `help-about`. + + Parameters + ---------- + icon : QIcon, optional + The icon to display, by default `help-about` + parent : QWidget, optional + The parent of this widget, by default None + """ + + def __init__(self, icon: Optional[QIcon] = None, parent: Optional[QWidget] = None) -> None: + """ + Init. + """ + super().__init__(parent) + self.setCursor(Qt.CursorShape.WhatsThisCursor) + self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.setMouseTracking(True) + self._icon = icon or QIcon() + + def sizeHint(self) -> QSize: + """ + Get the recommended size for the widget. + + Returns + ------- + QSize + + See Also + -------- + https://doc.qt.io/qt-5/qwidget.html#sizeHint-prop + """ + size = self.style().pixelMetric(QStyle.PixelMetric.PM_ButtonIconSize) + return QSize(size, size) + + def paintEvent(self, event: QPaintEvent) -> None: + """ + Repaint the widget on receiving a paint event. + + A paint event is a request to repaint all or part of a widget. + It can happen for one of the following reasons: + + - repaint() or update() was invoked, + - the widget was obscured and has now been uncovered, or + - many other reasons. + + Many widgets can simply repaint their entire surface when asked to, + but some slow widgets need to optimize by painting only the + requested region: QPaintEvent::region(). + This speed optimization does not change the result, + as painting is clipped to that region during event processing. + QListView and QTableView do this, for example. + + Parameters + ---------- + event : QPaintEvent + The paint event + + See Also + -------- + https://doc.qt.io/qt-5/qwidget.html#paintEvent + """ + painter = QStylePainter(self) + if self._icon: + painter.drawPixmap( + event.rect(), + self._icon.pixmap(event.rect().size(), QIcon.Mode.Normal if self.isEnabled() else QIcon.Mode.Disabled), + ) + painter.end() + + def mouseMoveEvent(self, event: QMouseEvent) -> None: + """ + Process mouse move events for this widget. + + If mouse tracking is switched off, mouse move events only occur if a + mouse button is pressed while the mouse is being moved. + If mouse tracking is switched on, mouse move events occur even + if no mouse button is pressed. + + Parameters + ---------- + event : QMouseEvent + The corresponding mouse event. + + See Also + -------- + setMouseTracking + https://doc.qt.io/qt-5/qwidget.html#mouseMoveEvent + """ + super().mouseMoveEvent(event) + QToolTip.showText(event.globalPos(), self.toolTip(), self) + QCoreApplication.postEvent(self, QHelpEvent(QEvent.Type.ToolTip, event.pos(), event.globalPos())) + + def setIcon(self, icon: QIcon): + """ + Set the icon displayed by the widget. + + This triggers a repaint event. + + Parameters + ---------- + icon : QIcon + The new icon. + """ + self._icon = icon + self.update() + + def icon(self) -> QIcon: + """ + Get the icon displayed by the widget. + + Returns + ------- + QIcon + The current icon. + """ + return self._icon diff --git a/tests/test_misc.py b/tests/test_misc.py index 1f721f9f0..e9cce1b29 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -17,7 +17,7 @@ def click_autostart(): item = tab.checkboxLayout.itemAt(x, QFormLayout.ItemRole.FieldRole) if not item: continue - checkbox = item.widget() + checkbox = item.itemAt(0).widget() checkbox.__class__ = QCheckBox if checkbox.text().startswith("Automatically"): # Have to use pos to click checkbox correctly From 58d71ac20816520dd8e5d84d3029a0c1b8d1440c Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Thu, 2 Mar 2023 22:25:31 +0530 Subject: [PATCH 03/24] Fix detecting whether sources are configured (#1613) Fixes #1463. This makes the code count the database rows for the current profile only. Previously one could run a backup without any sources when one had sources configured in a different profile. * src/vorta/borg/create.py (BorgCreateJob.prepare) --- src/vorta/borg/create.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vorta/borg/create.py b/src/vorta/borg/create.py index 904df6cad..3f338d25a 100644 --- a/src/vorta/borg/create.py +++ b/src/vorta/borg/create.py @@ -77,7 +77,7 @@ def prepare(cls, profile): else: ret['ok'] = False # Set back to False, so we can do our own checks here. - n_backup_folders = SourceFileModel.select().count() + n_backup_folders = SourceFileModel.select().where(SourceFileModel.profile == profile).count() # cmd options like `--paths-from-command` require a command # that is appended to the arguments From 4538ce7ea13f297cc147a82f2d31c7cdddaf5da5 Mon Sep 17 00:00:00 2001 From: ratchek Date: Fri, 3 Mar 2023 12:26:33 -0500 Subject: [PATCH 04/24] Add a development mode (#1162) This creates the option to use the --development or -D flags to launch vorta in development mode which stores all settings, cache, temp, and log files in the project tree instead of in the default places for the system. Allows for working on the project without it pulling in the settings from the system-wide copy of vorta that you use for your actual backups. --- .gitignore | 2 ++ src/vorta/__main__.py | 28 +++++++++++++++++++++++++--- src/vorta/config.py | 1 + 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7ebab259f..51cc48c65 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ env venv .env .venv +# dirs created by the --development option +dev/ # Avoid adding translations of source language # Files are still used by Transifex src/vorta/i18n/ts/vorta.en.ts diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index a0bda68b5..c9f28871e 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -2,8 +2,11 @@ import signal import sys from peewee import SqliteDatabase + +# Need to import config as a whole module instead of individual variables +# because we will be overriding the modules variables +import vorta.config as config from vorta._version import __version__ -from vorta.config import SETTINGS_DIR from vorta.i18n import trans_late, translate from vorta.log import init_logger, logger from vorta.store.connection import init_db @@ -56,13 +59,32 @@ def exception_handler(type, value, tb): sys.exit() if want_development: - print("In dev mode") + if not os.path.exists(config.DEV_MODE_DIR): + os.makedirs(config.DEV_MODE_DIR) + + config.SETTINGS_DIR = config.DEV_MODE_DIR / 'settings' + if not os.path.exists(config.SETTINGS_DIR): + os.makedirs(config.SETTINGS_DIR) + + config.LOG_DIR = config.DEV_MODE_DIR / 'logs' + if not os.path.exists(config.LOG_DIR): + os.makedirs(config.LOG_DIR) + + config.CACHE_DIR = config.DEV_MODE_DIR / 'cache' + if not os.path.exists(config.CACHE_DIR): + os.makedirs(config.CACHE_DIR) + + config.TEMP_DIR = config.CACHE_DIR / 'tmp' + if not os.path.exists(config.TEMP_DIR): + os.makedirs(config.TEMP_DIR) + + config.PROFILE_BOOTSTRAP_FILE = config.DEV_MODE_DIR / '.vorta-init.json' init_logger(background=want_background) # Init database sqlite_db = SqliteDatabase( - os.path.join(SETTINGS_DIR, 'settings.db'), + os.path.join(config.SETTINGS_DIR, 'settings.db'), pragmas={ 'journal_mode': 'wal', }, diff --git a/src/vorta/config.py b/src/vorta/config.py index c744f55e0..94f2ab44c 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -11,6 +11,7 @@ CACHE_DIR = dirs.user_cache_dir TEMP_DIR = os.path.join(CACHE_DIR, "tmp") PROFILE_BOOTSTRAP_FILE = Path.home() / '.vorta-init.json' +DEV_MODE_DIR = Path(__file__).parent.parent.parent / 'dev' if not os.path.exists(SETTINGS_DIR): os.makedirs(SETTINGS_DIR) From 4d2f9690358d90f0bd978a42e1508936e4ffe75b Mon Sep 17 00:00:00 2001 From: ratchek Date: Fri, 17 Mar 2023 16:50:36 -0400 Subject: [PATCH 05/24] Modify the config directory to a hidden directory and add config to the name --- src/vorta/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vorta/config.py b/src/vorta/config.py index 36c30e682..191a67022 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -10,7 +10,7 @@ CACHE_DIR = dirs.user_cache_path TEMP_DIR = CACHE_DIR / "tmp" PROFILE_BOOTSTRAP_FILE = Path.home() / '.vorta-init.json' -DEV_MODE_DIR = Path(__file__).parent.parent.parent / 'dev' +DEV_MODE_DIR = Path(__file__).parent.parent.parent / '.dev_config' # ensure directories exist From 3ef5e54d9bdabadb29d0da79fcda4dce0cd9fd94 Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 4 Apr 2023 13:12:35 -0400 Subject: [PATCH 06/24] Add support for custom dev dirs --- src/vorta/__main__.py | 17 +++++++++++++++-- src/vorta/utils.py | 17 ++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 0a8146682..322434c63 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -1,6 +1,7 @@ import os import signal import sys +from pathlib import Path from peewee import SqliteDatabase # Need to import config as a whole module instead of individual variables @@ -11,7 +12,7 @@ from vorta.log import init_logger, logger from vorta.store.connection import init_db from vorta.updater import get_updater -from vorta.utils import parse_args +from vorta.utils import DEFAULT_DIR_FLAG, parse_args def main(): @@ -48,7 +49,7 @@ def exception_handler(type, value, tb): want_version = getattr(args, 'version', False) want_background = getattr(args, 'daemonize', False) - want_development = getattr(args, 'development', False) + want_development = getattr(args, 'development') if want_version: print(f"Vorta {__version__}") @@ -58,7 +59,16 @@ def exception_handler(type, value, tb): if os.fork(): sys.exit() + # want_development is None when flag is not called + # it's set to the default directory when flag is called without an argument + # and it's set to the flag's argument if the flag has one if want_development: + if want_development == DEFAULT_DIR_FLAG: + print("I'm using the default directory") + else: + print("I'm using this config: ", want_development) + config.DEV_MODE_DIR = Path(want_development) + if not os.path.exists(config.DEV_MODE_DIR): os.makedirs(config.DEV_MODE_DIR) @@ -80,6 +90,9 @@ def exception_handler(type, value, tb): config.PROFILE_BOOTSTRAP_FILE = config.DEV_MODE_DIR / '.vorta-init.json' + # except Exception as exception: + # print("That's an invalid path for a dir \n", exception) + init_logger(background=want_background) # Init database diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 65a8e5502..d5e42baf9 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -20,6 +20,10 @@ from vorta.log import logger from vorta.network_status.abc import NetworkStatusMonitor +# Used to store whether a user wanted to override the +# default directory for the --development flag +DEFAULT_DIR_FLAG = "USE_DEFAULT_DIR" + QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons @@ -354,12 +358,19 @@ def parse_args(): help='Create a backup in the background using the given profile. ' 'Vorta must already be running for this to work.', ) + # the "development" attribute will be None if the flag is not called + # if the flag is called without an extra argument, the "development" attribute + # will be set to the value of DEFAULT_DIR_FLAG. + # if the flag is called with an extra argument, the "development" attribute + # will be set to that argument parser.add_argument( '--development', '-D', - action='store_true', - help='Start vorta in a local development environment' - 'All log, config, cache, and temp files will be stored within the project tree', + nargs='?', + const=DEFAULT_DIR_FLAG, + help='Start vorta in a local development environment. ' + 'All log, config, cache, and temp files will be stored within the project tree. ' + 'You can follow this flag with an optional path and it will store the files in the provided location.', ) return parser.parse_known_args()[0] From 28d934031a83d6bf9c8a8da4cbe2bb6d79781f6c Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 4 Apr 2023 13:13:27 -0400 Subject: [PATCH 07/24] Change the default dev config dir in gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 51cc48c65..7d83381b0 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ venv .env .venv # dirs created by the --development option -dev/ +.dev_config/ # Avoid adding translations of source language # Files are still used by Transifex src/vorta/i18n/ts/vorta.en.ts From 2b0b75631f20c8b83c22070f730af58431c84469 Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 4 Apr 2023 13:20:43 -0400 Subject: [PATCH 08/24] Clean up print statements used for debugging --- src/vorta/__main__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 322434c63..2e218aade 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -64,9 +64,8 @@ def exception_handler(type, value, tb): # and it's set to the flag's argument if the flag has one if want_development: if want_development == DEFAULT_DIR_FLAG: - print("I'm using the default directory") + pass else: - print("I'm using this config: ", want_development) config.DEV_MODE_DIR = Path(want_development) if not os.path.exists(config.DEV_MODE_DIR): From 097cac75ff413ff72255937b4b980f1d3e2b082a Mon Sep 17 00:00:00 2001 From: ratchek Date: Wed, 22 Feb 2023 17:05:50 -0500 Subject: [PATCH 09/24] Add development flag to options. This does nothing for now except echo that it was called to terminal. --- src/vorta/__main__.py | 4 ++++ src/vorta/utils.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 34a5bd8c3..f66107855 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -45,6 +45,7 @@ def exception_handler(type, value, tb): want_version = getattr(args, 'version', False) want_background = getattr(args, 'daemonize', False) + want_development = getattr(args, 'development', False) if want_version: print(f"Vorta {__version__}") @@ -54,6 +55,9 @@ def exception_handler(type, value, tb): if os.fork(): sys.exit() + if want_development: + print("In dev mode") + init_logger(background=want_background) # Init database diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 774949d6b..65a8e5502 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -354,7 +354,13 @@ def parse_args(): help='Create a backup in the background using the given profile. ' 'Vorta must already be running for this to work.', ) - + parser.add_argument( + '--development', + '-D', + action='store_true', + help='Start vorta in a local development environment' + 'All log, config, cache, and temp files will be stored within the project tree', + ) return parser.parse_known_args()[0] From a2d7e754e531897b53914bac8591c39346a49c15 Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 4 Apr 2023 13:13:27 -0400 Subject: [PATCH 10/24] Change the default dev config dir in gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 7ebab259f..7d83381b0 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ env venv .env .venv +# dirs created by the --development option +.dev_config/ # Avoid adding translations of source language # Files are still used by Transifex src/vorta/i18n/ts/vorta.en.ts From 2a2165158d1f0f358f5e036139f1ddb6f1114708 Mon Sep 17 00:00:00 2001 From: ratchek Date: Fri, 3 Mar 2023 12:26:33 -0500 Subject: [PATCH 11/24] Add a development mode (#1162) This creates the option to use the --development or -D flags to launch vorta in development mode which stores all settings, cache, temp, and log files in the project tree instead of in the default places for the system. Allows for working on the project without it pulling in the settings from the system-wide copy of vorta that you use for your actual backups. --- src/vorta/__main__.py | 28 +++++++++++++++++++++++++--- src/vorta/config.py | 1 + 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index f66107855..0a8146682 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -2,8 +2,11 @@ import signal import sys from peewee import SqliteDatabase + +# Need to import config as a whole module instead of individual variables +# because we will be overriding the modules variables +import vorta.config as config from vorta._version import __version__ -from vorta.config import SETTINGS_DIR from vorta.i18n import trans_late, translate from vorta.log import init_logger, logger from vorta.store.connection import init_db @@ -56,13 +59,32 @@ def exception_handler(type, value, tb): sys.exit() if want_development: - print("In dev mode") + if not os.path.exists(config.DEV_MODE_DIR): + os.makedirs(config.DEV_MODE_DIR) + + config.SETTINGS_DIR = config.DEV_MODE_DIR / 'settings' + if not os.path.exists(config.SETTINGS_DIR): + os.makedirs(config.SETTINGS_DIR) + + config.LOG_DIR = config.DEV_MODE_DIR / 'logs' + if not os.path.exists(config.LOG_DIR): + os.makedirs(config.LOG_DIR) + + config.CACHE_DIR = config.DEV_MODE_DIR / 'cache' + if not os.path.exists(config.CACHE_DIR): + os.makedirs(config.CACHE_DIR) + + config.TEMP_DIR = config.CACHE_DIR / 'tmp' + if not os.path.exists(config.TEMP_DIR): + os.makedirs(config.TEMP_DIR) + + config.PROFILE_BOOTSTRAP_FILE = config.DEV_MODE_DIR / '.vorta-init.json' init_logger(background=want_background) # Init database sqlite_db = SqliteDatabase( - SETTINGS_DIR / 'settings.db', + config.SETTINGS_DIR / 'settings.db', pragmas={ 'journal_mode': 'wal', }, diff --git a/src/vorta/config.py b/src/vorta/config.py index 80961e1b5..36c30e682 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -10,6 +10,7 @@ CACHE_DIR = dirs.user_cache_path TEMP_DIR = CACHE_DIR / "tmp" PROFILE_BOOTSTRAP_FILE = Path.home() / '.vorta-init.json' +DEV_MODE_DIR = Path(__file__).parent.parent.parent / 'dev' # ensure directories exist From 382eb70529652a757b4b98d9b86c5c83d156728f Mon Sep 17 00:00:00 2001 From: ratchek Date: Fri, 17 Mar 2023 16:50:36 -0400 Subject: [PATCH 12/24] Modify the config directory to a hidden directory and add config to the name --- src/vorta/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vorta/config.py b/src/vorta/config.py index 36c30e682..191a67022 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -10,7 +10,7 @@ CACHE_DIR = dirs.user_cache_path TEMP_DIR = CACHE_DIR / "tmp" PROFILE_BOOTSTRAP_FILE = Path.home() / '.vorta-init.json' -DEV_MODE_DIR = Path(__file__).parent.parent.parent / 'dev' +DEV_MODE_DIR = Path(__file__).parent.parent.parent / '.dev_config' # ensure directories exist From e7ba167c9930e9fe338af46e8dd0729df9709832 Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 4 Apr 2023 13:12:35 -0400 Subject: [PATCH 13/24] Add support for custom dev dirs --- src/vorta/__main__.py | 17 +++++++++++++++-- src/vorta/utils.py | 17 ++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 0a8146682..322434c63 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -1,6 +1,7 @@ import os import signal import sys +from pathlib import Path from peewee import SqliteDatabase # Need to import config as a whole module instead of individual variables @@ -11,7 +12,7 @@ from vorta.log import init_logger, logger from vorta.store.connection import init_db from vorta.updater import get_updater -from vorta.utils import parse_args +from vorta.utils import DEFAULT_DIR_FLAG, parse_args def main(): @@ -48,7 +49,7 @@ def exception_handler(type, value, tb): want_version = getattr(args, 'version', False) want_background = getattr(args, 'daemonize', False) - want_development = getattr(args, 'development', False) + want_development = getattr(args, 'development') if want_version: print(f"Vorta {__version__}") @@ -58,7 +59,16 @@ def exception_handler(type, value, tb): if os.fork(): sys.exit() + # want_development is None when flag is not called + # it's set to the default directory when flag is called without an argument + # and it's set to the flag's argument if the flag has one if want_development: + if want_development == DEFAULT_DIR_FLAG: + print("I'm using the default directory") + else: + print("I'm using this config: ", want_development) + config.DEV_MODE_DIR = Path(want_development) + if not os.path.exists(config.DEV_MODE_DIR): os.makedirs(config.DEV_MODE_DIR) @@ -80,6 +90,9 @@ def exception_handler(type, value, tb): config.PROFILE_BOOTSTRAP_FILE = config.DEV_MODE_DIR / '.vorta-init.json' + # except Exception as exception: + # print("That's an invalid path for a dir \n", exception) + init_logger(background=want_background) # Init database diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 65a8e5502..d5e42baf9 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -20,6 +20,10 @@ from vorta.log import logger from vorta.network_status.abc import NetworkStatusMonitor +# Used to store whether a user wanted to override the +# default directory for the --development flag +DEFAULT_DIR_FLAG = "USE_DEFAULT_DIR" + QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons @@ -354,12 +358,19 @@ def parse_args(): help='Create a backup in the background using the given profile. ' 'Vorta must already be running for this to work.', ) + # the "development" attribute will be None if the flag is not called + # if the flag is called without an extra argument, the "development" attribute + # will be set to the value of DEFAULT_DIR_FLAG. + # if the flag is called with an extra argument, the "development" attribute + # will be set to that argument parser.add_argument( '--development', '-D', - action='store_true', - help='Start vorta in a local development environment' - 'All log, config, cache, and temp files will be stored within the project tree', + nargs='?', + const=DEFAULT_DIR_FLAG, + help='Start vorta in a local development environment. ' + 'All log, config, cache, and temp files will be stored within the project tree. ' + 'You can follow this flag with an optional path and it will store the files in the provided location.', ) return parser.parse_known_args()[0] From 8e4a5a1449d9da76ba8e5ddbcfa4a419f7dc8b17 Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 4 Apr 2023 13:20:43 -0400 Subject: [PATCH 14/24] Clean up print statements used for debugging --- src/vorta/__main__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 322434c63..2e218aade 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -64,9 +64,8 @@ def exception_handler(type, value, tb): # and it's set to the flag's argument if the flag has one if want_development: if want_development == DEFAULT_DIR_FLAG: - print("I'm using the default directory") + pass else: - print("I'm using this config: ", want_development) config.DEV_MODE_DIR = Path(want_development) if not os.path.exists(config.DEV_MODE_DIR): From 67ea28791f6c97ca019b03a65e951bb1bfb88830 Mon Sep 17 00:00:00 2001 From: ratchek Date: Wed, 19 Apr 2023 14:19:36 -0400 Subject: [PATCH 15/24] Fix issues as discussed in #1682. Changes based on the discussion here: https://github.com/borgbase/vorta/pull/1682 Biggest change is that src/config is rewritten to initialize the config variables while the program is running, so you need to import the whole module every time you use variables/constants from it. This was done to avoid duplicating code responsible for setting up the directory in which config data will be stored. --- src/vorta/__main__.py | 40 +++++++---------------------- src/vorta/application.py | 8 +++--- src/vorta/borg/check.py | 4 +-- src/vorta/borg/compact.py | 4 +-- src/vorta/borg/create.py | 4 +-- src/vorta/config.py | 50 ++++++++++++++++++++++++++++--------- src/vorta/utils.py | 2 +- src/vorta/views/misc_tab.py | 5 ++-- 8 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index fc1277276..1c7533301 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -6,7 +6,7 @@ # Need to import config as a whole module instead of individual variables # because we will be overriding the modules variables -import vorta.config as config +from vorta import config from vorta._version import __version__ from vorta.i18n import trans_late, translate from vorta.log import init_logger, logger @@ -49,7 +49,7 @@ def exception_handler(type, value, tb): want_version = getattr(args, 'version', False) want_background = getattr(args, 'daemonize', False) - want_development = getattr(args, 'development') + want_development = getattr(args, 'development', False) if want_version: print(f"Vorta {__version__}") @@ -59,38 +59,16 @@ def exception_handler(type, value, tb): if os.fork(): sys.exit() - # want_development is None when flag is not called - # it's set to the default directory when flag is called without an argument - # and it's set to the flag's argument if the flag has one if want_development: + # if we're using the default dev dir if want_development == DEFAULT_DIR_FLAG: - pass + config.init_dev_mode(config.default_dev_dir()) else: - config.DEV_MODE_DIR = Path(want_development) - - if not os.path.exists(config.DEV_MODE_DIR): - os.makedirs(config.DEV_MODE_DIR) - - config.SETTINGS_DIR = config.DEV_MODE_DIR / 'settings' - if not os.path.exists(config.SETTINGS_DIR): - os.makedirs(config.SETTINGS_DIR) - - config.LOG_DIR = config.DEV_MODE_DIR / 'logs' - if not os.path.exists(config.LOG_DIR): - os.makedirs(config.LOG_DIR) - - config.CACHE_DIR = config.DEV_MODE_DIR / 'cache' - if not os.path.exists(config.CACHE_DIR): - os.makedirs(config.CACHE_DIR) - - config.TEMP_DIR = config.CACHE_DIR / 'tmp' - if not os.path.exists(config.TEMP_DIR): - os.makedirs(config.TEMP_DIR) - - config.PROFILE_BOOTSTRAP_FILE = config.DEV_MODE_DIR / '.vorta-init.json' - - # except Exception as exception: - # print("That's an invalid path for a dir \n", exception) + # if we're not using the default dev dir and + # instead we're using whatever dir is passed as an argument + config.init_dev_mode(Path(want_development)) + else: + config.init_from_platformdirs() init_logger(background=want_background) diff --git a/src/vorta/application.py b/src/vorta/application.py index 3542131e9..636d59706 100644 --- a/src/vorta/application.py +++ b/src/vorta/application.py @@ -5,11 +5,11 @@ from typing import Any, Dict, List, Tuple from PyQt6 import QtCore from PyQt6.QtWidgets import QMessageBox +from vorta import config from vorta.borg.break_lock import BorgBreakJob from vorta.borg.create import BorgCreateJob from vorta.borg.jobs_manager import JobsManager from vorta.borg.version import BorgVersionJob -from vorta.config import LOG_DIR, PROFILE_BOOTSTRAP_FILE, TEMP_DIR from vorta.i18n import init_translations, translate from vorta.notifications import VortaNotifications from vorta.profile_export import ProfileExport @@ -23,7 +23,7 @@ logger = logging.getLogger(__name__) -APP_ID = TEMP_DIR / "socket" +APP_ID = config.TEMP_DIR / "socket" class VortaApp(QtSingleApplication): @@ -259,7 +259,7 @@ def break_lock(self, profile): job = BorgBreakJob(params['cmd'], params) self.jobs_manager.add_job(job) - def bootstrap_profile(self, bootstrap_file=PROFILE_BOOTSTRAP_FILE): + def bootstrap_profile(self, bootstrap_file=config.PROFILE_BOOTSTRAP_FILE): """ Make sure there is at least one profile when first starting Vorta. Will either import a profile placed in ~/.vorta-init.json @@ -332,7 +332,7 @@ def check_failed_response(self, result: Dict[str, Any]): msg.setIcon(QMessageBox.Icon.Warning) text = translate( 'VortaApp', 'Borg exited with warning status (rc 1). See the logs for details.' - ).format(LOG_DIR.as_uri()) + ).format(config.LOG_DIR.as_uri()) infotext = error_message elif returncode > 128: # 128+N - killed by signal N (e.g. 137 == kill -9) diff --git a/src/vorta/borg/check.py b/src/vorta/borg/check.py index cdb15a1cc..60dd39d0f 100644 --- a/src/vorta/borg/check.py +++ b/src/vorta/borg/check.py @@ -1,5 +1,5 @@ from typing import Any, Dict -from vorta.config import LOG_DIR +from vorta import config from vorta.i18n import translate from vorta.utils import borg_compat from .borg_job import BorgJob @@ -25,7 +25,7 @@ def finished_event(self, result: Dict[str, Any]): self.app.backup_progress_event.emit( f"[{self.params['profile_name']}] " + translate('RepoCheckJob', 'Repo check failed. See the logs for details.').format( - LOG_DIR.as_uri() + config.LOG_DIR.as_uri() ) ) self.app.check_failed_event.emit(result) diff --git a/src/vorta/borg/compact.py b/src/vorta/borg/compact.py index 889954d85..e1bb846d5 100644 --- a/src/vorta/borg/compact.py +++ b/src/vorta/borg/compact.py @@ -1,5 +1,5 @@ from typing import Any, Dict -from vorta.config import LOG_DIR +from vorta import config from vorta.i18n import trans_late, translate from vorta.utils import borg_compat from .borg_job import BorgJob @@ -28,7 +28,7 @@ def finished_event(self, result: Dict[str, Any]): f"[{self.params['profile_name']}] " + translate( 'BorgCompactJob', 'Errors during compaction. See the logs for details.' - ).format(LOG_DIR.as_uri()) + ).format(config.LOG_DIR.as_uri()) ) else: self.app.backup_progress_event.emit(f"[{self.params['profile_name']}] {self.tr('Compaction completed.')}") diff --git a/src/vorta/borg/create.py b/src/vorta/borg/create.py index bbb5b765b..0b9daba30 100644 --- a/src/vorta/borg/create.py +++ b/src/vorta/borg/create.py @@ -2,7 +2,7 @@ import subprocess import tempfile from datetime import datetime as dt -from vorta.config import LOG_DIR +from vorta import config from vorta.i18n import trans_late, translate from vorta.store.models import ArchiveModel, RepoModel, SourceFileModel, WifiSettingModel from vorta.utils import borg_compat, format_archive_name, get_network_status_monitor @@ -39,7 +39,7 @@ def process_result(self, result): + translate( 'BorgCreateJob', 'Backup finished with warnings. See the logs for details.', - ).format(LOG_DIR.as_uri()) + ).format(config.LOG_DIR.as_uri()) ) else: self.app.backup_progress_event.emit(f"[{self.params['profile_name']}] {self.tr('Backup finished.')}") diff --git a/src/vorta/config.py b/src/vorta/config.py index 191a67022..d218d7a20 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -4,15 +4,41 @@ APP_NAME = 'Vorta' APP_AUTHOR = 'BorgBase' APP_ID_DARWIN = 'com.borgbase.client.macos' -dirs = platformdirs.PlatformDirs(APP_NAME, APP_AUTHOR) -SETTINGS_DIR = dirs.user_data_path -LOG_DIR = dirs.user_log_path -CACHE_DIR = dirs.user_cache_path -TEMP_DIR = CACHE_DIR / "tmp" -PROFILE_BOOTSTRAP_FILE = Path.home() / '.vorta-init.json' -DEV_MODE_DIR = Path(__file__).parent.parent.parent / '.dev_config' - - -# ensure directories exist -for dir in (SETTINGS_DIR, LOG_DIR, CACHE_DIR, TEMP_DIR): - dir.mkdir(parents=True, exist_ok=True) +SETTINGS_DIR = None +LOG_DIR = None +CACHE_DIR = None +TEMP_DIR = None +PROFILE_BOOTSTRAP_FILE = None + + +def default_dev_dir(): + return Path(__file__).parent.parent.parent / '.dev_config' + + +def init_from_platformdirs(): + dirs = platformdirs.PlatformDirs(APP_NAME, APP_AUTHOR) + init(dirs.user_data_path, dirs.user_log_path, dirs.user_cache_path, dirs.user_cache_path / 'tmp', Path.home()) + + +def init_dev_mode(dir): + init(dir / 'settings', dir / 'logs', dir / 'cache', dir / 'tmp', dir) + + +def init(settings, logs, cache, tmp, bootstrap): + global SETTINGS_DIR + global LOG_DIR + global CACHE_DIR + global TEMP_DIR + global PROFILE_BOOTSTRAP_FILE + SETTINGS_DIR = settings + LOG_DIR = logs + CACHE_DIR = cache + TEMP_DIR = tmp + PROFILE_BOOTSTRAP_FILE = bootstrap / '.vorta-init.json' + ensure_dirs() + + +def ensure_dirs(): + # ensure directories exist + for dir in (SETTINGS_DIR, LOG_DIR, CACHE_DIR, TEMP_DIR): + dir.mkdir(parents=True, exist_ok=True) diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 19d15d556..588bc4d2a 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -22,7 +22,7 @@ # Used to store whether a user wanted to override the # default directory for the --development flag -DEFAULT_DIR_FLAG = "USE_DEFAULT_DIR" +DEFAULT_DIR_FLAG = object() borg_compat = BorgCompatibility() _network_status_monitor = None diff --git a/src/vorta/views/misc_tab.py b/src/vorta/views/misc_tab.py index ccc0c65fe..7e7829be1 100644 --- a/src/vorta/views/misc_tab.py +++ b/src/vorta/views/misc_tab.py @@ -2,8 +2,8 @@ from PyQt6 import uic from PyQt6.QtCore import Qt from PyQt6.QtWidgets import QApplication, QCheckBox, QFormLayout, QHBoxLayout, QLabel, QSizePolicy, QSpacerItem +from vorta import config from vorta._version import __version__ -from vorta.config import LOG_DIR from vorta.i18n import translate from vorta.store.models import BackupProfileMixin, SettingsModel from vorta.store.settings import get_misc_settings @@ -24,7 +24,8 @@ def __init__(self, parent=None): self.setupUi(parent) self.versionLabel.setText(__version__) self.logLink.setText( - f'Log' + f'Log' ) self.checkboxLayout = QFormLayout(self.frameSettings) From f4d57b0f3f96e29ac31c06126bc1ca52df4df946 Mon Sep 17 00:00:00 2001 From: ratchek Date: Wed, 19 Apr 2023 14:19:36 -0400 Subject: [PATCH 16/24] Fix issues as discussed in #1682. Changes based on the discussion here: https://github.com/borgbase/vorta/pull/1682 Biggest change is that src/config is rewritten to initialize the config variables while the program is running, so you need to import the whole module every time you use variables/constants from it. This was done to avoid duplicating code responsible for setting up the directory in which config data will be stored. --- src/vorta/application.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vorta/application.py b/src/vorta/application.py index 636d59706..cee9a93df 100644 --- a/src/vorta/application.py +++ b/src/vorta/application.py @@ -23,6 +23,7 @@ logger = logging.getLogger(__name__) +config.init_from_platformdirs() APP_ID = config.TEMP_DIR / "socket" From 2784172bd10f162f035c1eb4485c9dcfda1a6cdb Mon Sep 17 00:00:00 2001 From: ratchek Date: Wed, 19 Apr 2023 18:36:21 -0400 Subject: [PATCH 17/24] Update logger to import config properly --- src/vorta/__main__.py | 1 - src/vorta/application.py | 1 - src/vorta/log.py | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 1c7533301..0baf7bf43 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -69,7 +69,6 @@ def exception_handler(type, value, tb): config.init_dev_mode(Path(want_development)) else: config.init_from_platformdirs() - init_logger(background=want_background) # Init database diff --git a/src/vorta/application.py b/src/vorta/application.py index cee9a93df..636d59706 100644 --- a/src/vorta/application.py +++ b/src/vorta/application.py @@ -23,7 +23,6 @@ logger = logging.getLogger(__name__) -config.init_from_platformdirs() APP_ID = config.TEMP_DIR / "socket" diff --git a/src/vorta/log.py b/src/vorta/log.py index c4ee22df0..8a7af5bd4 100644 --- a/src/vorta/log.py +++ b/src/vorta/log.py @@ -8,7 +8,7 @@ import logging from logging.handlers import TimedRotatingFileHandler -from .config import LOG_DIR +from vorta import config logger = logging.getLogger() @@ -22,7 +22,7 @@ def init_logger(background=False): formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # create handlers - fh = TimedRotatingFileHandler(LOG_DIR / 'vorta.log', when='d', interval=1, backupCount=5) + fh = TimedRotatingFileHandler(config.LOG_DIR / 'vorta.log', when='d', interval=1, backupCount=5) fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) logger.addHandler(fh) From 330ca1c62a988dd2c30a2d82cb85223f5506b13b Mon Sep 17 00:00:00 2001 From: ratchek Date: Wed, 19 Apr 2023 18:41:16 -0400 Subject: [PATCH 18/24] Initialize as system wide when running through application.py --- src/vorta/application.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vorta/application.py b/src/vorta/application.py index 636d59706..b562b939b 100644 --- a/src/vorta/application.py +++ b/src/vorta/application.py @@ -23,6 +23,11 @@ logger = logging.getLogger(__name__) +# If config.TEMP_DIR is None, this means that the app got launched withoug going through main +# (for example when running tests or when running on schedule.) +# In any case, if the config dirs aren't set, assume you're runnning system wide initialize appropriately +if not config.TEMP_DIR: + config.init_from_platformdirs() APP_ID = config.TEMP_DIR / "socket" From 0198ce8ba2d8e8d064ab9af48b01138cc95390c2 Mon Sep 17 00:00:00 2001 From: ratchek Date: Thu, 11 May 2023 13:09:07 -0400 Subject: [PATCH 19/24] Fix typo and loading config --- src/vorta/application.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vorta/application.py b/src/vorta/application.py index bfaa6616f..c239d7810 100644 --- a/src/vorta/application.py +++ b/src/vorta/application.py @@ -25,9 +25,9 @@ logger = logging.getLogger(__name__) -# If config.TEMP_DIR is None, this means that the app got launched withoug going through main +# If config.TEMP_DIR is None, this means that the app got launched without going through main # (for example when running tests or when running on schedule.) -# In any case, if the config dirs aren't set, assume you're runnning system wide initialize appropriately +# In any case, if the config dirs aren't set, assume you're running system-wide and initialize appropriately if not config.TEMP_DIR: config.init_from_platformdirs() APP_ID = config.TEMP_DIR / "socket" @@ -266,7 +266,11 @@ def break_lock(self, profile): job = BorgBreakJob(params['cmd'], params) self.jobs_manager.add_job(job) - def bootstrap_profile(self, bootstrap_file=config.PROFILE_BOOTSTRAP_FILE): + def bootstrap_profile(self, bootstrap_file=None): + # Necessary to dynamically load the variable from config during runtime + # Check out pull request for #1682 for context + bootstrap_file = bootstrap_file or config.PROFILE_BOOTSTRAP_FILE + """ Make sure there is at least one profile when first starting Vorta. Will either import a profile placed in ~/.vorta-init.json From a3238a4f23492711ee084c6507239c31da8bb826 Mon Sep 17 00:00:00 2001 From: ratchek Date: Thu, 11 May 2023 15:50:01 -0400 Subject: [PATCH 20/24] Initialize config values in config module --- src/vorta/__main__.py | 3 +-- src/vorta/application.py | 5 ----- src/vorta/config.py | 4 ++++ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index ca1d25e20..48ff52217 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -69,8 +69,7 @@ def exception_handler(type, value, tb): # if we're not using the default dev dir and # instead we're using whatever dir is passed as an argument config.init_dev_mode(Path(want_development)) - else: - config.init_from_platformdirs() + init_logger(background=want_background) # Init database diff --git a/src/vorta/application.py b/src/vorta/application.py index c239d7810..fac38440b 100644 --- a/src/vorta/application.py +++ b/src/vorta/application.py @@ -25,11 +25,6 @@ logger = logging.getLogger(__name__) -# If config.TEMP_DIR is None, this means that the app got launched without going through main -# (for example when running tests or when running on schedule.) -# In any case, if the config dirs aren't set, assume you're running system-wide and initialize appropriately -if not config.TEMP_DIR: - config.init_from_platformdirs() APP_ID = config.TEMP_DIR / "socket" diff --git a/src/vorta/config.py b/src/vorta/config.py index 885552dc2..d083e74da 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -43,3 +43,7 @@ def ensure_dirs(): # ensure directories exist for dir in (SETTINGS_DIR, LOG_DIR, CACHE_DIR, TEMP_DIR): dir.mkdir(parents=True, exist_ok=True) + + +# Make sure that the config values are valid +init_from_platformdirs() From 5e651adca20e572268ec07e5d81403c9e488c4e7 Mon Sep 17 00:00:00 2001 From: ratchek Date: Thu, 11 May 2023 16:23:51 -0400 Subject: [PATCH 21/24] Resolve paths when passed to dev mode --- src/vorta/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 48ff52217..9c4362475 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -68,7 +68,7 @@ def exception_handler(type, value, tb): else: # if we're not using the default dev dir and # instead we're using whatever dir is passed as an argument - config.init_dev_mode(Path(want_development)) + config.init_dev_mode(Path(want_development).resolve()) init_logger(background=want_background) From 5f1d6c752b33911a2582c6a6ce73cdcc5a69ae9a Mon Sep 17 00:00:00 2001 From: ratchek Date: Fri, 12 May 2023 16:26:27 -0400 Subject: [PATCH 22/24] Shift path resolution to config --- src/vorta/__main__.py | 5 ++--- src/vorta/config.py | 9 ++++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 9c4362475..29d24beb0 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -1,7 +1,6 @@ import os import signal import sys -from pathlib import Path from peewee import SqliteDatabase @@ -63,12 +62,12 @@ def exception_handler(type, value, tb): if want_development: # if we're using the default dev dir - if want_development == DEFAULT_DIR_FLAG: + if want_development is DEFAULT_DIR_FLAG: config.init_dev_mode(config.default_dev_dir()) else: # if we're not using the default dev dir and # instead we're using whatever dir is passed as an argument - config.init_dev_mode(Path(want_development).resolve()) + config.init_dev_mode(want_development) init_logger(background=want_background) diff --git a/src/vorta/config.py b/src/vorta/config.py index d083e74da..dbbe5ffd5 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -22,7 +22,14 @@ def init_from_platformdirs(): def init_dev_mode(dir): - init(dir / 'settings', dir / 'logs', dir / 'cache', dir / 'tmp', dir) + dir_full_path = Path(dir).resolve() + init( + dir_full_path / 'settings', + dir_full_path / 'logs', + dir_full_path / 'cache', + dir_full_path / 'tmp', + dir_full_path, + ) def init(settings, logs, cache, tmp, bootstrap): From 6224e88c09e11a74dfefdfe0571371ffa4a1ccc1 Mon Sep 17 00:00:00 2001 From: ratchek Date: Tue, 23 May 2023 17:01:31 -0400 Subject: [PATCH 23/24] Add docstrings and typing --- src/vorta/config.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vorta/config.py b/src/vorta/config.py index dbbe5ffd5..2bf14add6 100644 --- a/src/vorta/config.py +++ b/src/vorta/config.py @@ -12,16 +12,19 @@ PROFILE_BOOTSTRAP_FILE = None -def default_dev_dir(): +def default_dev_dir() -> Path: + """Returns a default dir for config files in the project's main folder""" return Path(__file__).parent.parent.parent / '.dev_config' def init_from_platformdirs(): + """Initializes config dirs for system-wide use""" dirs = platformdirs.PlatformDirs(APP_NAME, APP_AUTHOR) init(dirs.user_data_path, dirs.user_log_path, dirs.user_cache_path, dirs.user_cache_path / 'tmp', Path.home()) -def init_dev_mode(dir): +def init_dev_mode(dir: Path): + """Initializes config dirs for local use inside provided dir""" dir_full_path = Path(dir).resolve() init( dir_full_path / 'settings', @@ -32,7 +35,8 @@ def init_dev_mode(dir): ) -def init(settings, logs, cache, tmp, bootstrap): +def init(settings: Path, logs: Path, cache: Path, tmp: Path, bootstrap: Path): + """Initializes config directories with provided paths""" global SETTINGS_DIR global LOG_DIR global CACHE_DIR @@ -47,6 +51,7 @@ def init(settings, logs, cache, tmp, bootstrap): def ensure_dirs(): + """Creates config dirs and parent dirs if they don't exist""" # ensure directories exist for dir in (SETTINGS_DIR, LOG_DIR, CACHE_DIR, TEMP_DIR): dir.mkdir(parents=True, exist_ok=True) From b6578e6753daef35adaf548086c82a703ff4b43a Mon Sep 17 00:00:00 2001 From: ratchek Date: Mon, 29 May 2023 10:45:09 -0400 Subject: [PATCH 24/24] Add metavar for better help message --- src/vorta/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 3ef12024c..89510e803 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -367,6 +367,7 @@ def parse_args(): '-D', nargs='?', const=DEFAULT_DIR_FLAG, + metavar="CONFIG_DIRECTORY", help='Start vorta in a local development environment. ' 'All log, config, cache, and temp files will be stored within the project tree. ' 'You can follow this flag with an optional path and it will store the files in the provided location.',