Update the project storage class
This commit is contained in:
@@ -84,7 +84,6 @@ class nwFiles:
|
|||||||
INDEX_FILE = "tagsIndex.json"
|
INDEX_FILE = "tagsIndex.json"
|
||||||
OPTS_FILE = "guiOptions.json"
|
OPTS_FILE = "guiOptions.json"
|
||||||
RECENT_FILE = "recentProjects.json"
|
RECENT_FILE = "recentProjects.json"
|
||||||
BUILD_CACHE = "prevBuild.json"
|
|
||||||
BUILDS_FILE = "builds.json"
|
BUILDS_FILE = "builds.json"
|
||||||
|
|
||||||
# END Class nwFiles
|
# END Class nwFiles
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ from novelwriter.common import (
|
|||||||
)
|
)
|
||||||
from novelwriter.constants import nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
from novelwriter.core.status import NWStatus
|
from novelwriter.core.status import NWStatus
|
||||||
from novelwriter.core.projectdata import NWProjectData
|
from novelwriter.core.projectdata import NWProjectData
|
||||||
|
|
||||||
|
|||||||
+53
-64
@@ -1,7 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
novelWriter – Project Storage Class
|
novelWriter – Project Storage Class
|
||||||
===================================
|
===================================
|
||||||
The main class handling the project storage
|
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2022-11-01 [2.0rc2] NWStorage
|
Created: 2022-11-01 [2.0rc2] NWStorage
|
||||||
@@ -22,10 +21,12 @@ General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
||||||
|
|
||||||
@@ -36,29 +37,32 @@ from novelwriter.constants import nwFiles
|
|||||||
from novelwriter.core.document import NWDocument
|
from novelwriter.core.document import NWDocument
|
||||||
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter
|
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter
|
||||||
|
|
||||||
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
|
from novelwriter.core.project import NWProject
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NWStorage:
|
class NWStorage:
|
||||||
|
"""Core: Project Storage Class
|
||||||
|
|
||||||
|
The class that handles all paths related to the project storage.
|
||||||
|
"""
|
||||||
|
|
||||||
MODE_INACTIVE = 0
|
MODE_INACTIVE = 0
|
||||||
MODE_INPLACE = 1
|
MODE_INPLACE = 1
|
||||||
MODE_ARCHIVE = 2
|
MODE_ARCHIVE = 2
|
||||||
|
|
||||||
def __init__(self, theProject):
|
def __init__(self, project: NWProject):
|
||||||
|
self._project = project
|
||||||
self.theProject = theProject
|
|
||||||
|
|
||||||
self._storagePath = None
|
self._storagePath = None
|
||||||
self._runtimePath = None
|
self._runtimePath = None
|
||||||
self._lockFilePath = None
|
self._lockFilePath = None
|
||||||
self._openMode = self.MODE_INACTIVE
|
self._openMode = self.MODE_INACTIVE
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""Reset internal variables.
|
"""Reset internal variables."""
|
||||||
"""
|
|
||||||
self._storagePath = None
|
self._storagePath = None
|
||||||
self._runtimePath = None
|
self._runtimePath = None
|
||||||
self._openMode = self.MODE_INACTIVE
|
self._openMode = self.MODE_INACTIVE
|
||||||
@@ -69,15 +73,17 @@ class NWStorage:
|
|||||||
##
|
##
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def storagePath(self):
|
def storagePath(self) -> Path | None:
|
||||||
|
"""Get the path where the project is saved."""
|
||||||
return self._storagePath
|
return self._storagePath
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def runtimePath(self):
|
def runtimePath(self) -> Path | None:
|
||||||
|
"""Get the path where the project is saved at runtime."""
|
||||||
return self._runtimePath
|
return self._runtimePath
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def contentPath(self):
|
def contentPath(self) -> Path | None:
|
||||||
"""Return the path used for project content. The folder must
|
"""Return the path used for project content. The folder must
|
||||||
already exist, otherwise this property is None.
|
already exist, otherwise this property is None.
|
||||||
"""
|
"""
|
||||||
@@ -94,12 +100,11 @@ class NWStorage:
|
|||||||
# Core Methods
|
# Core Methods
|
||||||
##
|
##
|
||||||
|
|
||||||
def isOpen(self):
|
def isOpen(self) -> bool:
|
||||||
"""Check if the storage location is open.
|
"""Check if the storage location is open."""
|
||||||
"""
|
|
||||||
return self._runtimePath is not None
|
return self._runtimePath is not None
|
||||||
|
|
||||||
def openProjectInPlace(self, path, newProject=False):
|
def openProjectInPlace(self, path: str | Path, newProject: bool = False) -> bool:
|
||||||
"""Open a novelWriter project in-place. That is, it is opened
|
"""Open a novelWriter project in-place. That is, it is opened
|
||||||
directly from a project folder.
|
directly from a project folder.
|
||||||
"""
|
"""
|
||||||
@@ -124,13 +129,15 @@ class NWStorage:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def openProjectArchive(self, path): # pragma: no cover
|
def openProjectArchive(self, path: str | Path) -> bool: # pragma: no cover
|
||||||
"""Placeholder for later implementation. See #977.
|
"""Open the project from a single file.
|
||||||
|
Placeholder for later implementation. See #977.
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def runPostSaveTasks(self, autoSave=False): # pragma: no cover
|
def runPostSaveTasks(self, autoSave: bool = False) -> bool: # pragma: no cover
|
||||||
"""Run tasks after the project has been saved.
|
"""Run tasks after the project has been saved.
|
||||||
|
Placeholder for later implementation. See #977.
|
||||||
"""
|
"""
|
||||||
if self._openMode == self.MODE_INPLACE:
|
if self._openMode == self.MODE_INPLACE:
|
||||||
# Nothing to do, so we just return
|
# Nothing to do, so we just return
|
||||||
@@ -139,8 +146,7 @@ class NWStorage:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def closeSession(self):
|
def closeSession(self):
|
||||||
"""Run tasks related to closing the session.
|
"""Run tasks related to closing the session."""
|
||||||
"""
|
|
||||||
# Clear lockfile
|
# Clear lockfile
|
||||||
self.clear()
|
self.clear()
|
||||||
return
|
return
|
||||||
@@ -149,51 +155,35 @@ class NWStorage:
|
|||||||
# Content Access Methods
|
# Content Access Methods
|
||||||
##
|
##
|
||||||
|
|
||||||
def getXmlReader(self):
|
def getXmlReader(self) -> ProjectXMLReader | None:
|
||||||
"""Return a properly configured ProjectXMLReader instance.
|
"""Return a properly configured ProjectXMLReader instance."""
|
||||||
"""
|
|
||||||
if self._runtimePath is None:
|
if self._runtimePath is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
projFile = self._runtimePath / nwFiles.PROJ_FILE
|
projFile = self._runtimePath / nwFiles.PROJ_FILE
|
||||||
xmlReader = ProjectXMLReader(projFile)
|
xmlReader = ProjectXMLReader(projFile)
|
||||||
|
|
||||||
return xmlReader
|
return xmlReader
|
||||||
|
|
||||||
def getXmlWriter(self):
|
def getXmlWriter(self) -> ProjectXMLWriter | None:
|
||||||
"""Return a properly configured ProjectXMLWriter instance.
|
"""Return a properly configured ProjectXMLWriter instance."""
|
||||||
"""
|
|
||||||
if self._runtimePath is None:
|
if self._runtimePath is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
xmlWriter = ProjectXMLWriter(self._runtimePath)
|
xmlWriter = ProjectXMLWriter(self._runtimePath)
|
||||||
|
|
||||||
return xmlWriter
|
return xmlWriter
|
||||||
|
|
||||||
def getDocument(self, tHandle):
|
def getDocument(self, tHandle: str) -> NWDocument:
|
||||||
"""Return a document wrapper object.
|
"""Return a document wrapper object."""
|
||||||
"""
|
|
||||||
if self._runtimePath is not None:
|
if self._runtimePath is not None:
|
||||||
return NWDocument(self.theProject, tHandle)
|
return NWDocument(self._project, tHandle)
|
||||||
return NWDocument(self.theProject, None)
|
return NWDocument(self._project, None)
|
||||||
|
|
||||||
def getMetaFile(self, fileName):
|
def getMetaFile(self, fileName: str) -> Path | None:
|
||||||
"""Return the path to a file in the project meta folder.
|
"""Return the path to a file in the project meta folder."""
|
||||||
"""
|
|
||||||
if self._runtimePath is not None:
|
if self._runtimePath is not None:
|
||||||
return self._runtimePath / "meta" / fileName
|
return self._runtimePath / "meta" / fileName
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getCacheFile(self, fileName):
|
def readLockFile(self) -> list:
|
||||||
"""Return the path to a file in the project cache folder.
|
"""Read the project lock file."""
|
||||||
"""
|
|
||||||
if self._runtimePath is not None:
|
|
||||||
return self._runtimePath / "cache" / fileName
|
|
||||||
return None
|
|
||||||
|
|
||||||
def readLockFile(self):
|
|
||||||
"""Read the project lock file.
|
|
||||||
"""
|
|
||||||
if self._lockFilePath is None:
|
if self._lockFilePath is None:
|
||||||
return ["ERROR"]
|
return ["ERROR"]
|
||||||
|
|
||||||
@@ -212,9 +202,8 @@ class NWStorage:
|
|||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def writeLockFile(self):
|
def writeLockFile(self) -> bool:
|
||||||
"""Write the project lock file.
|
"""Write the project lock file."""
|
||||||
"""
|
|
||||||
if self._lockFilePath is None:
|
if self._lockFilePath is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -231,9 +220,8 @@ class NWStorage:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def clearLockFile(self):
|
def clearLockFile(self) -> bool:
|
||||||
"""Remove the lock file, if it exists.
|
"""Remove the lock file, if it exists."""
|
||||||
"""
|
|
||||||
if self._lockFilePath is None:
|
if self._lockFilePath is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -247,7 +235,7 @@ class NWStorage:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def zipIt(self, target, compression=None):
|
def zipIt(self, target: str | Path, compression: int | None = None) -> bool:
|
||||||
"""Zip the content of the project at its runtime location into a
|
"""Zip the content of the project at its runtime location into a
|
||||||
zip file. This process will only grab files that are supposed to
|
zip file. This process will only grab files that are supposed to
|
||||||
be in the project. All non-project files will be left out.
|
be in the project. All non-project files will be left out.
|
||||||
@@ -291,9 +279,8 @@ class NWStorage:
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _prepareStorage(self, checkLegacy=True, newProject=False):
|
def _prepareStorage(self, checkLegacy: bool = True, newProject: bool = False) -> bool:
|
||||||
"""Prepare the storage area for the project.
|
"""Prepare the storage area for the project."""
|
||||||
"""
|
|
||||||
path = self._runtimePath
|
path = self._runtimePath
|
||||||
if not isinstance(path, Path):
|
if not isinstance(path, Path):
|
||||||
logger.error("No path set")
|
logger.error("No path set")
|
||||||
@@ -318,7 +305,6 @@ class NWStorage:
|
|||||||
try:
|
try:
|
||||||
path.mkdir(exist_ok=True)
|
path.mkdir(exist_ok=True)
|
||||||
(path / "content").mkdir(exist_ok=True)
|
(path / "content").mkdir(exist_ok=True)
|
||||||
(path / "cache").mkdir(exist_ok=True)
|
|
||||||
(path / "meta").mkdir(exist_ok=True)
|
(path / "meta").mkdir(exist_ok=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error("Failed to create required project folders", exc_info=exc)
|
logger.error("Failed to create required project folders", exc_info=exc)
|
||||||
@@ -385,8 +371,7 @@ class NWStorage:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _deleteDeprecatedFiles(self, path: Path):
|
def _deleteDeprecatedFiles(self, path: Path):
|
||||||
"""Delete files that are no longer used by novelWriter.
|
"""Delete files that are no longer used by novelWriter."""
|
||||||
"""
|
|
||||||
remove = [
|
remove = [
|
||||||
path / "meta" / "mainOptions.json", # Replaced in 0.5
|
path / "meta" / "mainOptions.json", # Replaced in 0.5
|
||||||
path / "meta" / "exportOptions.json", # Replaced in 0.5
|
path / "meta" / "exportOptions.json", # Replaced in 0.5
|
||||||
@@ -394,16 +379,20 @@ class NWStorage:
|
|||||||
path / "meta" / "timelineOptions.json", # Replaced in 0.5
|
path / "meta" / "timelineOptions.json", # Replaced in 0.5
|
||||||
path / "meta" / "docMergeOptions.json", # Replaced in 0.5
|
path / "meta" / "docMergeOptions.json", # Replaced in 0.5
|
||||||
path / "meta" / "sessionLogOptions.json", # Replaced in 0.5
|
path / "meta" / "sessionLogOptions.json", # Replaced in 0.5
|
||||||
|
path / "cache" / "prevBuild.json", # Dropped in 2.1 Beta 1
|
||||||
|
path / "cache", # Dropped in 2.1 Beta 1
|
||||||
path / "ToC.json", # Dropped in 1.0 RC 1
|
path / "ToC.json", # Dropped in 1.0 RC 1
|
||||||
]
|
]
|
||||||
for item in remove:
|
for item in remove:
|
||||||
if item.is_file():
|
if item.exists():
|
||||||
try:
|
try:
|
||||||
item.unlink()
|
if item.is_dir():
|
||||||
|
item.rmdir()
|
||||||
|
else:
|
||||||
|
item.unlink()
|
||||||
logger.info("Deleted: %s", item)
|
logger.info("Deleted: %s", item)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning("Failed to delete: %s", item, exc_info=exc)
|
logger.warning("Failed to delete: %s", item, exc_info=exc)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class NWStorage
|
# END Class NWStorage
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ from novelwriter.core.docbuild import NWBuildDocument
|
|||||||
from novelwriter.core.buildsettings import BuildCollection, BuildSettings
|
from novelwriter.core.buildsettings import BuildCollection, BuildSettings
|
||||||
from novelwriter.tools.manussettings import GuiBuildSettings
|
from novelwriter.tools.manussettings import GuiBuildSettings
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
from novelwriter.guimain import GuiMain
|
from novelwriter.guimain import GuiMain
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ from novelwriter.extensions.switchbox import NSwitchBox
|
|||||||
from novelwriter.extensions.configlayout import NConfigLayout, NSimpleLayout
|
from novelwriter.extensions.configlayout import NConfigLayout, NSimpleLayout
|
||||||
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
from novelwriter.guimain import GuiMain
|
from novelwriter.guimain import GuiMain
|
||||||
from novelwriter.gui.theme import GuiTheme
|
from novelwriter.gui.theme import GuiTheme
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mocked import causeOSError
|
|
||||||
from tools import C, buildTestProject, writeFile
|
from tools import C, buildTestProject, writeFile
|
||||||
|
from mocked import causeOSError
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.constants import nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
@@ -33,13 +33,14 @@ from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter
|
|||||||
|
|
||||||
|
|
||||||
class MockProject:
|
class MockProject:
|
||||||
|
"""Test class for projects."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStorage_OpenProjectInPlace(mockGUI, fncPath, mockRnd):
|
def testCoreStorage_OpenProjectInPlace(mockGUI, fncPath, mockRnd):
|
||||||
"""Test opening a project in a folder.
|
"""Test opening a project in a folder."""
|
||||||
"""
|
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
mockRnd.reset()
|
mockRnd.reset()
|
||||||
buildTestProject(theProject, fncPath)
|
buildTestProject(theProject, fncPath)
|
||||||
@@ -60,7 +61,6 @@ def testCoreStorage_OpenProjectInPlace(mockGUI, fncPath, mockRnd):
|
|||||||
assert storage.getXmlWriter() is None
|
assert storage.getXmlWriter() is None
|
||||||
assert bool(storage.getDocument(C.hSceneDoc)) is False
|
assert bool(storage.getDocument(C.hSceneDoc)) is False
|
||||||
assert storage.getMetaFile("file") is None
|
assert storage.getMetaFile("file") is None
|
||||||
assert storage.getCacheFile("file") is None
|
|
||||||
|
|
||||||
# Open project as a new project should fail
|
# Open project as a new project should fail
|
||||||
assert storage.openProjectInPlace(fncPath, newProject=True) is False
|
assert storage.openProjectInPlace(fncPath, newProject=True) is False
|
||||||
@@ -93,7 +93,6 @@ def testCoreStorage_OpenProjectInPlace(mockGUI, fncPath, mockRnd):
|
|||||||
|
|
||||||
# Get paths
|
# Get paths
|
||||||
assert storage.getMetaFile("stuff") == fncPath / "meta" / "stuff"
|
assert storage.getMetaFile("stuff") == fncPath / "meta" / "stuff"
|
||||||
assert storage.getCacheFile("stuff") == fncPath / "cache" / "stuff"
|
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
assert theProject.closeProject() is True
|
assert theProject.closeProject() is True
|
||||||
@@ -104,15 +103,13 @@ def testCoreStorage_OpenProjectInPlace(mockGUI, fncPath, mockRnd):
|
|||||||
assert storage.getXmlWriter() is None
|
assert storage.getXmlWriter() is None
|
||||||
assert bool(storage.getDocument(C.hSceneDoc)) is False
|
assert bool(storage.getDocument(C.hSceneDoc)) is False
|
||||||
assert storage.getMetaFile("file") is None
|
assert storage.getMetaFile("file") is None
|
||||||
assert storage.getCacheFile("file") is None
|
|
||||||
|
|
||||||
# END Test testCoreStorage_ProjectInPlace
|
# END Test testCoreStorage_ProjectInPlace
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStorage_LockFile(monkeypatch, fncPath):
|
def testCoreStorage_LockFile(monkeypatch, fncPath):
|
||||||
"""Test the project lock file.
|
"""Test the project lock file."""
|
||||||
"""
|
|
||||||
monkeypatch.setattr("novelwriter.core.storage.time", lambda: 1000.0)
|
monkeypatch.setattr("novelwriter.core.storage.time", lambda: 1000.0)
|
||||||
|
|
||||||
storage = NWStorage(MockProject())
|
storage = NWStorage(MockProject())
|
||||||
@@ -174,8 +171,7 @@ def testCoreStorage_LockFile(monkeypatch, fncPath):
|
|||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
|
def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
|
||||||
"""Test the project path preparation functions.
|
"""Test the project path preparation functions."""
|
||||||
"""
|
|
||||||
storage = NWStorage(MockProject())
|
storage = NWStorage(MockProject())
|
||||||
assert storage.isOpen() is False
|
assert storage.isOpen() is False
|
||||||
|
|
||||||
@@ -198,8 +194,8 @@ def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
|
|||||||
storage._runtimePath = fncPath
|
storage._runtimePath = fncPath
|
||||||
assert storage._prepareStorage(checkLegacy=False) is True
|
assert storage._prepareStorage(checkLegacy=False) is True
|
||||||
assert (fncPath / "content").exists()
|
assert (fncPath / "content").exists()
|
||||||
assert (fncPath / "cache").exists()
|
|
||||||
assert (fncPath / "meta").exists()
|
assert (fncPath / "meta").exists()
|
||||||
|
assert not (fncPath / "cache").exists() # Removed in 2.1b1
|
||||||
|
|
||||||
# Add a legacy folder
|
# Add a legacy folder
|
||||||
storage._runtimePath = fncPath
|
storage._runtimePath = fncPath
|
||||||
@@ -280,8 +276,10 @@ def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
|
|||||||
fncPath / "meta" / "timelineOptions.json",
|
fncPath / "meta" / "timelineOptions.json",
|
||||||
fncPath / "meta" / "docMergeOptions.json",
|
fncPath / "meta" / "docMergeOptions.json",
|
||||||
fncPath / "meta" / "sessionLogOptions.json",
|
fncPath / "meta" / "sessionLogOptions.json",
|
||||||
|
fncPath / "cache" / "prevBuild.json",
|
||||||
fncPath / "ToC.json",
|
fncPath / "ToC.json",
|
||||||
]
|
]
|
||||||
|
(fncPath / "cache").mkdir()
|
||||||
for depFile in remove:
|
for depFile in remove:
|
||||||
depFile.write_text("foo")
|
depFile.write_text("foo")
|
||||||
assert depFile.exists()
|
assert depFile.exists()
|
||||||
@@ -301,8 +299,7 @@ def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
|
|||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd):
|
def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd):
|
||||||
"""Test making a zip archive of a project.
|
"""Test making a zip archive of a project."""
|
||||||
"""
|
|
||||||
zipFile = tstPaths.tmpDir / "project.zip"
|
zipFile = tstPaths.tmpDir / "project.zip"
|
||||||
|
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
|
|||||||
Reference in New Issue
Block a user