Add a quick document read function in the storage class
This commit is contained in:
@@ -27,18 +27,18 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from pathlib import Path
|
||||||
from time import time
|
from time import time
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from pathlib import Path
|
|
||||||
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.error import logException
|
|
||||||
from novelwriter.common import isHandle, minmax
|
from novelwriter.common import isHandle, minmax
|
||||||
from novelwriter.constants import nwFiles
|
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
|
||||||
from novelwriter.core.spellcheck import UserDictionary
|
from novelwriter.core.spellcheck import UserDictionary
|
||||||
|
from novelwriter.error import logException
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma: no cover
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
@@ -287,6 +287,25 @@ class NWStorage:
|
|||||||
return self._runtimePath / "meta" / fileName
|
return self._runtimePath / "meta" / fileName
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def getDocumentText(self, tHandle: str) -> str:
|
||||||
|
"""Return the text of a document in a fast and efficient way."""
|
||||||
|
if (
|
||||||
|
isinstance(self._runtimePath, Path)
|
||||||
|
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 ""
|
||||||
|
|
||||||
def scanContent(self) -> list[str]:
|
def scanContent(self) -> list[str]:
|
||||||
"""Scan the content folder and return the handle of all files
|
"""Scan the content folder and return the handle of all files
|
||||||
found in it. Files that do not match the pattern are ignored.
|
found in it. Files that do not match the pattern are ignored.
|
||||||
|
|||||||
@@ -26,15 +26,15 @@ import pytest
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from tools import C, buildTestProject
|
|
||||||
from mocked import causeOSError
|
from mocked import causeOSError
|
||||||
|
from tools import C, buildTestProject
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.constants import nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
from novelwriter.core.project import NWProject
|
|
||||||
from novelwriter.core.storage import NWStorage, NWStorageOpen, NWStorageCreate, _LegacyStorage
|
|
||||||
from novelwriter.core.document import NWDocument
|
from novelwriter.core.document import NWDocument
|
||||||
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter
|
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter
|
||||||
|
from novelwriter.core.storage import NWStorage, NWStorageOpen, NWStorageCreate, _LegacyStorage
|
||||||
|
|
||||||
|
|
||||||
class MockProject:
|
class MockProject:
|
||||||
@@ -85,7 +85,7 @@ def testCoreStorage_CreateNewProject(mockGUI, fncPath):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStorage_InitProjectStorage(mockGUI, fncPath, mockRnd):
|
def testCoreStorage_InitProjectStorage(monkeypatch, mockGUI, fncPath, mockRnd):
|
||||||
"""Test initialising a project in a folder."""
|
"""Test initialising a project in a folder."""
|
||||||
project = NWProject()
|
project = NWProject()
|
||||||
|
|
||||||
@@ -157,6 +157,15 @@ def testCoreStorage_InitProjectStorage(mockGUI, fncPath, mockRnd):
|
|||||||
assert isinstance(storage.getDocument(C.hSceneDoc), NWDocument)
|
assert isinstance(storage.getDocument(C.hSceneDoc), NWDocument)
|
||||||
assert repr(storage.getDocument(C.hSceneDoc)) == f"<NWDocument handle={C.hSceneDoc}>"
|
assert repr(storage.getDocument(C.hSceneDoc)) == f"<NWDocument handle={C.hSceneDoc}>"
|
||||||
|
|
||||||
|
# We can directly access the content of a document
|
||||||
|
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