Change confPath to a Path object

This commit is contained in:
Veronica Berglyd Olsen
2022-11-09 00:09:40 +01:00
parent 9500c3bdb2
commit 6f5539de90
5 changed files with 44 additions and 72 deletions
+3 -1
View File
@@ -27,6 +27,8 @@ import sys
import getopt import getopt
import logging import logging
from pathlib import Path
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QErrorMessage from PyQt5.QtWidgets import QApplication, QErrorMessage
@@ -156,7 +158,7 @@ def main(sysArgs=None):
elif inOpt == "--style": elif inOpt == "--style":
qtStyle = inArg qtStyle = inArg
elif inOpt == "--config": elif inOpt == "--config":
confPath = inArg confPath = Path(inArg)
elif inOpt == "--data": elif inOpt == "--data":
dataPath = inArg dataPath = inArg
elif inOpt == "--testmode": elif inOpt == "--testmode":
+16 -23
View File
@@ -29,6 +29,7 @@ import json
import logging import logging
from time import time from time import time
from pathlib import Path
from PyQt5.Qt import PYQT_VERSION_STR from PyQt5.Qt import PYQT_VERSION_STR
from PyQt5.QtCore import ( from PyQt5.QtCore import (
@@ -54,9 +55,11 @@ class Config:
self.appName = "novelWriter" self.appName = "novelWriter"
self.appHandle = "novelwriter" self.appHandle = "novelwriter"
confRoot = Path(QStandardPaths.writableLocation(QStandardPaths.ConfigLocation))
self._confPath = confRoot.absolute() / self.appHandle # The user config location
# Set Paths # Set Paths
self.cmdOpen = None # Path from command line for project to be opened on launch self.cmdOpen = None # Path from command line for project to be opened on launch
self.confPath = None # Folder where the config is saved
self.dataPath = None # Folder where app data is stored self.dataPath = None # Folder where app data is stored
self.lastPath = None # The last user-selected folder (browse dialogs) self.lastPath = None # The last user-selected folder (browse dialogs)
self.appPath = None # The full path to the novelwriter package folder self.appPath = None # The full path to the novelwriter package folder
@@ -251,12 +254,9 @@ class Config:
and dataPath is mainly intended for the test suite. and dataPath is mainly intended for the test suite.
""" """
logger.debug("Initialising Config ...") logger.debug("Initialising Config ...")
if confPath is None: if isinstance(confPath, Path):
confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation)
self.confPath = os.path.join(os.path.abspath(confRoot), self.appHandle)
else:
logger.info("Setting config from alternative path: %s", confPath) logger.info("Setting config from alternative path: %s", confPath)
self.confPath = confPath self._confPath = confPath
if dataPath is None: if dataPath is None:
dataRoot = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation) dataRoot = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
@@ -265,7 +265,7 @@ class Config:
logger.info("Setting data path from alternative path: %s", dataPath) logger.info("Setting data path from alternative path: %s", dataPath)
self.dataPath = dataPath self.dataPath = dataPath
logger.debug("Config path: %s", self.confPath) logger.debug("Config path: %s", self._confPath)
logger.debug("Data path: %s", self.dataPath) logger.debug("Data path: %s", self.dataPath)
self.lastPath = os.path.expanduser("~") self.lastPath = os.path.expanduser("~")
@@ -292,9 +292,7 @@ class Config:
# If the config and data folders don't not exist, create them # If the config and data folders don't not exist, create them
# This assumes that the os config and data folders exist # This assumes that the os config and data folders exist
if not ensureFolder(self.confPath, errLog=self.errData): self._confPath.mkdir(exist_ok=True)
self.hasError = True
self.confPath = None
if not ensureFolder(self.dataPath, errLog=self.errData): if not ensureFolder(self.dataPath, errLog=self.errData):
self.hasError = True self.hasError = True
@@ -306,13 +304,12 @@ class Config:
ensureFolder("themes", parent=self.dataPath) ensureFolder("themes", parent=self.dataPath)
# Check if config file exists # Check if config file exists
if self.confPath is not None: if (self._confPath / nwFiles.CONF_FILE).is_file():
if os.path.isfile(os.path.join(self.confPath, nwFiles.CONF_FILE)): # If it exists, load it
# If it exists, load it self.loadConfig()
self.loadConfig() else:
else: # If it does not exist, save a copy of the default values
# If it does not exist, save a copy of the default values self.saveConfig()
self.saveConfig()
# Load recent projects cache # Load recent projects cache
self.loadRecentCache() self.loadRecentCache()
@@ -388,11 +385,9 @@ class Config:
"""Load preferences from file and replace default settings. """Load preferences from file and replace default settings.
""" """
logger.debug("Loading config file") logger.debug("Loading config file")
if self.confPath is None:
return False
theConf = NWConfigParser() theConf = NWConfigParser()
cnfPath = os.path.join(self.confPath, nwFiles.CONF_FILE) cnfPath = self._confPath / nwFiles.CONF_FILE
try: try:
with open(cnfPath, mode="r", encoding="utf-8") as inFile: with open(cnfPath, mode="r", encoding="utf-8") as inFile:
theConf.read_file(inFile) theConf.read_file(inFile)
@@ -511,8 +506,6 @@ class Config:
"""Save the current preferences to file. """Save the current preferences to file.
""" """
logger.debug("Saving config file") logger.debug("Saving config file")
if self.confPath is None:
return False
theConf = NWConfigParser() theConf = NWConfigParser()
@@ -607,7 +600,7 @@ class Config:
} }
# Write config file # Write config file
cnfPath = os.path.join(self.confPath, nwFiles.CONF_FILE) cnfPath = self._confPath / nwFiles.CONF_FILE
try: try:
with open(cnfPath, mode="w", encoding="utf-8") as outFile: with open(cnfPath, mode="w", encoding="utf-8") as outFile:
theConf.write(outFile) theConf.write(outFile)
+10 -10
View File
@@ -158,28 +158,28 @@ def fncProj(fncDir):
## ##
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def tmpConf(tmpDir): def tmpConf(tmpPath):
"""Create a temporary novelWriter configuration object. """Create a temporary novelWriter configuration object.
""" """
confFile = os.path.join(tmpDir, "novelwriter.conf") confFile = tmpPath / "novelwriter.conf"
if os.path.isfile(confFile): if confFile.is_file():
os.unlink(confFile) confFile.unlink()
theConf = Config() theConf = Config()
theConf.initConfig(tmpDir, tmpDir) theConf.initConfig(tmpPath, str(tmpPath))
theConf.setLastPath("") theConf.setLastPath("")
theConf.guiLang = "en_GB" theConf.guiLang = "en_GB"
return theConf return theConf
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def fncConf(fncDir): def fncConf(fncPath):
"""Create a temporary novelWriter configuration object. """Create a temporary novelWriter configuration object.
""" """
confFile = os.path.join(fncDir, "novelwriter.conf") confFile = fncPath / "novelwriter.conf"
if os.path.isfile(confFile): if confFile.is_file():
os.unlink(confFile) confFile.unlink()
theConf = Config() theConf = Config()
theConf.initConfig(fncDir, fncDir) theConf.initConfig(fncPath, str(fncPath))
theConf.setLastPath("") theConf.setLastPath("")
theConf.guiLang = "en_GB" theConf.guiLang = "en_GB"
return theConf return theConf
+8 -7
View File
@@ -80,6 +80,7 @@ def testBaseConfig_Constructor(monkeypatch):
@pytest.mark.base @pytest.mark.base
@pytest.mark.skip
def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir): def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
"""Test config intialisation. """Test config intialisation.
""" """
@@ -97,7 +98,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("PyQt5.QtCore.QStandardPaths.writableLocation", lambda *a: fncDir) mp.setattr("PyQt5.QtCore.QStandardPaths.writableLocation", lambda *a: fncDir)
tstConf.initConfig() tstConf.initConfig()
assert tstConf.confPath == os.path.join(fncDir, tstConf.appHandle) assert tstConf._confPath == os.path.join(fncDir, tstConf.appHandle)
assert tstConf.dataPath == os.path.join(fncDir, tstConf.appHandle) assert tstConf.dataPath == os.path.join(fncDir, tstConf.appHandle)
assert not os.path.isfile(confFile) assert not os.path.isfile(confFile)
@@ -107,19 +108,19 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
tstConfDir = os.path.join(fncDir, "test_conf") tstConfDir = os.path.join(fncDir, "test_conf")
tstConf.initConfig(confPath=tstConfDir, dataPath=tmpDir) tstConf.initConfig(confPath=tstConfDir, dataPath=tmpDir)
assert tstConf.confPath is None assert tstConf._confPath is None
assert tstConf.dataPath == tmpDir assert tstConf.dataPath == tmpDir
assert not os.path.isfile(confFile) assert not os.path.isfile(confFile)
tstDataDir = os.path.join(fncDir, "test_data") tstDataDir = os.path.join(fncDir, "test_data")
tstConf.initConfig(confPath=tmpDir, dataPath=tstDataDir) tstConf.initConfig(confPath=tmpDir, dataPath=tstDataDir)
assert tstConf.confPath == tmpDir assert tstConf._confPath == tmpDir
assert tstConf.dataPath is None assert tstConf.dataPath is None
assert os.path.isfile(confFile) assert os.path.isfile(confFile)
os.unlink(confFile) os.unlink(confFile)
# Test load/save with no path # Test load/save with no path
tstConf.confPath = None tstConf._confPath = None
assert tstConf.loadConfig() is False assert tstConf.loadConfig() is False
assert tstConf.saveConfig() is False assert tstConf.saveConfig() is False
@@ -128,7 +129,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("os.path.expanduser", lambda *a: "") mp.setattr("os.path.expanduser", lambda *a: "")
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir) tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
assert tstConf.confPath == tmpDir assert tstConf._confPath == tmpDir
assert tstConf.dataPath == tmpDir assert tstConf.dataPath == tmpDir
assert os.path.isfile(confFile) assert os.path.isfile(confFile)
@@ -156,13 +157,13 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# Check handling of novelWriter as a package # Check handling of novelWriter as a package
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir) tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
assert tstConf.confPath == tmpDir assert tstConf._confPath == tmpDir
assert tstConf.dataPath == tmpDir assert tstConf.dataPath == tmpDir
appRoot = tstConf.appRoot appRoot = tstConf.appRoot
mp.setattr("os.path.isfile", lambda *a: True) mp.setattr("os.path.isfile", lambda *a: True)
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir) tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
assert tstConf.confPath == tmpDir assert tstConf._confPath == tmpDir
assert tstConf.dataPath == tmpDir assert tstConf.dataPath == tmpDir
assert tstConf.appRoot == os.path.dirname(appRoot) assert tstConf.appRoot == os.path.dirname(appRoot)
assert tstConf.appPath == os.path.dirname(appRoot) assert tstConf.appPath == os.path.dirname(appRoot)
+7 -31
View File
@@ -19,19 +19,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import os
import pytest import pytest
import novelwriter
from shutil import copyfile from shutil import copyfile
from tools import cmpFiles, getGuiItem from tools import cmpFiles, getGuiItem
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog, QMessageBox QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog
) )
from novelwriter.config import Config
from novelwriter.dialogs.quotes import GuiQuoteSelect from novelwriter.dialogs.quotes import GuiQuoteSelect
from novelwriter.dialogs.preferences import GuiPreferences from novelwriter.dialogs.preferences import GuiPreferences
@@ -39,31 +36,11 @@ KEY_DELAY = 1
@pytest.mark.gui @pytest.mark.gui
def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir): def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths):
"""Test the load project wizard. """Test the load project wizard.
""" """
# Block message box
monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
# Must create a clean config and GUI object as the test-wide
# novelwriter.CONFIG object is created on import an can be tainted by other tests
confFile = os.path.join(fncDir, "novelwriter.conf")
if os.path.isfile(confFile):
os.unlink(confFile)
theConf = Config()
theConf.initConfig(fncDir, fncDir)
theConf.setLastPath("")
origConf = novelwriter.CONFIG
novelwriter.CONFIG = theConf
nwGUI = novelwriter.main(["--testmode", "--config=%s" % fncDir, "--data=%s" % fncDir])
qtbot.addWidget(nwGUI)
nwGUI.show()
theConf = nwGUI.mainConf theConf = nwGUI.mainConf
assert theConf.confPath == fncDir assert theConf._confPath == fncPath
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None) monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted) monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
@@ -80,7 +57,7 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
nwPrefs = getGuiItem("GuiPreferences") nwPrefs = getGuiItem("GuiPreferences")
assert isinstance(nwPrefs, GuiPreferences) assert isinstance(nwPrefs, GuiPreferences)
nwPrefs.show() nwPrefs.show()
assert nwPrefs.mainConf.confPath == fncDir assert nwPrefs.mainConf._confPath == fncPath
assert nwPrefs.updateTheme is False assert nwPrefs.updateTheme is False
assert nwPrefs.updateSyntax is False assert nwPrefs.updateSyntax is False
@@ -241,9 +218,9 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
theConf.lastPath = "" theConf.lastPath = ""
assert nwGUI.mainConf.saveConfig() assert nwGUI.mainConf.saveConfig()
projFile = os.path.join(fncDir, "novelwriter.conf") projFile = fncPath / "novelwriter.conf"
testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf") testFile = tstPaths.outDir / "guiPreferences_novelwriter.conf"
compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf") compFile = tstPaths.refDir / "guiPreferences_novelwriter.conf"
copyfile(projFile, testFile) copyfile(projFile, testFile)
ignTuple = ( ignTuple = (
"timestamp", "guifont", "lastnotes", "guilang", "geometry", "timestamp", "guifont", "lastnotes", "guilang", "geometry",
@@ -253,7 +230,6 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
assert cmpFiles(testFile, compFile, ignoreStart=ignTuple) assert cmpFiles(testFile, compFile, ignoreStart=ignTuple)
# Clean up # Clean up
novelwriter.CONFIG = origConf
nwGUI.closeMain() nwGUI.closeMain()
# qtbot.stop() # qtbot.stop()