Move the quick read function to the document class where it belongs
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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]:
|
||||||
|
|||||||
@@ -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
|
||||||
# ===============
|
# ===============
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user