Move the quick read function to the document class where it belongs

This commit is contained in:
Veronica Berglyd Olsen
2024-03-26 12:14:07 +01:00
parent 6a7262b817
commit 147d6b95d7
4 changed files with 46 additions and 25 deletions
+24 -3
View File
@@ -31,7 +31,7 @@ from typing import TYPE_CHECKING
from pathlib import Path from pathlib import Path
from novelwriter.enum import nwItemLayout, nwItemClass from novelwriter.enum import nwItemLayout, nwItemClass
from novelwriter.error import formatException from novelwriter.error import formatException, logException
from novelwriter.common import formatTimeStamp, isHandle from novelwriter.common import formatTimeStamp, isHandle
from novelwriter.core.item import NWItem from novelwriter.core.item import NWItem
@@ -106,7 +106,28 @@ class NWDocument:
return self._item return self._item
## ##
# Class Methods # Static Methods
##
@staticmethod
def quickReadText(content: Path, tHandle: str) -> str:
"""Return the text of a document in a fast and efficient way."""
if (path := content / f"{tHandle}.nwd").is_file():
try:
with open(path, mode="r", encoding="utf-8") as inFile:
line = ""
for _ in range(10):
if not (line := inFile.readline()).startswith(r"%%~"):
break
return line + inFile.read()
except Exception:
logger.error("Cannot read document with handle '%s'", tHandle)
logException()
return ""
return ""
##
# Methods
## ##
def fileExists(self) -> bool: def fileExists(self) -> bool:
@@ -155,7 +176,7 @@ class NWDocument:
try: try:
with open(docPath, mode="r", encoding="utf-8") as inFile: with open(docPath, mode="r", encoding="utf-8") as inFile:
# Check the first <= 10 lines for metadata # Check the first <= 10 lines for metadata
for i in range(10): for _ in range(10):
line = inFile.readline() line = inFile.readline()
if line.startswith(r"%%~"): if line.startswith(r"%%~"):
self._parseMeta(line) self._parseMeta(line)
+2 -15
View File
@@ -289,21 +289,8 @@ class NWStorage:
def getDocumentText(self, tHandle: str) -> str: def getDocumentText(self, tHandle: str) -> str:
"""Return the text of a document in a fast and efficient way.""" """Return the text of a document in a fast and efficient way."""
if ( if isinstance(self._runtimePath, Path):
isinstance(self._runtimePath, Path) return NWDocument.quickReadText(self._runtimePath / "content", tHandle)
and (path := self._runtimePath / "content" / f"{tHandle}.nwd").is_file()
):
try:
with open(path, mode="r", encoding="utf-8") as inFile:
line = ""
for _ in range(10):
if not (line := inFile.readline()).startswith(r"%%~"):
break
return line + inFile.read()
except Exception:
logger.error("Cannot read document with handle '%s'", tHandle)
logException()
return ""
return "" return ""
def scanContent(self) -> list[str]: def scanContent(self) -> list[str]:
+19 -1
View File
@@ -47,6 +47,9 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
assert bool(doc) is False assert bool(doc) is False
assert doc.readDocument() is None assert doc.readDocument() is None
assert doc.fileExists() is False assert doc.fileExists() is False
assert doc.hashError is False
assert doc.createdDate == "Unknown"
assert doc.updatedDate == "Unknown"
# Non-existent handle # Non-existent handle
doc = NWDocument(project, C.hInvalid) doc = NWDocument(project, C.hInvalid)
@@ -76,6 +79,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
# Try to open a new (non-existent) file # Try to open a new (non-existent) file
xHandle = project.newFile("New File", C.hNovelRoot) xHandle = project.newFile("New File", C.hNovelRoot)
assert xHandle is not None
doc = NWDocument(project, xHandle) doc = NWDocument(project, xHandle)
assert bool(doc) is True assert bool(doc) is True
assert repr(doc) == f"<NWDocument handle={xHandle}>" assert repr(doc) == f"<NWDocument handle={xHandle}>"
@@ -93,7 +97,6 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
# Set handle and save # Set handle and save
text = "### Test File\n\nText ...\n\n" text = "### Test File\n\nText ...\n\n"
doc = NWDocument(project, xHandle) doc = NWDocument(project, xHandle)
assert doc.readDocument(xHandle) == "" # type: ignore
assert doc.writeDocument(text) is True assert doc.writeDocument(text) is True
# Save again to ensure temp file and previous file is handled # Save again to ensure temp file and previous file is handled
@@ -145,6 +148,21 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
doc._handle = None doc._handle = None
assert doc.writeDocument(text) is False assert doc.writeDocument(text) is False
# Quick Read
# ==========
contPath = fncPath / "content"
assert NWDocument.quickReadText(contPath, xHandle) == (
"### Test File\n\n"
"Text ...\n\n"
)
# Check read text fallback
assert NWDocument.quickReadText(contPath, "0000000000000") == ""
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert NWDocument.quickReadText(contPath, xHandle) == ""
# Delete Document # Delete Document
# =============== # ===============
+1 -6
View File
@@ -64,6 +64,7 @@ def testCoreStorage_CreateNewProject(mockGUI, fncPath):
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.scanContent() == [] assert storage.scanContent() == []
assert storage.getDocumentText(C.hSceneDoc) == ""
# Cannot prepare a non-empty folder # Cannot prepare a non-empty folder
(fncPath / "foobar.txt").touch() (fncPath / "foobar.txt").touch()
@@ -160,12 +161,6 @@ def testCoreStorage_InitProjectStorage(monkeypatch, mockGUI, fncPath, mockRnd):
# We can directly access the content of a document # We can directly access the content of a document
assert storage.getDocumentText(C.hSceneDoc) == "### New Scene\n\n" assert storage.getDocumentText(C.hSceneDoc) == "### New Scene\n\n"
# Check read text fallback
assert storage.getDocumentText(C.hInvalid) == ""
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert storage.getDocumentText(C.hSceneDoc) == ""
project.closeProject() project.closeProject()
# END Test testCoreStorage_InitProjectStorage # END Test testCoreStorage_InitProjectStorage