Completed coverage of setProjectPath and made all os imports explicit

This commit is contained in:
Veronica K. B. Olsen
2020-09-29 23:27:51 +02:00
parent 0b7cd71b92
commit e251ddacd2
23 changed files with 565 additions and 486 deletions
+5 -6
View File
@@ -28,8 +28,7 @@
import sys import sys
import getopt import getopt
import logging import logging
import os
from os import path, remove, rename
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QErrorMessage from PyQt5.QtWidgets import QApplication, QErrorMessage
@@ -203,10 +202,10 @@ def main(sysArgs=None):
logFmt = logging.Formatter(fmt=logFormat, style="{") logFmt = logging.Formatter(fmt=logFormat, style="{")
if not logFile == "" and toFile: if not logFile == "" and toFile:
if path.isfile(logFile+".bak"): if os.path.isfile(logFile+".bak"):
remove(logFile+".bak") os.remove(logFile+".bak")
if path.isfile(logFile): if os.path.isfile(logFile):
rename(logFile, logFile+".bak") os.rename(logFile, logFile+".bak")
fHandle = logging.FileHandler(logFile) fHandle = logging.FileHandler(logFile)
fHandle.setLevel(debugLevel) fHandle.setLevel(debugLevel)
+35 -35
View File
@@ -29,8 +29,8 @@ import logging
import configparser import configparser
import json import json
import sys import sys
import os
from os import path, mkdir, unlink, rename
from time import time from time import time
from shutil import which from shutil import which
@@ -238,7 +238,7 @@ class Config:
logger.debug("Initialising Config ...") logger.debug("Initialising Config ...")
if confPath is None: if confPath is None:
confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation) confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation)
self.confPath = path.join(path.abspath(confRoot), self.appHandle) self.confPath = os.path.join(os.path.abspath(confRoot), self.appHandle)
else: 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
@@ -248,7 +248,7 @@ class Config:
dataRoot = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation) dataRoot = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
else: else:
dataRoot = QStandardPaths.writableLocation(QStandardPaths.DataLocation) dataRoot = QStandardPaths.writableLocation(QStandardPaths.DataLocation)
self.dataPath = path.join(path.abspath(dataRoot), self.appHandle) self.dataPath = os.path.join(os.path.abspath(dataRoot), self.appHandle)
else: else:
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
@@ -257,24 +257,24 @@ class Config:
logger.verbose("Data path: %s" % self.dataPath) logger.verbose("Data path: %s" % self.dataPath)
self.confFile = self.appHandle+".conf" self.confFile = self.appHandle+".conf"
self.homePath = path.expanduser("~") self.homePath = os.path.expanduser("~")
self.lastPath = self.homePath self.lastPath = self.homePath
self.appPath = getattr(sys, "_MEIPASS", path.abspath(path.dirname(__file__))) self.appPath = getattr(sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__)))
self.appRoot = path.join(self.appPath, path.pardir) self.appRoot = os.path.join(self.appPath, os.path.pardir)
self.assetPath = path.join(self.appPath, "assets") self.assetPath = os.path.join(self.appPath, "assets")
self.themeRoot = path.join(self.assetPath, "themes") self.themeRoot = os.path.join(self.assetPath, "themes")
self.dictPath = path.join(self.assetPath, "dict") self.dictPath = os.path.join(self.assetPath, "dict")
self.iconPath = path.join(self.assetPath, "icons") self.iconPath = os.path.join(self.assetPath, "icons")
self.appIcon = path.join(self.iconPath, "novelwriter.svg") self.appIcon = os.path.join(self.iconPath, "novelwriter.svg")
logger.verbose("App path: %s" % self.appPath) logger.verbose("App path: %s" % self.appPath)
logger.verbose("Home path: %s" % self.homePath) logger.verbose("Home path: %s" % self.homePath)
# If config folder does not exist, make it. # If config folder does not exist, make it.
# This assumes that the os config folder itself exists. # This assumes that the os config folder itself exists.
if not path.isdir(self.confPath): if not os.path.isdir(self.confPath):
try: try:
mkdir(self.confPath) os.mkdir(self.confPath)
except Exception as e: except Exception as e:
logger.error("Could not create folder: %s" % self.confPath) logger.error("Could not create folder: %s" % self.confPath)
logger.error(str(e)) logger.error(str(e))
@@ -285,7 +285,7 @@ class Config:
# Check if config file exists # Check if config file exists
if self.confPath is not None: if self.confPath is not None:
if path.isfile(path.join(self.confPath, self.confFile)): if os.path.isfile(os.path.join(self.confPath, self.confFile)):
# If it exists, load it # If it exists, load it
self.loadConfig() self.loadConfig()
else: else:
@@ -295,9 +295,9 @@ class Config:
# If data folder does not exist, make it. # If data folder does not exist, make it.
# This assumes that the os data folder itself exists. # This assumes that the os data folder itself exists.
if self.dataPath is not None: if self.dataPath is not None:
if not path.isdir(self.dataPath): if not os.path.isdir(self.dataPath):
try: try:
mkdir(self.dataPath) os.mkdir(self.dataPath)
except Exception as e: except Exception as e:
logger.error("Could not create folder: %s" % self.dataPath) logger.error("Could not create folder: %s" % self.dataPath)
logger.error(str(e)) logger.error(str(e))
@@ -318,9 +318,9 @@ class Config:
self.spellLanguage = "en" self.spellLanguage = "en"
# Check if local help files exist # Check if local help files exist
self.helpPath = path.join(self.assetPath, "help", "novelWriter.qhc") self.helpPath = os.path.join(self.assetPath, "help", "novelWriter.qhc")
self.hasHelp = path.isfile(self.helpPath) self.hasHelp = os.path.isfile(self.helpPath)
self.hasHelp &= path.isfile(path.join(self.assetPath, "help", "novelWriter.qch")) self.hasHelp &= os.path.isfile(os.path.join(self.assetPath, "help", "novelWriter.qch"))
logger.debug("Config initialisation complete") logger.debug("Config initialisation complete")
@@ -334,7 +334,7 @@ class Config:
return False return False
cnfParse = configparser.ConfigParser() cnfParse = configparser.ConfigParser()
cnfPath = path.join(self.confPath, self.confFile) cnfPath = os.path.join(self.confPath, self.confFile)
try: try:
with open(cnfPath, mode="r", encoding="utf8") as inFile: with open(cnfPath, mode="r", encoding="utf8") as inFile:
cnfParse.read_file(inFile) cnfParse.read_file(inFile)
@@ -629,7 +629,7 @@ class Config:
cnfParse.set(cnfSec, "lastpath", str(self.lastPath)) cnfParse.set(cnfSec, "lastpath", str(self.lastPath))
# Write config file # Write config file
cnfPath = path.join(self.confPath, self.confFile) cnfPath = os.path.join(self.confPath, self.confFile)
try: try:
with open(cnfPath, mode="w", encoding="utf8") as outFile: with open(cnfPath, mode="w", encoding="utf8") as outFile:
cnfParse.write(outFile) cnfParse.write(outFile)
@@ -650,10 +650,10 @@ class Config:
if self.dataPath is None: if self.dataPath is None:
return False return False
cacheFile = path.join(self.dataPath, nwFiles.RECENT_FILE) cacheFile = os.path.join(self.dataPath, nwFiles.RECENT_FILE)
self.recentProj = {} self.recentProj = {}
if path.isfile(cacheFile): if os.path.isfile(cacheFile):
try: try:
with open(cacheFile, mode="r", encoding="utf8") as inFile: with open(cacheFile, mode="r", encoding="utf8") as inFile:
theJson = inFile.read() theJson = inFile.read()
@@ -690,8 +690,8 @@ class Config:
if self.dataPath is None: if self.dataPath is None:
return False return False
cacheFile = path.join(self.dataPath, nwFiles.RECENT_FILE) cacheFile = os.path.join(self.dataPath, nwFiles.RECENT_FILE)
cacheTemp = path.join(self.dataPath, nwFiles.RECENT_FILE+"~") cacheTemp = os.path.join(self.dataPath, nwFiles.RECENT_FILE+"~")
try: try:
with open(cacheTemp, mode="w+", encoding="utf8") as outFile: with open(cacheTemp, mode="w+", encoding="utf8") as outFile:
@@ -702,16 +702,16 @@ class Config:
self.errData.append(str(e)) self.errData.append(str(e))
return False return False
if path.isfile(cacheFile): if os.path.isfile(cacheFile):
unlink(cacheFile) os.unlink(cacheFile)
rename(cacheTemp, cacheFile) os.rename(cacheTemp, cacheFile)
return True return True
def updateRecentCache(self, projPath, projTitle, wordCount, saveTime): def updateRecentCache(self, projPath, projTitle, wordCount, saveTime):
"""Add or update recent cache information o9n a given project. """Add or update recent cache information o9n a given project.
""" """
self.recentProj[path.abspath(projPath)] = { self.recentProj[os.path.abspath(projPath)] = {
"title" : projTitle, "title" : projTitle,
"time" : int(saveTime), "time" : int(saveTime),
"words" : int(wordCount), "words" : int(wordCount),
@@ -737,27 +737,27 @@ class Config:
def setConfPath(self, newPath): def setConfPath(self, newPath):
if newPath is None: if newPath is None:
return True return True
if not path.isfile(newPath): if not os.path.isfile(newPath):
logger.error("File not found, using default config path instead") logger.error("File not found, using default config path instead")
return False return False
self.confPath = path.dirname(newPath) self.confPath = os.path.dirname(newPath)
self.confFile = path.basename(newPath) self.confFile = os.path.basename(newPath)
return True return True
def setDataPath(self, newPath): def setDataPath(self, newPath):
if newPath is None: if newPath is None:
return True return True
if not path.isdir(newPath): if not os.path.isdir(newPath):
logger.error("Path not found, using default data path instead") logger.error("Path not found, using default data path instead")
return False return False
self.dataPath = path.abspath(newPath) self.dataPath = os.path.abspath(newPath)
return True return True
def setLastPath(self, lastPath): def setLastPath(self, lastPath):
if lastPath is None or lastPath == "": if lastPath is None or lastPath == "":
self.lastPath = "" self.lastPath = ""
else: else:
self.lastPath = path.dirname(lastPath) self.lastPath = os.path.dirname(lastPath)
return True return True
def setWinSize(self, newWidth, newHeight): def setWinSize(self, newWidth, newHeight):
+12 -13
View File
@@ -26,8 +26,7 @@
""" """
import logging import logging
import os
from os import path, rename, unlink
from nw.constants import nwAlert from nw.constants import nwAlert
from nw.common import isHandle from nw.common import isHandle
@@ -89,12 +88,12 @@ class NWDoc():
docFile = self._docHandle+".nwd" docFile = self._docHandle+".nwd"
logger.debug("Opening document %s" % docFile) logger.debug("Opening document %s" % docFile)
docPath = path.join(self.theProject.projContent, docFile) docPath = os.path.join(self.theProject.projContent, docFile)
self._fileLoc = docPath self._fileLoc = docPath
theText = "" theText = ""
self._docMeta = "" self._docMeta = ""
if path.isfile(docPath): if os.path.isfile(docPath):
try: try:
with open(docPath, mode="r", encoding="utf8") as inFile: with open(docPath, mode="r", encoding="utf8") as inFile:
fstLine = inFile.readline() fstLine = inFile.readline()
@@ -137,8 +136,8 @@ class NWDoc():
docFile = self._docHandle+".nwd" docFile = self._docHandle+".nwd"
logger.debug("Saving document %s" % docFile) logger.debug("Saving document %s" % docFile)
docPath = path.join(self.theProject.projContent, docFile) docPath = os.path.join(self.theProject.projContent, docFile)
docTemp = path.join(self.theProject.projContent, docFile+"~") docTemp = os.path.join(self.theProject.projContent, docFile+"~")
if self._theItem is None: if self._theItem is None:
docMeta = "" docMeta = ""
@@ -163,9 +162,9 @@ class NWDoc():
# If we're here, the file was successfully saved, so we can # If we're here, the file was successfully saved, so we can
# replace the temp file with the actual file # replace the temp file with the actual file
if path.isfile(docPath): if os.path.isfile(docPath):
unlink(docPath) os.unlink(docPath)
rename(docTemp, docPath) os.rename(docTemp, docPath)
self.theParent.statusBar.setStatus("Saved Document: %s" % self._theItem.itemName) self.theParent.statusBar.setStatus("Saved Document: %s" % self._theItem.itemName)
@@ -181,13 +180,13 @@ class NWDoc():
docFile = tHandle+".nwd" docFile = tHandle+".nwd"
chkList = [] chkList = []
chkList.append(path.join(self.theProject.projContent, docFile)) chkList.append(os.path.join(self.theProject.projContent, docFile))
chkList.append(path.join(self.theProject.projContent, docFile+"~")) chkList.append(os.path.join(self.theProject.projContent, docFile+"~"))
for chkFile in chkList: for chkFile in chkList:
if path.isfile(chkFile): if os.path.isfile(chkFile):
try: try:
unlink(chkFile) os.unlink(chkFile)
logger.debug("Deleted: %s" % chkFile) logger.debug("Deleted: %s" % chkFile)
except Exception as e: except Exception as e:
self.makeAlert(["Could not delete document file.", str(e)], nwAlert.ERROR) self.makeAlert(["Could not delete document file.", str(e)], nwAlert.ERROR)
+4 -4
View File
@@ -28,8 +28,8 @@
import nw import nw
import logging import logging
import json import json
import os
from os import path
from time import time from time import time
from nw.constants import ( from nw.constants import (
@@ -153,9 +153,9 @@ class NWIndex():
"""Load index from last session from the project meta folder. """Load index from last session from the project meta folder.
""" """
theData = {} theData = {}
indexFile = path.join(self.theProject.projMeta, nwFiles.INDEX_FILE) indexFile = os.path.join(self.theProject.projMeta, nwFiles.INDEX_FILE)
if path.isfile(indexFile): if os.path.isfile(indexFile):
logger.debug("Loading index file") logger.debug("Loading index file")
try: try:
with open(indexFile, mode="r", encoding="utf8") as inFile: with open(indexFile, mode="r", encoding="utf8") as inFile:
@@ -190,7 +190,7 @@ class NWIndex():
"""Save the current index as a json file in the project meta """Save the current index as a json file in the project meta
data folder. data folder.
""" """
indexFile = path.join(self.theProject.projMeta, nwFiles.INDEX_FILE) indexFile = os.path.join(self.theProject.projMeta, nwFiles.INDEX_FILE)
logger.debug("Saving index file") logger.debug("Saving index file")
if self.mainConf.debugInfo: if self.mainConf.debugInfo:
+4 -5
View File
@@ -28,8 +28,7 @@
import logging import logging
import json import json
import os
from os import path
from nw.constants import nwFiles from nw.constants import nwFiles
@@ -100,10 +99,10 @@ class OptionState():
if self.theProject.projMeta is None: if self.theProject.projMeta is None:
return False return False
stateFile = path.join(self.theProject.projMeta, nwFiles.OPTS_FILE) stateFile = os.path.join(self.theProject.projMeta, nwFiles.OPTS_FILE)
theState = {} theState = {}
if path.isfile(stateFile): if os.path.isfile(stateFile):
logger.debug("Loading GUI options file") logger.debug("Loading GUI options file")
try: try:
with open(stateFile, mode="r", encoding="utf8") as inFile: with open(stateFile, mode="r", encoding="utf8") as inFile:
@@ -130,7 +129,7 @@ class OptionState():
if self.theProject.projMeta is None: if self.theProject.projMeta is None:
return False return False
stateFile = path.join(self.theProject.projMeta, nwFiles.OPTS_FILE) stateFile = os.path.join(self.theProject.projMeta, nwFiles.OPTS_FILE)
logger.debug("Saving GUI options file") logger.debug("Saving GUI options file")
try: try:
+90 -93
View File
@@ -27,8 +27,8 @@
import nw import nw
import logging import logging
import os
from os import path, mkdir, listdir, unlink, rename, rmdir
from lxml import etree from lxml import etree
from time import time from time import time
from shutil import make_archive, unpack_archive, copyfile from shutil import make_archive, unpack_archive, copyfile
@@ -351,14 +351,11 @@ class NWProject():
aDoc.saveDocument("### %s\n\n" % scTitle) aDoc.saveDocument("### %s\n\n" % scTitle)
aDoc.clearDocument() aDoc.clearDocument()
else:
# Fallback just in case. We shouldn't reach here.
self.newRoot("Novel", nwItemClass.NOVEL)
# Finalise # Finalise
self.projOpened = time() if popCustom or popMinimal:
self.setProjectChanged(True) self.projOpened = time()
self.saveProject(autoSave=True) self.setProjectChanged(True)
self.saveProject(autoSave=True)
return True return True
@@ -368,14 +365,14 @@ class NWProject():
parse the XML of the file and populate the project variables and parse the XML of the file and populate the project variables and
build the tree of project items. build the tree of project items.
""" """
if not path.isfile(fileName): if not os.path.isfile(fileName):
fileName = path.join(fileName, nwFiles.PROJ_FILE) fileName = os.path.join(fileName, nwFiles.PROJ_FILE)
if not path.isfile(fileName): if not os.path.isfile(fileName):
self.makeAlert("File not found: %s" % fileName, nwAlert.ERROR) self.makeAlert("File not found: %s" % fileName, nwAlert.ERROR)
return False return False
self.clearProject() self.clearProject()
self.projPath = path.abspath(path.dirname(fileName)) self.projPath = os.path.abspath(os.path.dirname(fileName))
logger.debug("Opening project: %s" % self.projPath) logger.debug("Opening project: %s" % self.projPath)
# Standard Folders and Files # Standard Folders and Files
@@ -385,13 +382,13 @@ class NWProject():
self.clearProject() self.clearProject()
return False return False
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT) self.projDict = os.path.join(self.projMeta, nwFiles.PROJ_DICT)
# Check for Old Legacy Data # Check for Old Legacy Data
# ========================= # =========================
legacyList = [] # Cleanup is done later legacyList = [] # Cleanup is done later
for projItem in listdir(self.projPath): for projItem in os.listdir(self.projPath):
logger.verbose("Project contains: %s" % projItem) logger.verbose("Project contains: %s" % projItem)
if projItem.startswith("data_"): if projItem.startswith("data_"):
legacyList.append(projItem) legacyList.append(projItem)
@@ -424,7 +421,7 @@ class NWProject():
# Trying to open backup file instead # Trying to open backup file instead
backFile = fileName[:-3]+"bak" backFile = fileName[:-3]+"bak"
if path.isfile(backFile): if os.path.isfile(backFile):
self.makeAlert("Attempting to open backup project file instead.", nwAlert.INFO) self.makeAlert("Attempting to open backup project file instead.", nwAlert.INFO)
try: try:
nwXML = etree.parse(backFile) nwXML = etree.parse(backFile)
@@ -706,9 +703,9 @@ class NWProject():
self.projTree.packXML(nwXML) self.projTree.packXML(nwXML)
# Write the xml tree to file # Write the xml tree to file
tempFile = path.join(self.projPath, self.projFile+"~") tempFile = os.path.join(self.projPath, self.projFile+"~")
saveFile = path.join(self.projPath, self.projFile) saveFile = os.path.join(self.projPath, self.projFile)
backFile = path.join(self.projPath, self.projFile[:-3]+"bak") backFile = os.path.join(self.projPath, self.projFile[:-3]+"bak")
try: try:
with open(tempFile, mode="wb") as outFile: with open(tempFile, mode="wb") as outFile:
outFile.write(etree.tostring( outFile.write(etree.tostring(
@@ -723,11 +720,11 @@ class NWProject():
# If we're here, the file was successfully saved, # If we're here, the file was successfully saved,
# so let's sort out the temps and backups # so let's sort out the temps and backups
if path.isfile(backFile): if os.path.isfile(backFile):
unlink(backFile) os.unlink(backFile)
if path.isfile(saveFile): if os.path.isfile(saveFile):
rename(saveFile, backFile) os.rename(saveFile, backFile)
rename(tempFile, saveFile) os.rename(tempFile, saveFile)
# Save project GUI options # Save project GUI options
self.optState.saveSettings() self.optState.saveSettings()
@@ -760,9 +757,9 @@ class NWProject():
if self.projPath is None or self.projPath == "": if self.projPath is None or self.projPath == "":
return False return False
self.projMeta = path.join(self.projPath, "meta") self.projMeta = os.path.join(self.projPath, "meta")
self.projCache = path.join(self.projPath, "cache") self.projCache = os.path.join(self.projPath, "cache")
self.projContent = path.join(self.projPath, "content") self.projContent = os.path.join(self.projPath, "content")
if not self._checkFolder(self.projMeta): if not self._checkFolder(self.projMeta):
return False return False
@@ -797,7 +794,7 @@ class NWProject():
), nwAlert.ERROR) ), nwAlert.ERROR)
return False return False
if not path.isdir(self.mainConf.backupPath): if not os.path.isdir(self.mainConf.backupPath):
self.theParent.makeAlert(( self.theParent.makeAlert((
"Cannot backup project because the backup path does not exist. " "Cannot backup project because the backup path does not exist. "
"Please set a valid backup location in Tools > Preferences." "Please set a valid backup location in Tools > Preferences."
@@ -805,10 +802,10 @@ class NWProject():
return False return False
cleanName = makeFileNameSafe(self.projName) cleanName = makeFileNameSafe(self.projName)
baseDir = path.abspath(path.join(self.mainConf.backupPath, cleanName)) baseDir = os.path.abspath(os.path.join(self.mainConf.backupPath, cleanName))
if not path.isdir(baseDir): if not os.path.isdir(baseDir):
try: try:
mkdir(baseDir) os.mkdir(baseDir)
logger.debug("Created folder %s" % baseDir) logger.debug("Created folder %s" % baseDir)
except Exception as e: except Exception as e:
self.theParent.makeAlert( self.theParent.makeAlert(
@@ -817,7 +814,7 @@ class NWProject():
) )
return False return False
if path.commonpath([self.projPath, baseDir]) == self.projPath: if os.path.commonpath([self.projPath, baseDir]) == self.projPath:
self.theParent.makeAlert(( self.theParent.makeAlert((
"Cannot backup project because the backup path is within the " "Cannot backup project because the backup path is within the "
"project folder to be backed up. Please choose a different " "project folder to be backed up. Please choose a different "
@@ -826,7 +823,7 @@ class NWProject():
return False return False
archName = "Backup from %s" % formatTimeStamp(time(), fileSafe=True) archName = "Backup from %s" % formatTimeStamp(time(), fileSafe=True)
baseName = path.join(baseDir, archName) baseName = os.path.join(baseDir, archName)
try: try:
self._clearLockFile() self._clearLockFile()
@@ -834,7 +831,7 @@ class NWProject():
self._writeLockFile() self._writeLockFile()
if doNotify: if doNotify:
self.theParent.makeAlert( self.theParent.makeAlert(
"Backup archive file written to: %s.zip" % path.join(cleanName, archName), "Backup archive file written to: %s.zip" % os.path.join(cleanName, archName),
nwAlert.INFO nwAlert.INFO
) )
else: else:
@@ -861,11 +858,11 @@ class NWProject():
logger.error("No project path set for the example project") logger.error("No project path set for the example project")
return False return False
srcSample = path.abspath(path.join(self.mainConf.appRoot, "sample")) srcSample = os.path.abspath(os.path.join(self.mainConf.appRoot, "sample"))
pkgSample = path.join(self.mainConf.assetPath, "sample.zip") pkgSample = os.path.join(self.mainConf.assetPath, "sample.zip")
isSuccess = False isSuccess = False
if path.isfile(pkgSample): if os.path.isfile(pkgSample):
self.setProjectPath(projPath, newProject=True) self.setProjectPath(projPath, newProject=True)
try: try:
@@ -876,19 +873,19 @@ class NWProject():
["Failed to create a new example project.", str(e)], nwAlert.ERROR ["Failed to create a new example project.", str(e)], nwAlert.ERROR
) )
elif path.isdir(srcSample): elif os.path.isdir(srcSample):
self.setProjectPath(projPath, newProject=True) self.setProjectPath(projPath, newProject=True)
try: try:
srcProj = path.join(srcSample, nwFiles.PROJ_FILE) srcProj = os.path.join(srcSample, nwFiles.PROJ_FILE)
dstProj = path.join(projPath, nwFiles.PROJ_FILE) dstProj = os.path.join(projPath, nwFiles.PROJ_FILE)
copyfile(srcProj, dstProj) copyfile(srcProj, dstProj)
srcContent = path.join(srcSample, "content") srcContent = os.path.join(srcSample, "content")
dstContent = path.join(projPath, "content") dstContent = os.path.join(projPath, "content")
for srcFile in listdir(srcContent): for srcFile in os.listdir(srcContent):
srcDoc = path.join(srcContent, srcFile) srcDoc = os.path.join(srcContent, srcFile)
dstDoc = path.join(dstContent, srcFile) dstDoc = os.path.join(dstContent, srcFile)
copyfile(srcDoc, dstDoc) copyfile(srcDoc, dstDoc)
isSuccess = True isSuccess = True
@@ -923,13 +920,13 @@ class NWProject():
self.projPath = None self.projPath = None
else: else:
if projPath.startswith("~"): if projPath.startswith("~"):
projPath = path.expanduser(projPath) projPath = os.path.expanduser(projPath)
self.projPath = path.abspath(projPath) self.projPath = os.path.abspath(projPath)
if newProject: if newProject:
if not path.isdir(projPath): if not os.path.isdir(projPath):
try: try:
mkdir(projPath) os.mkdir(projPath)
logger.debug("Created folder %s" % projPath) logger.debug("Created folder %s" % projPath)
except Exception as e: except Exception as e:
self.theParent.makeAlert(( self.theParent.makeAlert((
@@ -937,8 +934,8 @@ class NWProject():
), nwAlert.ERROR) ), nwAlert.ERROR)
return False return False
if path.isdir(projPath): if os.path.isdir(projPath):
if listdir(self.projPath): if os.listdir(self.projPath):
self.theParent.makeAlert(( self.theParent.makeAlert((
"New project folder is not empty. " "New project folder is not empty. "
"Each project requires a dedicated project folder." "Each project requires a dedicated project folder."
@@ -988,7 +985,7 @@ class NWProject():
""" """
self.doBackup = doBackup self.doBackup = doBackup
if doBackup: if doBackup:
if not path.isdir(self.mainConf.backupPath): if not os.path.isdir(self.mainConf.backupPath):
self.theParent.makeAlert(( self.theParent.makeAlert((
"You must set a valid backup path in preferences to use " "You must set a valid backup path in preferences to use "
"the automatic project backup feature." "the automatic project backup feature."
@@ -1187,8 +1184,8 @@ class NWProject():
if self.projPath is None: if self.projPath is None:
return ["ERROR"] return ["ERROR"]
lockFile = path.join(self.projPath, nwFiles.PROJ_LOCK) lockFile = os.path.join(self.projPath, nwFiles.PROJ_LOCK)
if not path.isfile(lockFile): if not os.path.isfile(lockFile):
return [] return []
try: try:
@@ -1213,7 +1210,7 @@ class NWProject():
if self.projPath is None: if self.projPath is None:
return False return False
lockFile = path.join(self.projPath, nwFiles.PROJ_LOCK) lockFile = os.path.join(self.projPath, nwFiles.PROJ_LOCK)
try: try:
with open(lockFile, mode="w+", encoding="utf8") as outFile: with open(lockFile, mode="w+", encoding="utf8") as outFile:
outFile.write("%s\n" % self.mainConf.hostName) outFile.write("%s\n" % self.mainConf.hostName)
@@ -1234,10 +1231,10 @@ class NWProject():
if self.projPath is None: if self.projPath is None:
return False return False
lockFile = path.join(self.projPath, nwFiles.PROJ_LOCK) lockFile = os.path.join(self.projPath, nwFiles.PROJ_LOCK)
if path.isfile(lockFile): if os.path.isfile(lockFile):
try: try:
unlink(lockFile) os.unlink(lockFile)
return True return True
except Exception as e: except Exception as e:
logger.error("Failed to remove project lockfile") logger.error("Failed to remove project lockfile")
@@ -1249,9 +1246,9 @@ class NWProject():
def _checkFolder(self, thePath): def _checkFolder(self, thePath):
"""Check if a folder exists, and if it doesn't, create it. """Check if a folder exists, and if it doesn't, create it.
""" """
if not path.isdir(thePath): if not os.path.isdir(thePath):
try: try:
mkdir(thePath) os.mkdir(thePath)
logger.debug("Created folder %s" % thePath) logger.debug("Created folder %s" % thePath)
except Exception as e: except Exception as e:
self.makeAlert(["Could not create folder.", str(e)], nwAlert.ERROR) self.makeAlert(["Could not create folder.", str(e)], nwAlert.ERROR)
@@ -1292,7 +1289,7 @@ class NWProject():
# Then check the files in the data folder # Then check the files in the data folder
logger.debug("Checking files in project content folder") logger.debug("Checking files in project content folder")
orphanFiles = [] orphanFiles = []
for fileItem in listdir(self.projContent): for fileItem in os.listdir(self.projContent):
if not fileItem.endswith(".nwd"): if not fileItem.endswith(".nwd"):
logger.warning("Skipping file %s" % fileItem) logger.warning("Skipping file %s" % fileItem)
continue continue
@@ -1355,8 +1352,8 @@ class NWProject():
if not self.ensureFolderStructure(): if not self.ensureFolderStructure():
return False return False
sessionFile = path.join(self.projMeta, nwFiles.SESS_STATS) sessionFile = os.path.join(self.projMeta, nwFiles.SESS_STATS)
isFile = path.isfile(sessionFile) isFile = os.path.isfile(sessionFile)
with open(sessionFile, mode="a+", encoding="utf8") as outFile: with open(sessionFile, mode="a+", encoding="utf8") as outFile:
if not isFile: if not isFile:
@@ -1383,8 +1380,8 @@ class NWProject():
def _legacyDataFolder(self, theFolder, errList): def _legacyDataFolder(self, theFolder, errList):
"""Clean up legacy data folders. """Clean up legacy data folders.
""" """
theData = path.join(self.projPath, theFolder) theData = os.path.join(self.projPath, theFolder)
if not path.isdir(theData): if not os.path.isdir(theData):
errList.append("Not a folder: %s" % theData) errList.append("Not a folder: %s" % theData)
return errList return errList
@@ -1392,9 +1389,9 @@ class NWProject():
# Move Documents to Content # Move Documents to Content
# ========================= # =========================
for dataItem in listdir(theData): for dataItem in os.listdir(theData):
theFile = path.join(theData, dataItem) theFile = os.path.join(theData, dataItem)
if not path.isfile(theFile): if not os.path.isfile(theFile):
theErr = self._moveUnknownItem(theData, dataItem) theErr = self._moveUnknownItem(theData, dataItem)
if theErr: if theErr:
errList.append(theErr) errList.append(theErr)
@@ -1402,9 +1399,9 @@ class NWProject():
if len(dataItem) == 21 and dataItem.endswith("_main.nwd"): if len(dataItem) == 21 and dataItem.endswith("_main.nwd"):
tHandle = theFolder[-1]+dataItem[:12] tHandle = theFolder[-1]+dataItem[:12]
newPath = path.join(self.projContent, tHandle+".nwd") newPath = os.path.join(self.projContent, tHandle+".nwd")
try: try:
rename(theFile, newPath) os.rename(theFile, newPath)
logger.info("Moved file: %s" % theFile) logger.info("Moved file: %s" % theFile)
logger.info("New location: %s" % newPath) logger.info("New location: %s" % newPath)
except Exception as e: except Exception as e:
@@ -1413,7 +1410,7 @@ class NWProject():
elif len(dataItem) == 21 and dataItem.endswith("_main.bak"): elif len(dataItem) == 21 and dataItem.endswith("_main.bak"):
try: try:
unlink(theFile) os.unlink(theFile)
logger.info("Deleted file: %s" % theFile) logger.info("Deleted file: %s" % theFile)
except Exception as e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
@@ -1427,7 +1424,7 @@ class NWProject():
# Remove Data Folder # Remove Data Folder
# ================== # ==================
try: try:
rmdir(theData) os.rmdir(theData)
logger.info("Removed folder: %s" % theFolder) logger.info("Removed folder: %s" % theFolder)
except Exception as e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
@@ -1439,15 +1436,15 @@ class NWProject():
"""Move an item that doesn't belong in the project folder to """Move an item that doesn't belong in the project folder to
a junk folder. a junk folder.
""" """
theJunk = path.join(self.projPath, "junk") theJunk = os.path.join(self.projPath, "junk")
if not self._checkFolder(theJunk): if not self._checkFolder(theJunk):
return "Could not make folder: %s" % theJunk return "Could not make folder: %s" % theJunk
theSrc = path.join(theDir, theItem) theSrc = os.path.join(theDir, theItem)
theDst = path.join(theJunk, theItem) theDst = os.path.join(theJunk, theItem)
try: try:
rename(theSrc, theDst) os.rename(theSrc, theDst)
logger.info("Moved to junk: %s" % theSrc) logger.info("Moved to junk: %s" % theSrc)
except Exception as e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
@@ -1459,29 +1456,29 @@ class NWProject():
"""Delete files that are no longer used by novelWriter. """Delete files that are no longer used by novelWriter.
""" """
rmList = [ rmList = [
path.join(self.projCache, "nwProject.nwx.0"), os.path.join(self.projCache, "nwProject.nwx.0"),
path.join(self.projCache, "nwProject.nwx.1"), os.path.join(self.projCache, "nwProject.nwx.1"),
path.join(self.projCache, "nwProject.nwx.2"), os.path.join(self.projCache, "nwProject.nwx.2"),
path.join(self.projCache, "nwProject.nwx.3"), os.path.join(self.projCache, "nwProject.nwx.3"),
path.join(self.projCache, "nwProject.nwx.4"), os.path.join(self.projCache, "nwProject.nwx.4"),
path.join(self.projCache, "nwProject.nwx.5"), os.path.join(self.projCache, "nwProject.nwx.5"),
path.join(self.projCache, "nwProject.nwx.6"), os.path.join(self.projCache, "nwProject.nwx.6"),
path.join(self.projCache, "nwProject.nwx.7"), os.path.join(self.projCache, "nwProject.nwx.7"),
path.join(self.projCache, "nwProject.nwx.8"), os.path.join(self.projCache, "nwProject.nwx.8"),
path.join(self.projCache, "nwProject.nwx.9"), os.path.join(self.projCache, "nwProject.nwx.9"),
path.join(self.projMeta, "mainOptions.json"), os.path.join(self.projMeta, "mainOptions.json"),
path.join(self.projMeta, "exportOptions.json"), os.path.join(self.projMeta, "exportOptions.json"),
path.join(self.projMeta, "outlineOptions.json"), os.path.join(self.projMeta, "outlineOptions.json"),
path.join(self.projMeta, "timelineOptions.json"), os.path.join(self.projMeta, "timelineOptions.json"),
path.join(self.projMeta, "docMergeOptions.json"), os.path.join(self.projMeta, "docMergeOptions.json"),
path.join(self.projMeta, "sessionLogOptions.json"), os.path.join(self.projMeta, "sessionLogOptions.json"),
] ]
for rmFile in rmList: for rmFile in rmList:
if path.isfile(rmFile): if os.path.isfile(rmFile):
logger.info("Deleting: %s" % rmFile) logger.info("Deleting: %s" % rmFile)
try: try:
unlink(rmFile) os.unlink(rmFile)
except Exception as e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
+5 -5
View File
@@ -27,8 +27,8 @@
import nw import nw
import logging import logging
import os
from os import path, listdir
from difflib import get_close_matches from difflib import get_close_matches
from nw.constants import isoLanguage from nw.constants import isoLanguage
@@ -108,7 +108,7 @@ class NWSpellCheck():
self.PROJW = [] self.PROJW = []
if projectDict is not None: if projectDict is not None:
self.projectDict = projectDict self.projectDict = projectDict
if not path.isfile(projectDict): if not os.path.isfile(projectDict):
return return
try: try:
logger.debug("Loading project word list") logger.debug("Loading project word list")
@@ -228,7 +228,7 @@ class NWSpellSimple(NWSpellCheck):
"""Load a dictionary as a list from the app assets folder. """Load a dictionary as a list from the app assets folder.
""" """
self.WORDS = [] self.WORDS = []
dictFile = path.join(self.mainConf.dictPath, theLang+".dict") dictFile = os.path.join(self.mainConf.dictPath, theLang+".dict")
try: try:
with open(dictFile, mode="r", encoding="utf-8") as wordsFile: with open(dictFile, mode="r", encoding="utf-8") as wordsFile:
for theLine in wordsFile: for theLine in wordsFile:
@@ -297,9 +297,9 @@ class NWSpellSimple(NWSpellCheck):
"""Lists the dictionary files in the app assets folder. """Lists the dictionary files in the app assets folder.
""" """
retList = [] retList = []
for dictFile in listdir(self.mainConf.dictPath): for dictFile in os.listdir(self.mainConf.dictPath):
theBits = path.splitext(dictFile) theBits = os.path.splitext(dictFile)
if len(theBits) != 2: if len(theBits) != 2:
continue continue
if theBits[1] != ".dict": if theBits[1] != ".dict":
+6 -6
View File
@@ -27,8 +27,8 @@
import logging import logging
import json import json
import os
from os import path
from lxml import etree from lxml import etree
from hashlib import sha256 from hashlib import sha256
from time import time from time import time
@@ -144,8 +144,8 @@ class NWTree():
the project directory. These files are there to assist the user the project directory. These files are there to assist the user
if they wish to browse the stored files. if they wish to browse the stored files.
""" """
tocText = path.join(self.theProject.projPath, nwFiles.TOC_TXT) tocText = os.path.join(self.theProject.projPath, nwFiles.TOC_TXT)
tocJson = path.join(self.theProject.projPath, nwFiles.TOC_JSON) tocJson = os.path.join(self.theProject.projPath, nwFiles.TOC_JSON)
jsonData = [] jsonData = []
try: try:
@@ -162,14 +162,14 @@ class NWTree():
if tItem is None: if tItem is None:
continue continue
tFile = tHandle+".nwd" tFile = tHandle+".nwd"
if path.isfile(path.join(self.theProject.projContent, tFile)): if os.path.isfile(os.path.join(self.theProject.projContent, tFile)):
outFile.write(" %-25s %-9s %s\n" % ( outFile.write(" %-25s %-9s %s\n" % (
path.join("content", tFile), os.path.join("content", tFile),
tItem.itemClass.name, tItem.itemClass.name,
tItem.itemName, tItem.itemName,
)) ))
jsonData.append([ jsonData.append([
path.join("content", tFile), os.path.join("content", tFile),
tItem.itemClass.name, tItem.itemClass.name,
tItem.itemName, tItem.itemName,
]) ])
+3 -3
View File
@@ -27,8 +27,8 @@
import nw import nw
import logging import logging
import os
from os import path
from datetime import datetime from datetime import datetime
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
@@ -197,8 +197,8 @@ class GuiAbout(QDialog):
"""Load the content for the License page. """Load the content for the License page.
""" """
docName = "gplv3_%s.htm" % self.mainConf.guiLang docName = "gplv3_%s.htm" % self.mainConf.guiLang
docPath = path.join(self.mainConf.assetPath, "text", docName) docPath = os.path.join(self.mainConf.assetPath, "text", docName)
if path.isfile(docPath): if os.path.isfile(docPath):
with open(docPath, mode="r", encoding="utf8") as inFile: with open(docPath, mode="r", encoding="utf8") as inFile:
helpText = inFile.read() helpText = inFile.read()
self.pageLicense.setHtml(helpText) self.pageLicense.setHtml(helpText)
+6 -6
View File
@@ -28,8 +28,8 @@
import nw import nw
import logging import logging
import json import json
import os
from os import path
from time import time from time import time
from datetime import datetime from datetime import datetime
@@ -630,8 +630,8 @@ class GuiBuildNovel(QDialog):
cleanName = makeFileNameSafe(self.theProject.projName) cleanName = makeFileNameSafe(self.theProject.projName)
fileName = "%s.%s" % (cleanName, fileExt) fileName = "%s.%s" % (cleanName, fileExt)
saveDir = self.mainConf.lastPath saveDir = self.mainConf.lastPath
savePath = path.join(saveDir, fileName) savePath = os.path.join(saveDir, fileName)
if not path.isdir(saveDir): if not os.path.isdir(saveDir):
saveDir = self.mainConf.homePath saveDir = self.mainConf.homePath
if self.mainConf.showGUI: if self.mainConf.showGUI:
@@ -792,9 +792,9 @@ class GuiBuildNovel(QDialog):
def _loadCache(self): def _loadCache(self):
"""Save the current data to cache. """Save the current data to cache.
""" """
buildCache = path.join(self.theProject.projCache, nwFiles.BUILD_CACHE) buildCache = os.path.join(self.theProject.projCache, nwFiles.BUILD_CACHE)
dataCount = 0 dataCount = 0
if path.isfile(buildCache): if os.path.isfile(buildCache):
logger.debug("Loading build cache") logger.debug("Loading build cache")
try: try:
@@ -823,7 +823,7 @@ class GuiBuildNovel(QDialog):
def _saveCache(self): def _saveCache(self):
"""Save the current data to cache. """Save the current data to cache.
""" """
buildCache = path.join(self.theProject.projCache, nwFiles.BUILD_CACHE) buildCache = os.path.join(self.theProject.projCache, nwFiles.BUILD_CACHE)
if self.mainConf.debugInfo: if self.mainConf.debugInfo:
nIndent = 2 nIndent = 2
+2 -3
View File
@@ -27,8 +27,7 @@
import nw import nw
import logging import logging
import os
from os import path
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont from PyQt5.QtGui import QFont
@@ -335,7 +334,7 @@ class GuiConfigEditGeneralTab(QWidget):
"""Open a dialog to select the backup folder. """Open a dialog to select the backup folder.
""" """
currDir = self.backupPath currDir = self.backupPath
if not path.isdir(currDir): if not os.path.isdir(currDir):
currDir = "" currDir = ""
dlgOpt = QFileDialog.Options() dlgOpt = QFileDialog.Options()
+2 -2
View File
@@ -27,8 +27,8 @@
import nw import nw
import logging import logging
import os
from os import path
from datetime import datetime from datetime import datetime
from PyQt5.QtCore import Qt, QSize from PyQt5.QtCore import Qt, QSize
@@ -186,7 +186,7 @@ class GuiProjectLoad(QDialog):
options=dlgOpt options=dlgOpt
) )
if projFile: if projFile:
thePath = path.abspath(path.dirname(projFile)) thePath = os.path.abspath(os.path.dirname(projFile))
self.selPath.setText(thePath) self.selPath.setText(thePath)
self.openPath = thePath self.openPath = thePath
self.openState = self.OPEN_STATE self.openState = self.OPEN_STATE
+3 -4
View File
@@ -27,8 +27,7 @@
import nw import nw
import logging import logging
import os
from os import path
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
@@ -208,7 +207,7 @@ class ProjWizardFolderPage(QWizardPage):
"""Select a project folder. """Select a project folder.
""" """
lastPath = self.mainConf.lastPath lastPath = self.mainConf.lastPath
if not path.isdir(lastPath): if not os.path.isdir(lastPath):
lastPath = "" lastPath = ""
dlgOpt = QFileDialog.Options() dlgOpt = QFileDialog.Options()
@@ -220,7 +219,7 @@ class ProjWizardFolderPage(QWizardPage):
if projDir: if projDir:
projName = self.field("projName") projName = self.field("projName")
if projName is not None: if projName is not None:
fullDir = path.join(path.abspath(projDir), makeFileNameSafe(projName)) fullDir = os.path.join(os.path.abspath(projDir), makeFileNameSafe(projName))
self.projPath.setText(fullDir) self.projPath.setText(fullDir)
else: else:
self.projPath.setText("") self.projPath.setText("")
+38 -38
View File
@@ -29,8 +29,8 @@
import nw import nw
import logging import logging
import configparser import configparser
import os
from os import path, listdir
from math import ceil from math import ceil
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
@@ -182,21 +182,21 @@ class GuiTheme:
"""Add the fonts in the assets fonts folder to the app. """Add the fonts in the assets fonts folder to the app.
""" """
ttfList = [] ttfList = []
fontAssets = path.join(self.mainConf.assetPath, self.fontPath) fontAssets = os.path.join(self.mainConf.assetPath, self.fontPath)
for fontFam in listdir(fontAssets): for fontFam in os.listdir(fontAssets):
fontDir = path.join(fontAssets, fontFam) fontDir = os.path.join(fontAssets, fontFam)
if path.isdir(fontDir): if os.path.isdir(fontDir):
if fontFam not in self.guiFontDB.families(): if fontFam not in self.guiFontDB.families():
for fontFile in listdir(fontDir): for fontFile in os.listdir(fontDir):
ttfFile = path.join(fontDir, fontFile) ttfFile = os.path.join(fontDir, fontFile)
if path.isfile(ttfFile) and fontFile.endswith(".ttf"): if os.path.isfile(ttfFile) and fontFile.endswith(".ttf"):
ttfList.append(ttfFile) ttfList.append(ttfFile)
for ttfFile in ttfList: for ttfFile in ttfList:
logger.verbose("Font asset: %s" % path.relpath(ttfFile)) logger.verbose("Font asset: %s" % os.path.relpath(ttfFile))
fontID = self.guiFontDB.addApplicationFont(ttfFile) fontID = self.guiFontDB.addApplicationFont(ttfFile)
if fontID < 0: if fontID < 0:
logger.error("Failed to add font: %s" % path.relpath(ttfFile)) logger.error("Failed to add font: %s" % os.path.relpath(ttfFile))
return return
@@ -227,10 +227,10 @@ class GuiTheme:
self.guiTheme = self.mainConf.guiTheme self.guiTheme = self.mainConf.guiTheme
self.guiSyntax = self.mainConf.guiSyntax self.guiSyntax = self.mainConf.guiSyntax
self.themeRoot = self.mainConf.themeRoot self.themeRoot = self.mainConf.themeRoot
self.themePath = path.join(self.mainConf.themeRoot, self.guiPath, self.guiTheme) self.themePath = os.path.join(self.mainConf.themeRoot, self.guiPath, self.guiTheme)
self.syntaxFile = path.join(self.themeRoot, self.syntaxPath, self.guiSyntax+".conf") self.syntaxFile = os.path.join(self.themeRoot, self.syntaxPath, self.guiSyntax+".conf")
self.confFile = path.join(self.themePath, self.confName) self.confFile = os.path.join(self.themePath, self.confName)
self.cssFile = path.join(self.themePath, self.cssName) self.cssFile = os.path.join(self.themePath, self.cssName)
self.loadTheme() self.loadTheme()
self.loadSyntax() self.loadSyntax()
@@ -259,7 +259,7 @@ class GuiTheme:
# CSS File # CSS File
cssData = "" cssData = ""
try: try:
if path.isfile(self.cssFile): if os.path.isfile(self.cssFile):
with open(self.cssFile, mode="r", encoding="utf8") as inFile: with open(self.cssFile, mode="r", encoding="utf8") as inFile:
cssData = inFile.read() cssData = inFile.read()
except Exception as e: except Exception as e:
@@ -375,8 +375,8 @@ class GuiTheme:
return self.themeList return self.themeList
confParser = configparser.ConfigParser() confParser = configparser.ConfigParser()
for themeDir in listdir(path.join(self.mainConf.themeRoot, self.guiPath)): for themeDir in os.listdir(os.path.join(self.mainConf.themeRoot, self.guiPath)):
themeConf = path.join(self.mainConf.themeRoot, self.guiPath, themeDir, self.confName) themeConf = os.path.join(self.mainConf.themeRoot, self.guiPath, themeDir, self.confName)
logger.verbose("Checking theme config for '%s'" % themeDir) logger.verbose("Checking theme config for '%s'" % themeDir)
try: try:
with open(themeConf, mode="r", encoding="utf8") as inFile: with open(themeConf, mode="r", encoding="utf8") as inFile:
@@ -405,10 +405,10 @@ class GuiTheme:
return self.syntaxList return self.syntaxList
confParser = configparser.ConfigParser() confParser = configparser.ConfigParser()
syntaxDir = path.join(self.mainConf.themeRoot, self.syntaxPath) syntaxDir = os.path.join(self.mainConf.themeRoot, self.syntaxPath)
for syntaxFile in listdir(syntaxDir): for syntaxFile in os.listdir(syntaxDir):
syntaxPath = path.join(syntaxDir, syntaxFile) syntaxPath = os.path.join(syntaxDir, syntaxFile)
if not path.isfile(syntaxPath): if not os.path.isfile(syntaxPath):
continue continue
logger.verbose("Checking theme syntax for '%s'" % syntaxFile) logger.verbose("Checking theme syntax for '%s'" % syntaxFile)
try: try:
@@ -612,11 +612,11 @@ class GuiIcons:
logger.debug("Loading icon theme files") logger.debug("Loading icon theme files")
self.themeMap = {} self.themeMap = {}
checkPath = path.join(self.mainConf.iconPath, self.mainConf.guiIcons) checkPath = os.path.join(self.mainConf.iconPath, self.mainConf.guiIcons)
if path.isdir(checkPath): if os.path.isdir(checkPath):
logger.debug("Loading icon theme '%s'" % self.mainConf.guiIcons) logger.debug("Loading icon theme '%s'" % self.mainConf.guiIcons)
self.iconPath = checkPath self.iconPath = checkPath
self.confFile = path.join(checkPath, self.confName) self.confFile = os.path.join(checkPath, self.confName)
else: else:
return False return False
@@ -648,8 +648,8 @@ class GuiIcons:
if iconName not in self.ICON_MAP: if iconName not in self.ICON_MAP:
logger.error("Unknown icon name '%s' in config file" % iconName) logger.error("Unknown icon name '%s' in config file" % iconName)
else: else:
iconPath = path.join(self.iconPath, iconFile) iconPath = os.path.join(self.iconPath, iconFile)
if path.isfile(iconPath): if os.path.isfile(iconPath):
self.themeMap[iconName] = iconPath self.themeMap[iconName] = iconPath
logger.verbose("Icon slot '%s' using file '%s'" % (iconName, iconFile)) logger.verbose("Icon slot '%s' using file '%s'" % (iconName, iconFile))
else: else:
@@ -671,10 +671,10 @@ class GuiIcons:
logger.error("Decoration with name '%s' does not exist" % decoKey) logger.error("Decoration with name '%s' does not exist" % decoKey)
return QPixmap() return QPixmap()
imgPath = path.join( imgPath = os.path.join(
self.mainConf.assetPath, "images", self.DECO_MAP[decoKey] self.mainConf.assetPath, "images", self.DECO_MAP[decoKey]
) )
if not path.isfile(imgPath): if not os.path.isfile(imgPath):
logger.error("Decoration file '%s' not in assets folder" % self.DECO_MAP[decoKey]) logger.error("Decoration file '%s' not in assets folder" % self.DECO_MAP[decoKey])
return QPixmap() return QPixmap()
@@ -714,11 +714,11 @@ class GuiIcons:
return self.themeList return self.themeList
confParser = configparser.ConfigParser() confParser = configparser.ConfigParser()
for themeDir in listdir(self.mainConf.iconPath): for themeDir in os.listdir(self.mainConf.iconPath):
themePath = path.join(self.mainConf.iconPath, themeDir) themePath = os.path.join(self.mainConf.iconPath, themeDir)
if not path.isdir(themePath) or themeDir == self.fbackName: if not os.path.isdir(themePath) or themeDir == self.fbackName:
continue continue
themeConf = path.join(themePath, self.confName) themeConf = os.path.join(themePath, self.confName)
logger.verbose("Checking icon theme config for '%s'" % themeDir) logger.verbose("Checking icon theme config for '%s'" % themeDir)
try: try:
with open(themeConf, mode="r", encoding="utf8") as inFile: with open(themeConf, mode="r", encoding="utf8") as inFile:
@@ -756,12 +756,12 @@ class GuiIcons:
# If we just want the app icon, return it right away # If we just want the app icon, return it right away
if iconKey == "novelwriter": if iconKey == "novelwriter":
return QIcon(path.join(self.mainConf.iconPath, "novelwriter.svg")) return QIcon(os.path.join(self.mainConf.iconPath, "novelwriter.svg"))
# Otherwise, we start looking for it # Otherwise, we start looking for it
# First in the theme folder # First in the theme folder
if iconKey in self.themeMap: if iconKey in self.themeMap:
logger.verbose("Loading: %s" % path.relpath(self.themeMap[iconKey])) logger.verbose("Loading: %s" % os.path.relpath(self.themeMap[iconKey]))
return QIcon(self.themeMap[iconKey]) return QIcon(self.themeMap[iconKey])
# Next, we try to load the Qt style icons # Next, we try to load the Qt style icons
@@ -777,14 +777,14 @@ class GuiIcons:
# Finally. we check if we have a fallback icon # Finally. we check if we have a fallback icon
if self.mainConf.guiDark: if self.mainConf.guiDark:
fbackIcon = path.join( fbackIcon = os.path.join(
self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey
) )
if path.isfile(fbackIcon): if os.path.isfile(fbackIcon):
logger.verbose("Loading icon '%s' from fallback theme (dark mode)" % iconKey) logger.verbose("Loading icon '%s' from fallback theme (dark mode)" % iconKey)
return QIcon(fbackIcon) return QIcon(fbackIcon)
fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey) fbackIcon = os.path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey)
if path.isfile(fbackIcon): if os.path.isfile(fbackIcon):
logger.verbose("Loading icon '%s' from fallback theme (light mode)" % iconKey) logger.verbose("Loading icon '%s' from fallback theme (light mode)" % iconKey)
return QIcon(fbackIcon) return QIcon(fbackIcon)
+4 -4
View File
@@ -28,8 +28,8 @@
import nw import nw
import logging import logging
import json import json
import os
from os import path
from datetime import datetime from datetime import datetime
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
@@ -322,8 +322,8 @@ class GuiWritingStats(QDialog):
if fileExt: if fileExt:
fileName = "sessionStats.%s" % fileExt fileName = "sessionStats.%s" % fileExt
saveDir = self.mainConf.lastPath saveDir = self.mainConf.lastPath
savePath = path.join(saveDir, fileName) savePath = os.path.join(saveDir, fileName)
if not path.isdir(saveDir): if not os.path.isdir(saveDir):
saveDir = self.mainConf.homePath saveDir = self.mainConf.homePath
dlgOpt = QFileDialog.Options() dlgOpt = QFileDialog.Options()
@@ -410,7 +410,7 @@ class GuiWritingStats(QDialog):
ttTime = 0 ttTime = 0
try: try:
logFile = path.join(self.theProject.projMeta, nwFiles.SESS_STATS) logFile = os.path.join(self.theProject.projMeta, nwFiles.SESS_STATS)
with open(logFile, mode="r", encoding="utf8") as inFile: with open(logFile, mode="r", encoding="utf8") as inFile:
for inLine in inFile: for inLine in inFile:
if inLine.startswith("#"): if inLine.startswith("#"):
+2 -2
View File
@@ -27,8 +27,8 @@
import nw import nw
import logging import logging
import os
from os import path
from datetime import datetime from datetime import datetime
from time import time from time import time
@@ -268,7 +268,7 @@ class GuiMain(QMainWindow):
logger.error("No projData or projPath set") logger.error("No projData or projPath set")
return False return False
if path.isfile(path.join(projPath, self.theProject.projFile)): if os.path.isfile(os.path.join(projPath, self.theProject.projFile)):
self.makeAlert( self.makeAlert(
"A project already exists in that location. Please choose another folder.", "A project already exists in that location. Please choose another folder.",
nwAlert.ERROR nwAlert.ERROR
+2 -3
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys import sys
import shutil
import subprocess import subprocess
import setuptools import setuptools
@@ -42,7 +41,7 @@ if buildDocs:
buildFail = False buildFail = False
try: try:
subprocess.call(["make","-C", "docs", "qthelp"]) subprocess.call(["make", "-C", "docs", "qthelp"])
except Exception as e: except Exception as e:
print("Failed with error:") print("Failed with error:")
print(str(e)) print(str(e))
@@ -98,7 +97,7 @@ if buildSample:
from zipfile import ZipFile from zipfile import ZipFile
with ZipFile(dstSample, "w") as zipObj: with ZipFile(dstSample, "w") as zipObj:
zipObj.write(os.path.join("sample", "nwProject.nwx"), "nwProject.nwx") zipObj.write(os.path.join(srcSample, "nwProject.nwx"), "nwProject.nwx")
for docFile in os.listdir(os.path.join(srcSample, "content")): for docFile in os.listdir(os.path.join(srcSample, "content")):
srcDoc = os.path.join(srcSample, "content", docFile) srcDoc = os.path.join(srcSample, "content", docFile)
zipObj.write(srcDoc, "content/"+docFile) zipObj.write(srcDoc, "content/"+docFile)
+46 -46
View File
@@ -5,13 +5,13 @@
import sys import sys
import pytest import pytest
import shutil import shutil
import os
from os import path, mkdir
from nwdummy import DummyMain from nwdummy import DummyMain
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
sys.path.insert(1, path.abspath(path.join(path.dirname(__file__), path.pardir))) sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
from nw.config import Config # noqa: E402 from nw.config import Config # noqa: E402
@@ -25,12 +25,12 @@ def nwTemp():
presistent after the test so that the status of generated files can presistent after the test so that the status of generated files can
be checked. The folder is instead cleared before a new test session. be checked. The folder is instead cleared before a new test session.
""" """
testDir = path.dirname(__file__) testDir = os.path.dirname(__file__)
tempDir = path.join(testDir, "temp") tempDir = os.path.join(testDir, "temp")
if path.isdir(tempDir): if os.path.isdir(tempDir):
shutil.rmtree(tempDir) shutil.rmtree(tempDir)
if not path.isdir(tempDir): if not os.path.isdir(tempDir):
mkdir(tempDir) os.mkdir(tempDir)
return tempDir return tempDir
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
@@ -38,8 +38,8 @@ def nwRef():
"""The folder where all the reference files are stored for verifying """The folder where all the reference files are stored for verifying
the results of tests. the results of tests.
""" """
testDir = path.dirname(__file__) testDir = os.path.dirname(__file__)
refDir = path.join(testDir, "reference") refDir = os.path.join(testDir, "reference")
return refDir return refDir
## ##
@@ -80,40 +80,40 @@ def nwDummy(nwRef, nwTemp, nwConf):
def nwTempProj(nwTemp): def nwTempProj(nwTemp):
"""A temporary folder for project tests. """A temporary folder for project tests.
""" """
projDir = path.join(nwTemp, "proj") projDir = os.path.join(nwTemp, "proj")
if not path.isdir(projDir): if not os.path.isdir(projDir):
mkdir(projDir) os.mkdir(projDir)
return projDir return projDir
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def nwTempGUI(nwTemp): def nwTempGUI(nwTemp):
"""A temporary folder for GUI tests. """A temporary folder for GUI tests.
""" """
guiDir = path.join(nwTemp, "gui") guiDir = os.path.join(nwTemp, "gui")
if not path.isdir(guiDir): if not os.path.isdir(guiDir):
mkdir(guiDir) os.mkdir(guiDir)
return guiDir return guiDir
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def nwTempBuild(nwTemp): def nwTempBuild(nwTemp):
"""A temporary folder for build tests. """A temporary folder for build tests.
""" """
buildDir = path.join(nwTemp, "build") buildDir = os.path.join(nwTemp, "build")
if not path.isdir(buildDir): if not os.path.isdir(buildDir):
mkdir(buildDir) os.mkdir(buildDir)
return buildDir return buildDir
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def nwFuncTemp(nwTemp): def nwFuncTemp(nwTemp):
"""A temporary folder for a single test function. """A temporary folder for a single test function.
""" """
funcDir = path.join(nwTemp, "ftemp") funcDir = os.path.join(nwTemp, "ftemp")
if path.isdir(funcDir): if os.path.isdir(funcDir):
shutil.rmtree(funcDir) shutil.rmtree(funcDir)
if not path.isdir(funcDir): if not os.path.isdir(funcDir):
mkdir(funcDir) os.mkdir(funcDir)
yield funcDir yield funcDir
if path.isdir(funcDir): if os.path.isdir(funcDir):
shutil.rmtree(funcDir) shutil.rmtree(funcDir)
return return
@@ -125,20 +125,20 @@ def nwFuncTemp(nwTemp):
def nwMinimal(nwTemp): def nwMinimal(nwTemp):
"""A minimal novelWriter example project. """A minimal novelWriter example project.
""" """
testDir = path.dirname(__file__) testDir = os.path.dirname(__file__)
minimalStore = path.join(testDir, "minimal") minimalStore = os.path.join(testDir, "minimal")
minimalDir = path.join(nwTemp, "minimal") minimalDir = os.path.join(nwTemp, "minimal")
if path.isdir(minimalDir): if os.path.isdir(minimalDir):
shutil.rmtree(minimalDir) shutil.rmtree(minimalDir)
shutil.copytree(minimalStore, minimalDir) shutil.copytree(minimalStore, minimalDir)
cacheDir = path.join(minimalDir, "cache") cacheDir = os.path.join(minimalDir, "cache")
if path.isdir(cacheDir): if os.path.isdir(cacheDir):
shutil.rmtree(cacheDir) shutil.rmtree(cacheDir)
metaDir = path.join(minimalDir, "meta") metaDir = os.path.join(minimalDir, "meta")
if path.isdir(metaDir): if os.path.isdir(metaDir):
shutil.rmtree(metaDir) shutil.rmtree(metaDir)
yield minimalDir yield minimalDir
if path.isdir(minimalDir): if os.path.isdir(minimalDir):
shutil.rmtree(minimalDir) shutil.rmtree(minimalDir)
return return
@@ -147,20 +147,20 @@ def nwLipsum(nwTemp):
"""A medium sized novelWriter example project with a lot of Lorem """A medium sized novelWriter example project with a lot of Lorem
Ipsum dummy text. Ipsum dummy text.
""" """
testDir = path.dirname(__file__) testDir = os.path.dirname(__file__)
lipsumStore = path.join(testDir, "lipsum") lipsumStore = os.path.join(testDir, "lipsum")
lipsumDir = path.join(nwTemp, "lipsum") lipsumDir = os.path.join(nwTemp, "lipsum")
if path.isdir(lipsumDir): if os.path.isdir(lipsumDir):
shutil.rmtree(lipsumDir) shutil.rmtree(lipsumDir)
shutil.copytree(lipsumStore, lipsumDir) shutil.copytree(lipsumStore, lipsumDir)
cacheDir = path.join(lipsumDir, "cache") cacheDir = os.path.join(lipsumDir, "cache")
if path.isdir(cacheDir): if os.path.isdir(cacheDir):
shutil.rmtree(cacheDir) shutil.rmtree(cacheDir)
metaDir = path.join(lipsumDir, "meta") metaDir = os.path.join(lipsumDir, "meta")
if path.isdir(metaDir): if os.path.isdir(metaDir):
shutil.rmtree(metaDir) shutil.rmtree(metaDir)
yield lipsumDir yield lipsumDir
if path.isdir(lipsumDir): if os.path.isdir(lipsumDir):
shutil.rmtree(lipsumDir) shutil.rmtree(lipsumDir)
return return
@@ -168,14 +168,14 @@ def nwLipsum(nwTemp):
def nwOldProj(nwTemp): def nwOldProj(nwTemp):
"""A minimal movelWriter project using the old folder structure. """A minimal movelWriter project using the old folder structure.
""" """
testDir = path.dirname(__file__) testDir = os.path.dirname(__file__)
oldProjStore = path.join(testDir, "oldproj") oldProjStore = os.path.join(testDir, "oldproj")
oldProjDir = path.join(nwTemp, "oldproj") oldProjDir = os.path.join(nwTemp, "oldproj")
if path.isdir(oldProjDir): if os.path.isdir(oldProjDir):
shutil.rmtree(oldProjDir) shutil.rmtree(oldProjDir)
shutil.copytree(oldProjStore, oldProjDir) shutil.copytree(oldProjStore, oldProjDir)
yield oldProjDir yield oldProjDir
if path.isdir(oldProjDir): if os.path.isdir(oldProjDir):
shutil.rmtree(oldProjDir) shutil.rmtree(oldProjDir)
return return
+3 -4
View File
@@ -2,15 +2,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pstats import pstats
import os
from os import path profDir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, "prof"))
profDir = path.abspath(path.join(path.dirname(__file__), path.pardir, "prof"))
print("") print("")
print("Profiles directory: %s" % profDir) print("Profiles directory: %s" % profDir)
print("") print("")
profMainWindows = pstats.Stats(path.join(profDir, "testMainWindows.prof")) profMainWindows = pstats.Stats(os.path.join(profDir, "testMainWindows.prof"))
profMainWindows.sort_stats("cumtime") profMainWindows.sort_stats("cumtime")
profMainWindows.print_stats("nw/") profMainWindows.print_stats("nw/")
+16 -15
View File
@@ -3,13 +3,14 @@
""" """
import pytest import pytest
import os
from nwtools import cmpFiles from nwtools import cmpFiles
from os import path
@pytest.mark.core @pytest.mark.core
def testConfigCore(tmpConf, nwTemp, nwRef): def testConfigCore(tmpConf, nwTemp, nwRef):
refConf = path.join(nwRef, "novelwriter.conf") refConf = os.path.join(nwRef, "novelwriter.conf")
testConf = path.join(tmpConf.confPath, "novelwriter.conf") testConf = os.path.join(tmpConf.confPath, "novelwriter.conf")
assert tmpConf.confPath == nwTemp assert tmpConf.confPath == nwTemp
assert tmpConf.saveConfig() assert tmpConf.saveConfig()
@@ -22,8 +23,8 @@ def testConfigCore(tmpConf, nwTemp, nwRef):
@pytest.mark.core @pytest.mark.core
def testConfigSetConfPath(tmpConf, nwTemp): def testConfigSetConfPath(tmpConf, nwTemp):
assert tmpConf.setConfPath(None) assert tmpConf.setConfPath(None)
assert not tmpConf.setConfPath(path.join("somewhere", "over", "the", "rainbow")) assert not tmpConf.setConfPath(os.path.join("somewhere", "over", "the", "rainbow"))
assert tmpConf.setConfPath(path.join(nwTemp, "novelwriter.conf")) assert tmpConf.setConfPath(os.path.join(nwTemp, "novelwriter.conf"))
assert tmpConf.confPath == nwTemp assert tmpConf.confPath == nwTemp
assert tmpConf.confFile == "novelwriter.conf" assert tmpConf.confFile == "novelwriter.conf"
assert not tmpConf.confChanged assert not tmpConf.confChanged
@@ -31,15 +32,15 @@ def testConfigSetConfPath(tmpConf, nwTemp):
@pytest.mark.core @pytest.mark.core
def testConfigSetDataPath(tmpConf, nwTemp): def testConfigSetDataPath(tmpConf, nwTemp):
assert tmpConf.setDataPath(None) assert tmpConf.setDataPath(None)
assert not tmpConf.setDataPath(path.join("somewhere", "over", "the", "rainbow")) assert not tmpConf.setDataPath(os.path.join("somewhere", "over", "the", "rainbow"))
assert tmpConf.setDataPath(nwTemp) assert tmpConf.setDataPath(nwTemp)
assert tmpConf.dataPath == nwTemp assert tmpConf.dataPath == nwTemp
assert not tmpConf.confChanged assert not tmpConf.confChanged
@pytest.mark.core @pytest.mark.core
def testConfigSetWinSize(tmpConf, nwTemp, nwRef): def testConfigSetWinSize(tmpConf, nwTemp, nwRef):
refConf = path.join(nwRef, "novelwriter.conf") refConf = os.path.join(nwRef, "novelwriter.conf")
testConf = path.join(tmpConf.confPath, "novelwriter.conf") testConf = os.path.join(tmpConf.confPath, "novelwriter.conf")
tmpConf.guiScale = 1.0 tmpConf.guiScale = 1.0
assert tmpConf.confPath == nwTemp assert tmpConf.confPath == nwTemp
@@ -55,8 +56,8 @@ def testConfigSetWinSize(tmpConf, nwTemp, nwRef):
@pytest.mark.core @pytest.mark.core
def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef): def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef):
refConf = path.join(nwRef, "novelwriter.conf") refConf = os.path.join(nwRef, "novelwriter.conf")
testConf = path.join(tmpConf.confPath, "novelwriter.conf") testConf = os.path.join(tmpConf.confPath, "novelwriter.conf")
assert tmpConf.confPath == nwTemp assert tmpConf.confPath == nwTemp
tmpConf.guiScale = 1.0 tmpConf.guiScale = 1.0
@@ -77,8 +78,8 @@ def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef):
@pytest.mark.core @pytest.mark.core
def testConfigSetPanePos(tmpConf, nwTemp, nwRef): def testConfigSetPanePos(tmpConf, nwTemp, nwRef):
refConf = path.join(nwRef, "novelwriter.conf") refConf = os.path.join(nwRef, "novelwriter.conf")
testConf = path.join(tmpConf.confPath, "novelwriter.conf") testConf = os.path.join(tmpConf.confPath, "novelwriter.conf")
assert tmpConf.confPath == nwTemp assert tmpConf.confPath == nwTemp
@@ -113,8 +114,8 @@ def testConfigSetPanePos(tmpConf, nwTemp, nwRef):
@pytest.mark.core @pytest.mark.core
def testConfigFlags(tmpConf, nwTemp, nwRef): def testConfigFlags(tmpConf, nwTemp, nwRef):
refConf = path.join(nwRef, "novelwriter.conf") refConf = os.path.join(nwRef, "novelwriter.conf")
testConf = path.join(tmpConf.confPath, "novelwriter.conf") testConf = os.path.join(tmpConf.confPath, "novelwriter.conf")
assert tmpConf.confPath == nwTemp assert tmpConf.confPath == nwTemp
@@ -150,7 +151,7 @@ def testTextSizes(tmpConf, nwTemp, nwRef):
@pytest.mark.core @pytest.mark.core
def testConfigErrors(tmpConf): def testConfigErrors(tmpConf):
nonPath = path.join("somewhere", "over", "the", "rainbow") nonPath = os.path.join("somewhere", "over", "the", "rainbow")
assert tmpConf.initConfig(nonPath, nonPath) assert tmpConf.initConfig(nonPath, nonPath)
assert tmpConf.hasError assert tmpConf.hasError
assert not tmpConf.loadConfig() assert not tmpConf.loadConfig()
+76 -77
View File
@@ -5,12 +5,11 @@
import nw import nw
import pytest import pytest
import json import json
import os
from shutil import copyfile from shutil import copyfile
from nwtools import cmpFiles, getGuiItem from nwtools import cmpFiles, getGuiItem
from os import path
from PyQt5.QtCore import Qt, QItemSelectionModel from PyQt5.QtCore import Qt, QItemSelectionModel
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialogButtonBox, QTreeWidgetItem, QListWidgetItem, QDialog, QAction, QDialogButtonBox, QTreeWidgetItem, QListWidgetItem, QDialog, QAction,
@@ -130,9 +129,9 @@ def testProjectSettings(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTempGUI, nwR
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Check the files # Check the files
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempGUI, "2_nwProject.nwx") testFile = os.path.join(nwTempGUI, "2_nwProject.nwx")
refFile = path.join(nwRef, "gui", "2_nwProject.nwx") refFile = os.path.join(nwRef, "gui", "2_nwProject.nwx")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [2, 8, 9, 10]) assert cmpFiles(testFile, refFile, [2, 8, 9, 10])
@@ -189,9 +188,9 @@ def testItemEditor(qtbot, yesToAll, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Check the files # Check the files
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempGUI, "3_nwProject.nwx") testFile = os.path.join(nwTempGUI, "3_nwProject.nwx")
refFile = path.join(nwRef, "gui", "3_nwProject.nwx") refFile = os.path.join(nwRef, "gui", "3_nwProject.nwx")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
@@ -273,7 +272,7 @@ def testWritingStatsExport(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTemp):
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
jsonStats = path.join(nwFuncTemp, "sessionStats.json") jsonStats = os.path.join(nwFuncTemp, "sessionStats.json")
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -289,7 +288,7 @@ def testWritingStatsExport(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTemp):
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
jsonStats = path.join(nwFuncTemp, "sessionStats.json") jsonStats = os.path.join(nwFuncTemp, "sessionStats.json")
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -306,7 +305,7 @@ def testWritingStatsExport(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTemp):
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
jsonStats = path.join(nwFuncTemp, "sessionStats.json") jsonStats = os.path.join(nwFuncTemp, "sessionStats.json")
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -323,7 +322,7 @@ def testWritingStatsExport(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTemp):
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
jsonStats = path.join(nwFuncTemp, "sessionStats.json") jsonStats = os.path.join(nwFuncTemp, "sessionStats.json")
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -336,7 +335,7 @@ def testWritingStatsExport(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTemp):
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
jsonStats = path.join(nwFuncTemp, "sessionStats.json") jsonStats = os.path.join(nwFuncTemp, "sessionStats.json")
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -348,7 +347,7 @@ def testWritingStatsExport(qtbot, monkeypatch, yesToAll, nwFuncTemp, nwTemp):
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
jsonStats = path.join(nwFuncTemp, "sessionStats.json") jsonStats = os.path.join(nwFuncTemp, "sessionStats.json")
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -419,15 +418,15 @@ def testBuildTool(qtbot, yesToAll, nwTempBuild, nwLipsum, nwRef, nwTemp):
assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwBuild._saveDocument(nwBuild.FMT_NWD)
assert nwBuild._saveDocument(nwBuild.FMT_HTM) assert nwBuild._saveDocument(nwBuild.FMT_HTM)
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd") projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
testFile = path.join(nwTempBuild, "1_LoremIpsum.nwd") testFile = os.path.join(nwTempBuild, "1_LoremIpsum.nwd")
refFile = path.join(nwRef, "build", "1_LoremIpsum.nwd") refFile = os.path.join(nwRef, "build", "1_LoremIpsum.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "Lorem Ipsum.htm") projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
testFile = path.join(nwTempBuild, "1_LoremIpsum.htm") testFile = os.path.join(nwTempBuild, "1_LoremIpsum.htm")
refFile = path.join(nwRef, "build", "1_LoremIpsum.htm") refFile = os.path.join(nwRef, "build", "1_LoremIpsum.htm")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
@@ -458,15 +457,15 @@ def testBuildTool(qtbot, yesToAll, nwTempBuild, nwLipsum, nwRef, nwTemp):
assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwBuild._saveDocument(nwBuild.FMT_NWD)
assert nwBuild._saveDocument(nwBuild.FMT_HTM) assert nwBuild._saveDocument(nwBuild.FMT_HTM)
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd") projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
testFile = path.join(nwTempBuild, "2_LoremIpsum.nwd") testFile = os.path.join(nwTempBuild, "2_LoremIpsum.nwd")
refFile = path.join(nwRef, "build", "2_LoremIpsum.nwd") refFile = os.path.join(nwRef, "build", "2_LoremIpsum.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "Lorem Ipsum.htm") projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
testFile = path.join(nwTempBuild, "2_LoremIpsum.htm") testFile = os.path.join(nwTempBuild, "2_LoremIpsum.htm")
refFile = path.join(nwRef, "build", "2_LoremIpsum.htm") refFile = os.path.join(nwRef, "build", "2_LoremIpsum.htm")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
@@ -491,31 +490,31 @@ def testBuildTool(qtbot, yesToAll, nwTempBuild, nwLipsum, nwRef, nwTemp):
# Save files that can be compared # Save files that can be compared
assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwBuild._saveDocument(nwBuild.FMT_NWD)
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd") projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
testFile = path.join(nwTempBuild, "3_LoremIpsum.nwd") testFile = os.path.join(nwTempBuild, "3_LoremIpsum.nwd")
refFile = path.join(nwRef, "build", "3_LoremIpsum.nwd") refFile = os.path.join(nwRef, "build", "3_LoremIpsum.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
assert nwBuild._saveDocument(nwBuild.FMT_HTM) assert nwBuild._saveDocument(nwBuild.FMT_HTM)
projFile = path.join(nwLipsum, "Lorem Ipsum.htm") projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
testFile = path.join(nwTempBuild, "3_LoremIpsum.htm") testFile = os.path.join(nwTempBuild, "3_LoremIpsum.htm")
refFile = path.join(nwRef, "build", "3_LoremIpsum.htm") refFile = os.path.join(nwRef, "build", "3_LoremIpsum.htm")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
# Check the JSON files too at this stage # Check the JSON files too at this stage
assert nwBuild._saveDocument(nwBuild.FMT_JSON_H) assert nwBuild._saveDocument(nwBuild.FMT_JSON_H)
projFile = path.join(nwLipsum, "Lorem Ipsum.json") projFile = os.path.join(nwLipsum, "Lorem Ipsum.json")
testFile = path.join(nwTempBuild, "3H_LoremIpsum.json") testFile = os.path.join(nwTempBuild, "3H_LoremIpsum.json")
refFile = path.join(nwRef, "build", "3H_LoremIpsum.json") refFile = os.path.join(nwRef, "build", "3H_LoremIpsum.json")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [8]) assert cmpFiles(testFile, refFile, [8])
assert nwBuild._saveDocument(nwBuild.FMT_JSON_M) assert nwBuild._saveDocument(nwBuild.FMT_JSON_M)
projFile = path.join(nwLipsum, "Lorem Ipsum.json") projFile = os.path.join(nwLipsum, "Lorem Ipsum.json")
testFile = path.join(nwTempBuild, "3M_LoremIpsum.json") testFile = os.path.join(nwTempBuild, "3M_LoremIpsum.json")
refFile = path.join(nwRef, "build", "3M_LoremIpsum.json") refFile = os.path.join(nwRef, "build", "3M_LoremIpsum.json")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [8]) assert cmpFiles(testFile, refFile, [8])
@@ -526,10 +525,10 @@ def testBuildTool(qtbot, yesToAll, nwTempBuild, nwLipsum, nwRef, nwTemp):
assert nwBuild._saveDocument(nwBuild.FMT_PDF) assert nwBuild._saveDocument(nwBuild.FMT_PDF)
assert nwBuild._saveDocument(nwBuild.FMT_MD) assert nwBuild._saveDocument(nwBuild.FMT_MD)
assert nwBuild._saveDocument(nwBuild.FMT_TXT) assert nwBuild._saveDocument(nwBuild.FMT_TXT)
assert path.isfile(path.join(nwLipsum, "Lorem Ipsum.odt")) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.odt"))
assert path.isfile(path.join(nwLipsum, "Lorem Ipsum.pdf")) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.pdf"))
assert path.isfile(path.join(nwLipsum, "Lorem Ipsum.md")) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.md"))
assert path.isfile(path.join(nwLipsum, "Lorem Ipsum.txt")) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.txt"))
# Close the build tool # Close the build tool
htmlText = nwBuild.htmlText htmlText = nwBuild.htmlText
@@ -581,9 +580,9 @@ def testMergeSplitTools(qtbot, monkeypatch, yesToAll, nwTempGUI, nwLipsum, nwRef
assert nwGUI.theProject.projTree["73475cb40a568"] is not None assert nwGUI.theProject.projTree["73475cb40a568"] is not None
projFile = path.join(nwLipsum, "content", "73475cb40a568.nwd") projFile = os.path.join(nwLipsum, "content", "73475cb40a568.nwd")
testFile = path.join(nwTempGUI, "4_73475cb40a568.nwd") testFile = os.path.join(nwTempGUI, "4_73475cb40a568.nwd")
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd") refFile = os.path.join(nwRef, "gui", "4_73475cb40a568.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
@@ -607,9 +606,9 @@ def testMergeSplitTools(qtbot, monkeypatch, yesToAll, nwTempGUI, nwLipsum, nwRef
assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None
# This should give us back the file as it was before # This should give us back the file as it was before
projFile = path.join(nwLipsum, "content", "71ee45a3c0db9.nwd") projFile = os.path.join(nwLipsum, "content", "71ee45a3c0db9.nwd")
testFile = path.join(nwTempGUI, "4_71ee45a3c0db9.nwd") testFile = os.path.join(nwTempGUI, "4_71ee45a3c0db9.nwd")
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd") refFile = os.path.join(nwRef, "gui", "4_73475cb40a568.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [1]) assert cmpFiles(testFile, refFile, [1])
@@ -627,21 +626,21 @@ def testMergeSplitTools(qtbot, monkeypatch, yesToAll, nwTempGUI, nwLipsum, nwRef
assert nwGUI.theProject.projTree["31489056e0916"] is not None assert nwGUI.theProject.projTree["31489056e0916"] is not None
assert nwGUI.theProject.projTree["98010bd9270f9"] is not None assert nwGUI.theProject.projTree["98010bd9270f9"] is not None
projFile = path.join(nwLipsum, "content", "25fc0e7096fc6.nwd") projFile = os.path.join(nwLipsum, "content", "25fc0e7096fc6.nwd")
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd") testFile = os.path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd") refFile = os.path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "content", "31489056e0916.nwd") projFile = os.path.join(nwLipsum, "content", "31489056e0916.nwd")
testFile = path.join(nwTempGUI, "5_31489056e0916.nwd") testFile = os.path.join(nwTempGUI, "5_31489056e0916.nwd")
refFile = path.join(nwRef, "gui", "5_31489056e0916.nwd") refFile = os.path.join(nwRef, "gui", "5_31489056e0916.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "content", "98010bd9270f9.nwd") projFile = os.path.join(nwLipsum, "content", "98010bd9270f9.nwd")
testFile = path.join(nwTempGUI, "5_98010bd9270f9.nwd") testFile = os.path.join(nwTempGUI, "5_98010bd9270f9.nwd")
refFile = path.join(nwRef, "gui", "5_98010bd9270f9.nwd") refFile = os.path.join(nwRef, "gui", "5_98010bd9270f9.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
@@ -661,33 +660,33 @@ def testMergeSplitTools(qtbot, monkeypatch, yesToAll, nwTempGUI, nwLipsum, nwRef
assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None
assert nwGUI.theProject.projTree["2fca346db6561"] is not None assert nwGUI.theProject.projTree["2fca346db6561"] is not None
projFile = path.join(nwLipsum, "content", "1a6562590ef19.nwd") projFile = os.path.join(nwLipsum, "content", "1a6562590ef19.nwd")
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd") testFile = os.path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd") refFile = os.path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [1]) assert cmpFiles(testFile, refFile, [1])
projFile = path.join(nwLipsum, "content", "031b4af5197ec.nwd") projFile = os.path.join(nwLipsum, "content", "031b4af5197ec.nwd")
testFile = path.join(nwTempGUI, "5_031b4af5197ec.nwd") testFile = os.path.join(nwTempGUI, "5_031b4af5197ec.nwd")
refFile = path.join(nwRef, "gui", "5_031b4af5197ec.nwd") refFile = os.path.join(nwRef, "gui", "5_031b4af5197ec.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd") projFile = os.path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd")
testFile = path.join(nwTempGUI, "5_41cfc0d1f2d12.nwd") testFile = os.path.join(nwTempGUI, "5_41cfc0d1f2d12.nwd")
refFile = path.join(nwRef, "gui", "5_41cfc0d1f2d12.nwd") refFile = os.path.join(nwRef, "gui", "5_41cfc0d1f2d12.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "content", "2858dcd1057d3.nwd") projFile = os.path.join(nwLipsum, "content", "2858dcd1057d3.nwd")
testFile = path.join(nwTempGUI, "5_2858dcd1057d3.nwd") testFile = os.path.join(nwTempGUI, "5_2858dcd1057d3.nwd")
refFile = path.join(nwRef, "gui", "5_2858dcd1057d3.nwd") refFile = os.path.join(nwRef, "gui", "5_2858dcd1057d3.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwLipsum, "content", "2fca346db6561.nwd") projFile = os.path.join(nwLipsum, "content", "2fca346db6561.nwd")
testFile = path.join(nwTempGUI, "5_2fca346db6561.nwd") testFile = os.path.join(nwTempGUI, "5_2fca346db6561.nwd")
refFile = path.join(nwRef, "gui", "5_2fca346db6561.nwd") refFile = os.path.join(nwRef, "gui", "5_2fca346db6561.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
@@ -795,7 +794,7 @@ def testNewProjectWizard(qtbot, monkeypatch, yesToAll, nwMinimal, nwTemp):
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100) qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
projPath = path.join(nwMinimal, "Test Minimal") projPath = os.path.join(nwMinimal, "Test Minimal")
assert storagePage.projPath.text() == projPath assert storagePage.projPath.text() == projPath
# Setting projPath should activate the button # Setting projPath should activate the button
@@ -939,7 +938,7 @@ def testLoadProject(qtbot, monkeypatch, yesToAll, nwMinimal, nwTemp):
nwLoad._keyPressDelete() nwLoad._keyPressDelete()
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1 assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
getFile = path.join(nwMinimal, "nwProject.nwx") getFile = os.path.join(nwMinimal, "nwProject.nwx")
monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwargs: (getFile, None)) monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwargs: (getFile, None))
qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton) qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton)
assert nwLoad.openPath == nwMinimal assert nwLoad.openPath == nwMinimal
@@ -1109,9 +1108,9 @@ def testPreferences(qtbot, monkeypatch, yesToAll, nwMinimal, nwTemp, nwRef, tmpC
# qtbot.stopForInteraction() # qtbot.stopForInteraction()
nwGUI.closeMain() nwGUI.closeMain()
refConf = path.join(nwRef, "novelwriter_prefs.conf") refConf = os.path.join(nwRef, "novelwriter_prefs.conf")
projConf = path.join(nwGUI.mainConf.confPath, "novelwriter.conf") projConf = os.path.join(nwGUI.mainConf.confPath, "novelwriter.conf")
testConf = path.join(nwTemp, "novelwriter_prefs.conf") testConf = os.path.join(nwTemp, "novelwriter_prefs.conf")
copyfile(projConf, testConf) copyfile(projConf, testConf)
ignoreLines = [ ignoreLines = [
2, # Timestamp 2, # Timestamp
+31 -31
View File
@@ -5,11 +5,11 @@
import nw import nw
import pytest import pytest
import logging import logging
import os
from shutil import copyfile from shutil import copyfile
from nwtools import cmpFiles from nwtools import cmpFiles
from os import path
from PyQt5.QtCore import Qt, QUrl, QPoint, QItemSelectionModel from PyQt5.QtCore import Qt, QUrl, QPoint, QItemSelectionModel
from PyQt5.QtGui import QTextCursor, QColor, QPixmap, QIcon from PyQt5.QtGui import QTextCursor, QColor, QPixmap, QIcon
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
@@ -57,19 +57,19 @@ def testLaunch(qtbot, nwFuncTemp, nwTemp):
nwGUI.close() nwGUI.close()
# Log file # Log file
logFile = path.join(nwTemp, "logFile.log") logFile = os.path.join(nwTemp, "logFile.log")
bakFile = path.join(nwTemp, "logFile.log.bak") bakFile = os.path.join(nwTemp, "logFile.log.bak")
nwGUI = nw.main( nwGUI = nw.main(
["--testmode", "--logfile=%s" % logFile, "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp] ["--testmode", "--logfile=%s" % logFile, "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp]
) )
assert path.isfile(logFile) assert os.path.isfile(logFile)
nwGUI = nw.main( nwGUI = nw.main(
["--testmode", "--logfile=%s" % logFile, "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp] ["--testmode", "--logfile=%s" % logFile, "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp]
) )
assert path.isfile(bakFile) assert os.path.isfile(bakFile)
assert path.isfile(logFile) assert os.path.isfile(logFile)
nwGUI.closeMain() nwGUI.closeMain()
nwGUI.close() nwGUI.close()
@@ -116,9 +116,9 @@ def testDocEditor(qtbot, yesToAll, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
assert not nwGUI.theProject.spellCheck assert not nwGUI.theProject.spellCheck
# Check the files # Check the files
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempGUI, "0_nwProject.nwx") testFile = os.path.join(nwTempGUI, "0_nwProject.nwx")
refFile = path.join(nwRef, "gui", "0_nwProject.nwx") refFile = os.path.join(nwRef, "gui", "0_nwProject.nwx")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
@@ -135,7 +135,7 @@ def testDocEditor(qtbot, yesToAll, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
assert len(nwGUI.theProject.projTree._treeRoots) == 4 assert len(nwGUI.theProject.projTree._treeRoots) == 4
assert nwGUI.theProject.projTree.trashRoot() is None assert nwGUI.theProject.projTree.trashRoot() is None
assert nwGUI.theProject.projPath == nwFuncTemp assert nwGUI.theProject.projPath == nwFuncTemp
assert nwGUI.theProject.projMeta == path.join(nwFuncTemp, "meta") assert nwGUI.theProject.projMeta == os.path.join(nwFuncTemp, "meta")
assert nwGUI.theProject.projFile == "nwProject.nwx" assert nwGUI.theProject.projFile == "nwProject.nwx"
assert nwGUI.theProject.projName == "New Project" assert nwGUI.theProject.projName == "New Project"
assert nwGUI.theProject.bookTitle == "" assert nwGUI.theProject.bookTitle == ""
@@ -358,33 +358,33 @@ def testDocEditor(qtbot, yesToAll, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
assert nwGUI.saveProject() assert nwGUI.saveProject()
# Check the files # Check the files
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempGUI, "1_nwProject.nwx") testFile = os.path.join(nwTempGUI, "1_nwProject.nwx")
refFile = path.join(nwRef, "gui", "1_nwProject.nwx") refFile = os.path.join(nwRef, "gui", "1_nwProject.nwx")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
projFile = path.join(nwFuncTemp, "content", "031b4af5197ec.nwd") projFile = os.path.join(nwFuncTemp, "content", "031b4af5197ec.nwd")
testFile = path.join(nwTempGUI, "1_031b4af5197ec.nwd") testFile = os.path.join(nwTempGUI, "1_031b4af5197ec.nwd")
refFile = path.join(nwRef, "gui", "1_031b4af5197ec.nwd") refFile = os.path.join(nwRef, "gui", "1_031b4af5197ec.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwFuncTemp, "content", "1a6562590ef19.nwd") projFile = os.path.join(nwFuncTemp, "content", "1a6562590ef19.nwd")
testFile = path.join(nwTempGUI, "1_1a6562590ef19.nwd") testFile = os.path.join(nwTempGUI, "1_1a6562590ef19.nwd")
refFile = path.join(nwRef, "gui", "1_1a6562590ef19.nwd") refFile = os.path.join(nwRef, "gui", "1_1a6562590ef19.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwFuncTemp, "content", "0e17daca5f3e1.nwd") projFile = os.path.join(nwFuncTemp, "content", "0e17daca5f3e1.nwd")
testFile = path.join(nwTempGUI, "1_0e17daca5f3e1.nwd") testFile = os.path.join(nwTempGUI, "1_0e17daca5f3e1.nwd")
refFile = path.join(nwRef, "gui", "1_0e17daca5f3e1.nwd") refFile = os.path.join(nwRef, "gui", "1_0e17daca5f3e1.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
projFile = path.join(nwFuncTemp, "content", "41cfc0d1f2d12.nwd") projFile = os.path.join(nwFuncTemp, "content", "41cfc0d1f2d12.nwd")
testFile = path.join(nwTempGUI, "1_41cfc0d1f2d12.nwd") testFile = os.path.join(nwTempGUI, "1_41cfc0d1f2d12.nwd")
refFile = path.join(nwRef, "gui", "1_41cfc0d1f2d12.nwd") refFile = os.path.join(nwRef, "gui", "1_41cfc0d1f2d12.nwd")
copyfile(projFile, testFile) copyfile(projFile, testFile)
assert cmpFiles(testFile, refFile) assert cmpFiles(testFile, refFile)
@@ -625,7 +625,7 @@ def testProjectTree(qtbot, yesToAll, nwMinimal, nwTemp):
nwGUI.openDocument("73475cb40a568") nwGUI.openDocument("73475cb40a568")
nwGUI.docEditor.setText("# Hello World\n") nwGUI.docEditor.setText("# Hello World\n")
nwGUI.saveDocument() nwGUI.saveDocument()
assert path.isfile(path.join(nwMinimal, "content", "73475cb40a568.nwd")) assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
# Delete the items we added earlier # Delete the items we added earlier
nwTree.clearSelection() nwTree.clearSelection()
@@ -640,17 +640,17 @@ def testProjectTree(qtbot, yesToAll, nwMinimal, nwTemp):
assert "71ee45a3c0db9" not in nwGUI.theProject.projTree._treeOrder assert "71ee45a3c0db9" not in nwGUI.theProject.projTree._treeOrder
# The file is in trash, empty it # The file is in trash, empty it
assert path.isfile(path.join(nwMinimal, "content", "73475cb40a568.nwd")) assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
assert nwTree.emptyTrash() assert nwTree.emptyTrash()
assert not nwTree.emptyTrash() # Already empty assert not nwTree.emptyTrash() # Already empty
assert not path.isfile(path.join(nwMinimal, "content", "73475cb40a568.nwd")) assert not os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
assert "73475cb40a568" not in nwGUI.theProject.projTree._treeOrder assert "73475cb40a568" not in nwGUI.theProject.projTree._treeOrder
# Close the project # Close the project
nwGUI.closeProject() nwGUI.closeProject()
# Add an orphaned file # Add an orphaned file
orphFile = path.join(nwMinimal, "content", "1234567890abc.nwd") orphFile = os.path.join(nwMinimal, "content", "1234567890abc.nwd")
with open(orphFile, mode="w+", encoding="utf8") as outFile: with open(orphFile, mode="w+", encoding="utf8") as outFile:
outFile.write("# Hello World\n") outFile.write("# Hello World\n")
@@ -1102,7 +1102,7 @@ def testInsertMenu(qtbot, monkeypatch, nwFuncTemp, nwTemp):
assert not nwGUI.importDocument() assert not nwGUI.importDocument()
# Then a valid path, but bot a file that exists # Then a valid path, but bot a file that exists
theFile = path.join(nwTemp, "import.txt") theFile = os.path.join(nwTemp, "import.txt")
monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwards: [theFile]) monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwards: [theFile])
assert not nwGUI.importDocument() assert not nwGUI.importDocument()
@@ -1145,7 +1145,7 @@ def testInsertMenu(qtbot, monkeypatch, nwFuncTemp, nwTemp):
assert len(theBits) == 3 assert len(theBits) == 3
assert theBits[0] == "File details for the currently open file" assert theBits[0] == "File details for the currently open file"
assert theBits[1] == "Handle: 0e17daca5f3e1" assert theBits[1] == "Handle: 0e17daca5f3e1"
assert theBits[2] == "Location: %s" % path.join(nwFuncTemp, "content", "0e17daca5f3e1.nwd") assert theBits[2] == "Location: %s" % os.path.join(nwFuncTemp, "content", "0e17daca5f3e1.nwd")
# qtbot.stopForInteraction() # qtbot.stopForInteraction()
nwGUI.closeMain() nwGUI.closeMain()
+170 -81
View File
@@ -3,7 +3,8 @@
""" """
import pytest import pytest
from os import path, mkdir, listdir import os
from shutil import copyfile from shutil import copyfile
from zipfile import ZipFile from zipfile import ZipFile
@@ -18,9 +19,9 @@ from nw.constants import nwItemClass, nwItemType, nwItemLayout, nwFiles
def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy): def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy):
"""Test that a basic project can be created, and opened and saved. """Test that a basic project can be created, and opened and saved.
""" """
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempProj, "1_nwProject.nwx") testFile = os.path.join(nwTempProj, "1_nwProject.nwx")
refFile = path.join(nwRef, "proj", "1_nwProject.nwx") refFile = os.path.join(nwRef, "proj", "1_nwProject.nwx")
theProject = NWProject(nwDummy) theProject = NWProject(nwDummy)
theProject.projTree.setSeed(42) theProject.projTree.setSeed(42)
@@ -64,9 +65,9 @@ def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy):
def testProjectNewRoot(nwFuncTemp, nwTempProj, nwRef, nwDummy): def testProjectNewRoot(nwFuncTemp, nwTempProj, nwRef, nwDummy):
"""Check that new root folders can be added to the project. """Check that new root folders can be added to the project.
""" """
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempProj, "2_nwProject.nwx") testFile = os.path.join(nwTempProj, "2_nwProject.nwx")
refFile = path.join(nwRef, "proj", "2_nwProject.nwx") refFile = os.path.join(nwRef, "proj", "2_nwProject.nwx")
theProject = NWProject(nwDummy) theProject = NWProject(nwDummy)
theProject.projTree.setSeed(42) theProject.projTree.setSeed(42)
@@ -98,9 +99,9 @@ def testProjectNewRoot(nwFuncTemp, nwTempProj, nwRef, nwDummy):
def testProjectNewFile(nwFuncTemp, nwTempProj, nwRef, nwDummy): def testProjectNewFile(nwFuncTemp, nwTempProj, nwRef, nwDummy):
"""Check that new files can be added to the project. """Check that new files can be added to the project.
""" """
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempProj, "3_nwProject.nwx") testFile = os.path.join(nwTempProj, "3_nwProject.nwx")
refFile = path.join(nwRef, "proj", "3_nwProject.nwx") refFile = os.path.join(nwRef, "proj", "3_nwProject.nwx")
theProject = NWProject(nwDummy) theProject = NWProject(nwDummy)
theProject.projTree.setSeed(42) theProject.projTree.setSeed(42)
@@ -126,9 +127,9 @@ def testProjectNewCustomA(nwFuncTemp, nwTempProj, nwRef, nwDummy):
"""Create a new project from a project wizard dictionary. """Create a new project from a project wizard dictionary.
Custom type with chapters and scenes. Custom type with chapters and scenes.
""" """
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempProj, "4_nwProject.nwx") testFile = os.path.join(nwTempProj, "4_nwProject.nwx")
refFile = path.join(nwRef, "proj", "4_nwProject.nwx") refFile = os.path.join(nwRef, "proj", "4_nwProject.nwx")
projData = { projData = {
"projName": "Test Custom", "projName": "Test Custom",
@@ -165,9 +166,9 @@ def testProjectNewCustomB(nwFuncTemp, nwTempProj, nwRef, nwDummy):
"""Create a new project from a project wizard dictionary. """Create a new project from a project wizard dictionary.
Custom type without chapters, but with scenes. Custom type without chapters, but with scenes.
""" """
projFile = path.join(nwFuncTemp, "nwProject.nwx") projFile = os.path.join(nwFuncTemp, "nwProject.nwx")
testFile = path.join(nwTempProj, "5_nwProject.nwx") testFile = os.path.join(nwTempProj, "5_nwProject.nwx")
refFile = path.join(nwRef, "proj", "5_nwProject.nwx") refFile = os.path.join(nwRef, "proj", "5_nwProject.nwx")
projData = { projData = {
"projName": "Test Custom", "projName": "Test Custom",
@@ -200,9 +201,9 @@ def testProjectNewCustomB(nwFuncTemp, nwTempProj, nwRef, nwDummy):
assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
@pytest.mark.project @pytest.mark.project
def testProjectNewSample(nwFuncTemp, nwRef, nwConf, nwDummy): def testProjectNewSampleA(nwFuncTemp, nwConf, nwDummy, nwTemp):
"""Check that we can create a new project can be created from the """Check that we can create a new project can be created from the
provided sample project. provided sample project via a zip file.
""" """
projData = { projData = {
"projName": "Test Sample", "projName": "Test Sample",
@@ -217,11 +218,99 @@ def testProjectNewSample(nwFuncTemp, nwRef, nwConf, nwDummy):
theProject.projTree.setSeed(42) theProject.projTree.setSeed(42)
theProject.mainConf = nwConf theProject.mainConf = nwConf
# Sample set, but no path
assert not theProject.newProject({"popSample": True})
# Force the lookup path for assets to our temp folder
srcSample = os.path.abspath(os.path.join(nwConf.appRoot, "sample"))
dstSample = os.path.join(nwTemp, "sample.zip")
nwConf.assetPath = nwTemp
# Create and open a defective zip file
with open(dstSample, mode="w+") as outFile:
outFile.write("foo")
assert not theProject.newProject(projData)
os.unlink(dstSample)
# Create a real zip file, and unpack it
with ZipFile(dstSample, "w") as zipObj:
zipObj.write(os.path.join(srcSample, "nwProject.nwx"), "nwProject.nwx")
for docFile in os.listdir(os.path.join(srcSample, "content")):
srcDoc = os.path.join(srcSample, "content", docFile)
zipObj.write(srcDoc, "content/"+docFile)
assert theProject.newProject(projData) assert theProject.newProject(projData)
assert theProject.openProject(nwFuncTemp) assert theProject.openProject(nwFuncTemp)
assert theProject.projName == "Sample Project" assert theProject.projName == "Sample Project"
assert theProject.saveProject() assert theProject.saveProject()
assert theProject.closeProject() assert theProject.closeProject()
os.unlink(dstSample)
@pytest.mark.project
def testProjectNewSampleB(monkeypatch, nwFuncTemp, nwConf, nwDummy, nwTemp):
"""Check that we can create a new project can be created from the
provided sample project folder.
"""
projData = {
"projName": "Test Sample",
"projTitle": "Test Novel",
"projAuthors": "Jane Doe\nJohn Doh\n",
"projPath": nwFuncTemp,
"popSample": True,
"popMinimal": False,
"popCustom": False,
}
theProject = NWProject(nwDummy)
theProject.projTree.setSeed(42)
theProject.mainConf = nwConf
# Make sure we do not pick up the nw/assets/sample.zip file
nwConf.assetPath = nwTemp
# Set a fake project file name
monkeypatch.setattr(nwFiles, "PROJ_FILE", "nothing.nwx")
assert not theProject.newProject(projData)
monkeypatch.setattr(nwFiles, "PROJ_FILE", "nwProject.nwx")
assert theProject.newProject(projData)
assert theProject.openProject(nwFuncTemp)
assert theProject.projName == "Sample Project"
assert theProject.saveProject()
assert theProject.closeProject()
# Misdirect the appRoot path so neither is possible
nwConf.appRoot = nwTemp
assert not theProject.newProject(projData)
@pytest.mark.project
def testProjectMethods(monkeypatch, nwMinimal, nwDummy):
"""Test other project class methods and functions.
"""
theProject = NWProject(nwDummy)
theProject.projTree.setSeed(42)
assert theProject.openProject(nwMinimal)
assert theProject.projPath == nwMinimal
# Setting project path
assert theProject.setProjectPath(None)
assert theProject.projPath is None
assert theProject.setProjectPath("")
assert theProject.projPath is None
assert theProject.setProjectPath("~")
assert theProject.projPath == os.path.expanduser("~")
# Create a new folder and populate it
projPath = os.path.join(nwMinimal, "dummy1")
assert theProject.setProjectPath(projPath, newProject=True)
# Make the os.mkdir fail
def altMkdir(*args):
raise Exception("Oops!")
monkeypatch.setattr("os.mkdir", altMkdir)
projPath = os.path.join(nwMinimal, "dummy2")
assert not theProject.setProjectPath(projPath, newProject=True)
@pytest.mark.project @pytest.mark.project
def testDocMeta(nwDummy, nwLipsum): def testDocMeta(nwDummy, nwLipsum):
@@ -252,7 +341,7 @@ def testDocMeta(nwDummy, nwLipsum):
@pytest.mark.project @pytest.mark.project
def testSpellEnchant(nwTemp, nwConf): def testSpellEnchant(nwTemp, nwConf):
wList = path.join(nwTemp, "wordlist.txt") wList = os.path.join(nwTemp, "wordlist.txt")
with open(wList, mode="w") as wFile: with open(wList, mode="w") as wFile:
wFile.write("a_word\nb_word\nc_word\n") wFile.write("a_word\nb_word\nc_word\n")
@@ -277,7 +366,7 @@ def testSpellEnchant(nwTemp, nwConf):
@pytest.mark.project @pytest.mark.project
def testSpellSimple(nwTemp, nwConf): def testSpellSimple(nwTemp, nwConf):
wList = path.join(nwTemp, "wordlist.txt") wList = os.path.join(nwTemp, "wordlist.txt")
with open(wList, mode="w") as wFile: with open(wList, mode="w") as wFile:
wFile.write("a_word\nb_word\nc_word\n") wFile.write("a_word\nb_word\nc_word\n")
@@ -320,7 +409,7 @@ def testProjectOptions(nwDummy, nwLipsum):
assert str(theOpts.theState) == r"{}" assert str(theOpts.theState) == r"{}"
# Read Invalid Settings and Filter # Read Invalid Settings and Filter
stateFile = path.join(theProject.projMeta, nwFiles.OPTS_FILE) stateFile = os.path.join(theProject.projMeta, nwFiles.OPTS_FILE)
with open(stateFile, mode="w", encoding="utf8") as outFile: with open(stateFile, mode="w", encoding="utf8") as outFile:
outFile.write( outFile.write(
r'{"GuiProjectSettings": {"winWidth": 100, "winHeight": 50}, "NoGroup": {"NoName": 0}}' r'{"GuiProjectSettings": {"winWidth": 100, "winHeight": 50}, "NoGroup": {"NoName": 0}}'
@@ -376,28 +465,28 @@ def testProjectOrphanedFiles(nwDummy, nwLipsum):
assert theProject.closeProject() assert theProject.closeProject()
# First Item with Meta Data # First Item with Meta Data
orphPath = path.join(nwLipsum, "content", "636b6aa9b697b.nwd") orphPath = os.path.join(nwLipsum, "content", "636b6aa9b697b.nwd")
with open(orphPath, mode="w", encoding="utf8") as outFile: with open(orphPath, mode="w", encoding="utf8") as outFile:
outFile.write(r"%%~ 5eaea4e8cdee8:15c4492bd5107:WORLD:NOTE:Mars") outFile.write(r"%%~ 5eaea4e8cdee8:15c4492bd5107:WORLD:NOTE:Mars")
outFile.write("\n") outFile.write("\n")
# Second Item without Meta Data # Second Item without Meta Data
orphPath = path.join(nwLipsum, "content", "736b6aa9b697b.nwd") orphPath = os.path.join(nwLipsum, "content", "736b6aa9b697b.nwd")
with open(orphPath, mode="w", encoding="utf8") as outFile: with open(orphPath, mode="w", encoding="utf8") as outFile:
outFile.write("\n") outFile.write("\n")
# Invalid File Name # Invalid File Name
dummyPath = path.join(nwLipsum, "content", "636b6aa9b697b.txt") dummyPath = os.path.join(nwLipsum, "content", "636b6aa9b697b.txt")
with open(dummyPath, mode="w", encoding="utf8") as outFile: with open(dummyPath, mode="w", encoding="utf8") as outFile:
outFile.write("\n") outFile.write("\n")
# Invalid File Name # Invalid File Name
dummyPath = path.join(nwLipsum, "content", "636b6aa9b697bb.nwd") dummyPath = os.path.join(nwLipsum, "content", "636b6aa9b697bb.nwd")
with open(dummyPath, mode="w", encoding="utf8") as outFile: with open(dummyPath, mode="w", encoding="utf8") as outFile:
outFile.write("\n") outFile.write("\n")
# Invalid File Name # Invalid File Name
dummyPath = path.join(nwLipsum, "content", "abcdefghijklm.nwd") dummyPath = os.path.join(nwLipsum, "content", "abcdefghijklm.nwd")
with open(dummyPath, mode="w", encoding="utf8") as outFile: with open(dummyPath, mode="w", encoding="utf8") as outFile:
outFile.write("\n") outFile.write("\n")
@@ -441,84 +530,84 @@ def testProjectOldFormat(nwDummy, nwOldProj):
# Create dummy files for known legacy files # Create dummy files for known legacy files
deleteFiles = [ deleteFiles = [
path.join(nwOldProj, "cache", "nwProject.nwx.0"), os.path.join(nwOldProj, "cache", "nwProject.nwx.0"),
path.join(nwOldProj, "cache", "nwProject.nwx.1"), os.path.join(nwOldProj, "cache", "nwProject.nwx.1"),
path.join(nwOldProj, "cache", "nwProject.nwx.2"), os.path.join(nwOldProj, "cache", "nwProject.nwx.2"),
path.join(nwOldProj, "cache", "nwProject.nwx.3"), os.path.join(nwOldProj, "cache", "nwProject.nwx.3"),
path.join(nwOldProj, "cache", "nwProject.nwx.4"), os.path.join(nwOldProj, "cache", "nwProject.nwx.4"),
path.join(nwOldProj, "cache", "nwProject.nwx.5"), os.path.join(nwOldProj, "cache", "nwProject.nwx.5"),
path.join(nwOldProj, "cache", "nwProject.nwx.6"), os.path.join(nwOldProj, "cache", "nwProject.nwx.6"),
path.join(nwOldProj, "cache", "nwProject.nwx.7"), os.path.join(nwOldProj, "cache", "nwProject.nwx.7"),
path.join(nwOldProj, "cache", "nwProject.nwx.8"), os.path.join(nwOldProj, "cache", "nwProject.nwx.8"),
path.join(nwOldProj, "cache", "nwProject.nwx.9"), os.path.join(nwOldProj, "cache", "nwProject.nwx.9"),
path.join(nwOldProj, "meta", "mainOptions.json"), os.path.join(nwOldProj, "meta", "mainOptions.json"),
path.join(nwOldProj, "meta", "exportOptions.json"), os.path.join(nwOldProj, "meta", "exportOptions.json"),
path.join(nwOldProj, "meta", "outlineOptions.json"), os.path.join(nwOldProj, "meta", "outlineOptions.json"),
path.join(nwOldProj, "meta", "timelineOptions.json"), os.path.join(nwOldProj, "meta", "timelineOptions.json"),
path.join(nwOldProj, "meta", "docMergeOptions.json"), os.path.join(nwOldProj, "meta", "docMergeOptions.json"),
path.join(nwOldProj, "meta", "sessionLogOptions.json"), os.path.join(nwOldProj, "meta", "sessionLogOptions.json"),
] ]
# Add some files that shouldn't be there # Add some files that shouldn't be there
deleteFiles.append(path.join(nwOldProj, "data_f", "whatnow.nwd")) deleteFiles.append(os.path.join(nwOldProj, "data_f", "whatnow.nwd"))
deleteFiles.append(path.join(nwOldProj, "data_f", "whatnow.txt")) deleteFiles.append(os.path.join(nwOldProj, "data_f", "whatnow.txt"))
# Add some folders that shouldn't be there # Add some folders that shouldn't be there
mkdir(path.join(nwOldProj, "stuff")) os.mkdir(os.path.join(nwOldProj, "stuff"))
mkdir(path.join(nwOldProj, "data_1", "stuff")) os.mkdir(os.path.join(nwOldProj, "data_1", "stuff"))
# Create dummy files # Create dummy files
mkdir(path.join(nwOldProj, "cache")) os.mkdir(os.path.join(nwOldProj, "cache"))
for aFile in deleteFiles: for aFile in deleteFiles:
with open(aFile, mode="w+", encoding="utf8") as outFile: with open(aFile, mode="w+", encoding="utf8") as outFile:
outFile.write("Hi") outFile.write("Hi")
for aFile in deleteFiles: for aFile in deleteFiles:
assert path.isfile(aFile) assert os.path.isfile(aFile)
# Open project and check that files that are not supposed to be # Open project and check that files that are not supposed to be
# there have been removed # there have been removed
assert theProject.openProject(nwOldProj) assert theProject.openProject(nwOldProj)
for aFile in deleteFiles: for aFile in deleteFiles:
assert not path.isfile(aFile) assert not os.path.isfile(aFile)
assert not path.isdir(path.join(nwOldProj, "data_1", "stuff")) assert not os.path.isdir(os.path.join(nwOldProj, "data_1", "stuff"))
assert not path.isdir(path.join(nwOldProj, "data_1")) assert not os.path.isdir(os.path.join(nwOldProj, "data_1"))
assert not path.isdir(path.join(nwOldProj, "data_7")) assert not os.path.isdir(os.path.join(nwOldProj, "data_7"))
assert not path.isdir(path.join(nwOldProj, "data_8")) assert not os.path.isdir(os.path.join(nwOldProj, "data_8"))
assert not path.isdir(path.join(nwOldProj, "data_9")) assert not os.path.isdir(os.path.join(nwOldProj, "data_9"))
assert not path.isdir(path.join(nwOldProj, "data_a")) assert not os.path.isdir(os.path.join(nwOldProj, "data_a"))
assert not path.isdir(path.join(nwOldProj, "data_f")) assert not os.path.isdir(os.path.join(nwOldProj, "data_f"))
# Check stuff that has been moved # Check stuff that has been moved
assert path.isdir(path.join(nwOldProj, "junk")) assert os.path.isdir(os.path.join(nwOldProj, "junk"))
assert path.isdir(path.join(nwOldProj, "junk", "stuff")) assert os.path.isdir(os.path.join(nwOldProj, "junk", "stuff"))
assert path.isfile(path.join(nwOldProj, "junk", "whatnow.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "junk", "whatnow.nwd"))
assert path.isfile(path.join(nwOldProj, "junk", "whatnow.txt")) assert os.path.isfile(os.path.join(nwOldProj, "junk", "whatnow.txt"))
# Check that files we want to keep are in the right place # Check that files we want to keep are in the right place
assert path.isdir(path.join(nwOldProj, "cache")) assert os.path.isdir(os.path.join(nwOldProj, "cache"))
assert path.isdir(path.join(nwOldProj, "content")) assert os.path.isdir(os.path.join(nwOldProj, "content"))
assert path.isdir(path.join(nwOldProj, "meta")) assert os.path.isdir(os.path.join(nwOldProj, "meta"))
assert path.isfile(path.join(nwOldProj, "content", "f528d831f5b24.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "f528d831f5b24.nwd"))
assert path.isfile(path.join(nwOldProj, "content", "88124a4292d8b.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "88124a4292d8b.nwd"))
assert path.isfile(path.join(nwOldProj, "content", "91239bf2f8b69.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "91239bf2f8b69.nwd"))
assert path.isfile(path.join(nwOldProj, "content", "19752e7f9d8af.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "19752e7f9d8af.nwd"))
assert path.isfile(path.join(nwOldProj, "content", "a764d5acf5a21.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "a764d5acf5a21.nwd"))
assert path.isfile(path.join(nwOldProj, "content", "9058ae29f0dfd.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "9058ae29f0dfd.nwd"))
assert path.isfile(path.join(nwOldProj, "content", "7ff63b8afc4cd.nwd")) assert os.path.isfile(os.path.join(nwOldProj, "content", "7ff63b8afc4cd.nwd"))
assert path.isfile(path.join(nwOldProj, "meta", "tagsIndex.json")) assert os.path.isfile(os.path.join(nwOldProj, "meta", "tagsIndex.json"))
assert path.isfile(path.join(nwOldProj, "meta", "sessionInfo.log")) assert os.path.isfile(os.path.join(nwOldProj, "meta", "sessionInfo.log"))
# Close the project # Close the project
theProject.closeProject() theProject.closeProject()
# Check that new files have been created # Check that new files have been created
assert path.isfile(path.join(nwOldProj, "meta", "guiOptions.json")) assert os.path.isfile(os.path.join(nwOldProj, "meta", "guiOptions.json"))
assert path.isfile(path.join(nwOldProj, "meta", "sessionStats.log")) assert os.path.isfile(os.path.join(nwOldProj, "meta", "sessionStats.log"))
assert path.isfile(path.join(nwOldProj, "ToC.json")) assert os.path.isfile(os.path.join(nwOldProj, "ToC.json"))
assert path.isfile(path.join(nwOldProj, "ToC.txt")) assert os.path.isfile(os.path.join(nwOldProj, "ToC.txt"))
@pytest.mark.project @pytest.mark.project
def testProjectBackup(nwDummy, nwMinimal, nwTemp): def testProjectBackup(nwDummy, nwMinimal, nwTemp):
@@ -541,7 +630,7 @@ def testProjectBackup(nwDummy, nwMinimal, nwTemp):
assert not theProject.zipIt(doNotify=False) assert not theProject.zipIt(doNotify=False)
# Non-existent folder # Non-existent folder
theProject.mainConf.backupPath = path.join(nwTemp, "nonexistent") theProject.mainConf.backupPath = os.path.join(nwTemp, "nonexistent")
theProject.projName = "Test Minimal" theProject.projName = "Test Minimal"
assert not theProject.zipIt(doNotify=False) assert not theProject.zipIt(doNotify=False)
@@ -553,7 +642,7 @@ def testProjectBackup(nwDummy, nwMinimal, nwTemp):
theProject.mainConf.backupPath = nwTemp theProject.mainConf.backupPath = nwTemp
assert theProject.zipIt(doNotify=False) assert theProject.zipIt(doNotify=False)
theFiles = listdir(path.join(nwTemp, "Test Minimal")) theFiles = os.listdir(os.path.join(nwTemp, "Test Minimal"))
assert len(theFiles) == 1 assert len(theFiles) == 1
theZip = theFiles[0] theZip = theFiles[0]
@@ -561,10 +650,10 @@ def testProjectBackup(nwDummy, nwMinimal, nwTemp):
assert theZip[-4:] == ".zip" assert theZip[-4:] == ".zip"
# Extract the archive # Extract the archive
with ZipFile(path.join(nwTemp, "Test Minimal", theZip), "r") as inZip: with ZipFile(os.path.join(nwTemp, "Test Minimal", theZip), "r") as inZip:
inZip.extractall(path.join(nwTemp, "extract")) inZip.extractall(os.path.join(nwTemp, "extract"))
# Check that the main project file was restored # Check that the main project file was restored
assert cmpFiles( assert cmpFiles(
path.join(nwMinimal, "nwProject.nwx"), path.join(nwTemp, "extract", "nwProject.nwx") os.path.join(nwMinimal, "nwProject.nwx"), os.path.join(nwTemp, "extract", "nwProject.nwx")
) )